1911 |
19 Mar 13 |
nicklas |
1 |
package net.sf.basedb.reggie.servlet; |
1911 |
19 Mar 13 |
nicklas |
2 |
|
1911 |
19 Mar 13 |
nicklas |
3 |
import java.io.IOException; |
1959 |
03 May 13 |
nicklas |
4 |
import java.util.Arrays; |
1970 |
08 May 13 |
nicklas |
5 |
import java.util.Date; |
1911 |
19 Mar 13 |
nicklas |
6 |
import java.util.List; |
1911 |
19 Mar 13 |
nicklas |
7 |
|
1911 |
19 Mar 13 |
nicklas |
8 |
import javax.servlet.ServletException; |
1911 |
19 Mar 13 |
nicklas |
9 |
import javax.servlet.http.HttpServlet; |
1911 |
19 Mar 13 |
nicklas |
10 |
import javax.servlet.http.HttpServletRequest; |
1911 |
19 Mar 13 |
nicklas |
11 |
import javax.servlet.http.HttpServletResponse; |
1911 |
19 Mar 13 |
nicklas |
12 |
|
1911 |
19 Mar 13 |
nicklas |
13 |
import org.json.simple.JSONArray; |
1911 |
19 Mar 13 |
nicklas |
14 |
import org.json.simple.JSONObject; |
1911 |
19 Mar 13 |
nicklas |
15 |
|
2040 |
03 Oct 13 |
nicklas |
16 |
import net.sf.basedb.clients.web.util.HTML; |
2141 |
18 Nov 13 |
nicklas |
17 |
import net.sf.basedb.core.AnyToAny; |
1934 |
17 Apr 13 |
nicklas |
18 |
import net.sf.basedb.core.BioMaterialEvent; |
1934 |
17 Apr 13 |
nicklas |
19 |
import net.sf.basedb.core.BioMaterialEventSource; |
3247 |
14 Apr 15 |
nicklas |
20 |
import net.sf.basedb.core.ItemList; |
1911 |
19 Mar 13 |
nicklas |
21 |
import net.sf.basedb.core.BioPlate; |
2104 |
25 Oct 13 |
nicklas |
22 |
import net.sf.basedb.core.BioWell; |
1911 |
19 Mar 13 |
nicklas |
23 |
import net.sf.basedb.core.DbControl; |
1911 |
19 Mar 13 |
nicklas |
24 |
import net.sf.basedb.core.Extract; |
1911 |
19 Mar 13 |
nicklas |
25 |
import net.sf.basedb.core.ItemQuery; |
1934 |
17 Apr 13 |
nicklas |
26 |
import net.sf.basedb.core.ItemSubtype; |
1970 |
08 May 13 |
nicklas |
27 |
import net.sf.basedb.core.Protocol; |
1911 |
19 Mar 13 |
nicklas |
28 |
import net.sf.basedb.core.SessionControl; |
1959 |
03 May 13 |
nicklas |
29 |
import net.sf.basedb.core.Type; |
1911 |
19 Mar 13 |
nicklas |
30 |
import net.sf.basedb.core.query.Annotations; |
1911 |
19 Mar 13 |
nicklas |
31 |
import net.sf.basedb.core.query.Expressions; |
1911 |
19 Mar 13 |
nicklas |
32 |
import net.sf.basedb.core.query.Hql; |
1911 |
19 Mar 13 |
nicklas |
33 |
import net.sf.basedb.core.query.Orders; |
1911 |
19 Mar 13 |
nicklas |
34 |
import net.sf.basedb.core.query.Restrictions; |
3762 |
19 Feb 16 |
nicklas |
35 |
import net.sf.basedb.core.snapshot.SnapshotManager; |
2598 |
22 Aug 14 |
nicklas |
36 |
import net.sf.basedb.reggie.JsonUtil; |
1911 |
19 Mar 13 |
nicklas |
37 |
import net.sf.basedb.reggie.Reggie; |
5384 |
26 Apr 19 |
nicklas |
38 |
import net.sf.basedb.reggie.activity.ActivityDef; |
3059 |
19 Dec 14 |
nicklas |
39 |
import net.sf.basedb.reggie.counter.CounterService; |
1911 |
19 Mar 13 |
nicklas |
40 |
import net.sf.basedb.reggie.dao.Annotationtype; |
1987 |
23 May 13 |
nicklas |
41 |
import net.sf.basedb.reggie.dao.BiomaterialList; |
1911 |
19 Mar 13 |
nicklas |
42 |
import net.sf.basedb.reggie.dao.BioplateType; |
1911 |
19 Mar 13 |
nicklas |
43 |
import net.sf.basedb.reggie.dao.Library; |
5434 |
17 May 19 |
nicklas |
44 |
import net.sf.basedb.reggie.dao.Pipeline; |
1934 |
17 Apr 13 |
nicklas |
45 |
import net.sf.basedb.reggie.dao.PooledLibrary; |
1911 |
19 Mar 13 |
nicklas |
46 |
import net.sf.basedb.reggie.dao.ReactionPlate; |
4897 |
10 Jul 18 |
nicklas |
47 |
import net.sf.basedb.reggie.dao.ReggieItem; |
2161 |
09 Dec 13 |
nicklas |
48 |
import net.sf.basedb.reggie.dao.ReggieRole; |
1987 |
23 May 13 |
nicklas |
49 |
import net.sf.basedb.reggie.dao.Rna; |
1934 |
17 Apr 13 |
nicklas |
50 |
import net.sf.basedb.reggie.dao.Subtype; |
1911 |
19 Mar 13 |
nicklas |
51 |
import net.sf.basedb.util.Values; |
1911 |
19 Mar 13 |
nicklas |
52 |
import net.sf.basedb.util.error.ThrowableUtil; |
1911 |
19 Mar 13 |
nicklas |
53 |
|
1911 |
19 Mar 13 |
nicklas |
54 |
|
1911 |
19 Mar 13 |
nicklas |
55 |
public class PoolServlet |
1911 |
19 Mar 13 |
nicklas |
56 |
extends HttpServlet |
1911 |
19 Mar 13 |
nicklas |
57 |
{ |
1911 |
19 Mar 13 |
nicklas |
58 |
|
1959 |
03 May 13 |
nicklas |
59 |
/** |
3107 |
27 Jan 15 |
nicklas |
Default target molarity in nM when mixing libraries. |
1959 |
03 May 13 |
nicklas |
61 |
*/ |
3107 |
27 Jan 15 |
nicklas |
62 |
private static final float DEFAULT_TARGET_MOLARITY_IN_POOL = 2f; |
1911 |
19 Mar 13 |
nicklas |
63 |
|
1959 |
03 May 13 |
nicklas |
64 |
/** |
3107 |
27 Jan 15 |
nicklas |
Default volume in µl to use from each lib in the pool |
1959 |
03 May 13 |
nicklas |
66 |
*/ |
2025 |
25 Sep 13 |
nicklas |
67 |
private static final float DEFAULT_TARGET_VOLUME_IN_POOL_PER_LIB = 5f; |
1959 |
03 May 13 |
nicklas |
68 |
|
1959 |
03 May 13 |
nicklas |
69 |
/** |
1959 |
03 May 13 |
nicklas |
If the volume to use from the lib is lower than this limit, |
1959 |
03 May 13 |
nicklas |
we mix a larger amount to begin with, but only use the same target volume |
1959 |
03 May 13 |
nicklas |
(the extra is left in a temporary plate). |
1959 |
03 May 13 |
nicklas |
73 |
*/ |
1974 |
14 May 13 |
nicklas |
74 |
private static final float LIMIT_FOR_EXTRA_LARGE_MIX = 1f; |
1959 |
03 May 13 |
nicklas |
75 |
|
1959 |
03 May 13 |
nicklas |
76 |
/** |
1975 |
15 May 13 |
nicklas |
Factor to apply when making an extra large mix. |
1975 |
15 May 13 |
nicklas |
In the common case 2.0 means mixing 10µl instead of 5µl. But, only |
1959 |
03 May 13 |
nicklas |
5µl is used for the pool and the remaining 5µl is saved in a temporary |
1959 |
03 May 13 |
nicklas |
location. |
1959 |
03 May 13 |
nicklas |
81 |
*/ |
1975 |
15 May 13 |
nicklas |
82 |
private static final float EXTRA_LARGE_MIX_FACTOR = 2.0f; |
1959 |
03 May 13 |
nicklas |
83 |
|
1959 |
03 May 13 |
nicklas |
84 |
|
1911 |
19 Mar 13 |
nicklas |
85 |
private static final long serialVersionUID = -5652847260721336320L; |
1911 |
19 Mar 13 |
nicklas |
86 |
|
1911 |
19 Mar 13 |
nicklas |
87 |
public PoolServlet() |
1911 |
19 Mar 13 |
nicklas |
88 |
{} |
1911 |
19 Mar 13 |
nicklas |
89 |
|
1911 |
19 Mar 13 |
nicklas |
90 |
@Override |
1911 |
19 Mar 13 |
nicklas |
91 |
protected void doGet(HttpServletRequest req, HttpServletResponse resp) |
1911 |
19 Mar 13 |
nicklas |
92 |
throws ServletException, IOException |
1911 |
19 Mar 13 |
nicklas |
93 |
{ |
1911 |
19 Mar 13 |
nicklas |
94 |
String cmd = req.getParameter("cmd"); |
2598 |
22 Aug 14 |
nicklas |
95 |
JsonUtil.setJsonResponseHeaders(resp); |
1911 |
19 Mar 13 |
nicklas |
96 |
|
1911 |
19 Mar 13 |
nicklas |
97 |
JSONObject json = new JSONObject(); |
1911 |
19 Mar 13 |
nicklas |
98 |
json.put("status", "ok"); |
1911 |
19 Mar 13 |
nicklas |
99 |
|
3975 |
26 May 16 |
nicklas |
100 |
final SessionControl sc = Reggie.getSessionControl(req); |
1911 |
19 Mar 13 |
nicklas |
101 |
DbControl dc = null; |
1911 |
19 Mar 13 |
nicklas |
102 |
try |
1911 |
19 Mar 13 |
nicklas |
103 |
{ |
3059 |
19 Dec 14 |
nicklas |
104 |
if ("GetLibraryPlatesForPooling".equals(cmd)) |
1911 |
19 Mar 13 |
nicklas |
105 |
{ |
1911 |
19 Mar 13 |
nicklas |
106 |
/* |
1911 |
19 Mar 13 |
nicklas |
Find all Library bioplates for pooling. |
1911 |
19 Mar 13 |
nicklas |
108 |
*/ |
6333 |
15 Jun 21 |
nicklas |
109 |
dc = sc.newDbControl(":Create pooled libraries"); |
1952 |
24 Apr 13 |
nicklas |
110 |
|
1952 |
24 Apr 13 |
nicklas |
// Find Library items with remaining quantity==original quantity |
1952 |
24 Apr 13 |
nicklas |
112 |
ItemQuery<Extract> libQuery = Extract.getQuery(); |
1952 |
24 Apr 13 |
nicklas |
113 |
libQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT); |
1952 |
24 Apr 13 |
nicklas |
114 |
Subtype.LIBRARY.addFilter(dc, libQuery); |
2032 |
02 Oct 13 |
nicklas |
115 |
libQuery.restrict(Restrictions.neq(Hql.property("originalQuantity"), null)); |
2032 |
02 Oct 13 |
nicklas |
116 |
libQuery.restrict(Restrictions.eq(Hql.property("originalQuantity"), Hql.property("remainingQuantity"))); |
1987 |
23 May 13 |
nicklas |
// Must NOT have a Flag annotation |
1987 |
23 May 13 |
nicklas |
118 |
libQuery.join(Annotations.leftJoin(null, Annotationtype.FLAG.load(dc), "flg")); |
1987 |
23 May 13 |
nicklas |
119 |
libQuery.restrict(Restrictions.eq(Hql.alias("flg"), null)); |
1952 |
24 Apr 13 |
nicklas |
120 |
|
1911 |
19 Mar 13 |
nicklas |
121 |
ItemQuery<BioPlate> query = BioPlate.getQuery(); |
1911 |
19 Mar 13 |
nicklas |
122 |
query.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT); |
5883 |
26 Mar 20 |
nicklas |
// Only Library bioplates that are not destroyed |
5883 |
26 Mar 20 |
nicklas |
124 |
BioplateType.LIBRARY.addFilter(dc, query, true); |
3309 |
06 May 15 |
nicklas |
125 |
|
1911 |
19 Mar 13 |
nicklas |
// Must have a PLATE_PROCESS_RESULT=Success annotation |
1911 |
19 Mar 13 |
nicklas |
127 |
query.join(Annotations.leftJoin(null, Annotationtype.PLATE_PROCESS_RESULT.load(dc), "ppr")); |
1911 |
19 Mar 13 |
nicklas |
128 |
query.restrict(Restrictions.eq(Hql.alias("ppr"), Expressions.string(ReactionPlate.PROCESS_SUCCESSFUL))); |
1911 |
19 Mar 13 |
nicklas |
129 |
|
1952 |
24 Apr 13 |
nicklas |
130 |
query.join(Hql.innerJoin("bioWells", "bw")); |
1952 |
24 Apr 13 |
nicklas |
131 |
query.join(Hql.innerJoin("bw", "bioMaterial", "bm")); |
1952 |
24 Apr 13 |
nicklas |
132 |
|
1952 |
24 Apr 13 |
nicklas |
133 |
query.restrict(Restrictions.eq(Hql.alias("bm"), Expressions.any(libQuery))); |
2907 |
07 Nov 14 |
nicklas |
134 |
query.order(Orders.asc(Hql.property("name"))); |
1952 |
24 Apr 13 |
nicklas |
135 |
query.setDistinct(true); |
1952 |
24 Apr 13 |
nicklas |
136 |
|
1911 |
19 Mar 13 |
nicklas |
137 |
List<BioPlate> plates = query.list(dc); |
1911 |
19 Mar 13 |
nicklas |
138 |
JSONArray jsonPlates = new JSONArray(); |
1911 |
19 Mar 13 |
nicklas |
139 |
for (BioPlate plate : plates) |
1911 |
19 Mar 13 |
nicklas |
140 |
{ |
1959 |
03 May 13 |
nicklas |
141 |
jsonPlates.add(getJSONForLibPlate(dc, plate)); |
1911 |
19 Mar 13 |
nicklas |
142 |
} |
1911 |
19 Mar 13 |
nicklas |
143 |
json.put("bioplates", jsonPlates); |
1911 |
19 Mar 13 |
nicklas |
144 |
} |
1959 |
03 May 13 |
nicklas |
145 |
else if ("GetLibPlateInfo".equals(cmd)) |
1959 |
03 May 13 |
nicklas |
146 |
{ |
1959 |
03 May 13 |
nicklas |
// Load information about a single library bioplate |
1959 |
03 May 13 |
nicklas |
148 |
int libPlateId = Values.getInt(req.getParameter("bioplate")); |
6333 |
15 Jun 21 |
nicklas |
149 |
dc = sc.newDbControl(":Create pooled libraries"); |
1959 |
03 May 13 |
nicklas |
150 |
BioPlate libPlate = BioPlate.getById(dc, libPlateId); |
1959 |
03 May 13 |
nicklas |
151 |
json.put("libPlate", getJSONForLibPlate(dc, libPlate)); |
1959 |
03 May 13 |
nicklas |
152 |
|
1959 |
03 May 13 |
nicklas |
153 |
} |
2137 |
13 Nov 13 |
nicklas |
154 |
else if ("GetLibraryInfo".equals(cmd)) |
2137 |
13 Nov 13 |
nicklas |
155 |
{ |
2805 |
15 Oct 14 |
nicklas |
// Get information about a list of libraries |
2805 |
15 Oct 14 |
nicklas |
157 |
Integer[] libId = Values.getInt(req.getParameter("libraries").split(",")); |
6333 |
15 Jun 21 |
nicklas |
158 |
dc = sc.newDbControl(":Create pooled libraries"); |
3762 |
19 Feb 16 |
nicklas |
159 |
SnapshotManager manager = new SnapshotManager(); |
2137 |
13 Nov 13 |
nicklas |
160 |
|
2805 |
15 Oct 14 |
nicklas |
161 |
JSONArray jsonLibs = new JSONArray(); |
2805 |
15 Oct 14 |
nicklas |
162 |
for (int i = 0; i < libId.length; i++) |
2805 |
15 Oct 14 |
nicklas |
163 |
{ |
2805 |
15 Oct 14 |
nicklas |
164 |
Library lib = Library.getById(dc, libId[i]); |
2805 |
15 Oct 14 |
nicklas |
165 |
lib.loadBioPlateLocation(); |
2805 |
15 Oct 14 |
nicklas |
166 |
addPoolingCalculationsToLib(dc, lib, null); |
2805 |
15 Oct 14 |
nicklas |
167 |
lib.setAnnotation("comment", lib.getExtract().getDescription()); |
5436 |
17 May 19 |
nicklas |
168 |
lib.loadAnnotations(dc, "pipeline", Annotationtype.PIPELINE, null); |
4984 |
27 Sep 18 |
nicklas |
169 |
lib.loadDoNotUseAnnotations(dc, manager); |
3762 |
19 Feb 16 |
nicklas |
170 |
Rna rna = lib.getRna(dc, true); |
5436 |
17 May 19 |
nicklas |
171 |
if (rna != null) lib.setAnnotation("specimen", rna.loadYellowLabelInfo(dc, manager)); |
2805 |
15 Oct 14 |
nicklas |
172 |
jsonLibs.add(lib.asJSONObject()); |
2805 |
15 Oct 14 |
nicklas |
173 |
} |
2805 |
15 Oct 14 |
nicklas |
174 |
json.put("libraries", jsonLibs); |
2137 |
13 Nov 13 |
nicklas |
175 |
|
2137 |
13 Nov 13 |
nicklas |
176 |
} |
1911 |
19 Mar 13 |
nicklas |
177 |
else if ("GetLibraryInfoForPlate".equals(cmd)) |
1911 |
19 Mar 13 |
nicklas |
178 |
{ |
1959 |
03 May 13 |
nicklas |
// Get information about libraries on a single library bioplate |
1959 |
03 May 13 |
nicklas |
// Calculate mixing volumes for pooling using the target molarity |
1959 |
03 May 13 |
nicklas |
// and volumes |
1911 |
19 Mar 13 |
nicklas |
182 |
int libPlateId = Values.getInt(req.getParameter("bioplate")); |
6333 |
15 Jun 21 |
nicklas |
183 |
dc = sc.newDbControl(":Create pooled libraries"); |
3762 |
19 Feb 16 |
nicklas |
184 |
SnapshotManager manager = new SnapshotManager(); |
1911 |
19 Mar 13 |
nicklas |
185 |
|
1911 |
19 Mar 13 |
nicklas |
186 |
BioPlate libPlate = BioPlate.getById(dc, libPlateId); |
1911 |
19 Mar 13 |
nicklas |
187 |
|
1911 |
19 Mar 13 |
nicklas |
188 |
ItemQuery<Extract> query = Extract.getQuery(); |
1911 |
19 Mar 13 |
nicklas |
189 |
query.join(Hql.innerJoin(null, "bioWell", "bw", true)); |
1911 |
19 Mar 13 |
nicklas |
190 |
query.join(Hql.innerJoin("bw", "bioPlate", "bp")); |
1911 |
19 Mar 13 |
nicklas |
191 |
query.restrict(Restrictions.eq(Hql.alias("bp"), Hql.entity(libPlate))); |
2032 |
02 Oct 13 |
nicklas |
192 |
query.restrict(Restrictions.neq(Hql.property("originalQuantity"), null)); // Get rid of Stratagene, etc. |
1911 |
19 Mar 13 |
nicklas |
193 |
query.order(Orders.asc(Hql.property("bw", "column"))); |
1911 |
19 Mar 13 |
nicklas |
194 |
query.order(Orders.asc(Hql.property("bw", "row"))); |
1911 |
19 Mar 13 |
nicklas |
195 |
|
1911 |
19 Mar 13 |
nicklas |
196 |
List<Library> libs = Library.toList(query.list(dc)); |
1911 |
19 Mar 13 |
nicklas |
197 |
|
1911 |
19 Mar 13 |
nicklas |
198 |
JSONArray jsonLibs = new JSONArray(); |
1911 |
19 Mar 13 |
nicklas |
199 |
for (Library lib : libs) |
1911 |
19 Mar 13 |
nicklas |
200 |
{ |
1911 |
19 Mar 13 |
nicklas |
201 |
lib.loadBioPlateLocation(); |
2137 |
13 Nov 13 |
nicklas |
202 |
addPoolingCalculationsToLib(dc, lib, null); |
1987 |
23 May 13 |
nicklas |
203 |
lib.setAnnotation("comment", lib.getExtract().getDescription()); |
3762 |
19 Feb 16 |
nicklas |
204 |
Rna rna = lib.getRna(dc, true); |
3762 |
19 Feb 16 |
nicklas |
205 |
lib.setAnnotation("specimen", rna.loadYellowLabelInfo(dc, manager)); |
1911 |
19 Mar 13 |
nicklas |
206 |
jsonLibs.add(lib.asJSONObject()); |
1911 |
19 Mar 13 |
nicklas |
207 |
} |
1911 |
19 Mar 13 |
nicklas |
208 |
|
1911 |
19 Mar 13 |
nicklas |
209 |
json.put("libraries", jsonLibs); |
1959 |
03 May 13 |
nicklas |
210 |
|
1959 |
03 May 13 |
nicklas |
// Send some info about the target molarity and volume used in the pooling calculations |
1959 |
03 May 13 |
nicklas |
// back to the client for presentation purposes |
1959 |
03 May 13 |
nicklas |
213 |
JSONObject poolInfo = new JSONObject(); |
3107 |
27 Jan 15 |
nicklas |
214 |
poolInfo.put("targetMolarity", DEFAULT_TARGET_MOLARITY_IN_POOL); |
2025 |
25 Sep 13 |
nicklas |
215 |
poolInfo.put("targetVolumePerLib", DEFAULT_TARGET_VOLUME_IN_POOL_PER_LIB); |
2025 |
25 Sep 13 |
nicklas |
216 |
poolInfo.put("extraLargeMixFactor", EXTRA_LARGE_MIX_FACTOR); |
2025 |
25 Sep 13 |
nicklas |
217 |
poolInfo.put("limitForExtraLargeMix", LIMIT_FOR_EXTRA_LARGE_MIX); |
1959 |
03 May 13 |
nicklas |
218 |
json.put("poolInfo", poolInfo); |
1911 |
19 Mar 13 |
nicklas |
219 |
} |
1934 |
17 Apr 13 |
nicklas |
220 |
else if ("GetNextAutoGeneratedPoolNames".equals(cmd)) |
1934 |
17 Apr 13 |
nicklas |
221 |
{ |
1959 |
03 May 13 |
nicklas |
// Get the pool names for the next number of pools to create |
6333 |
15 Jun 21 |
nicklas |
223 |
dc = sc.newDbControl(":Create pooled libraries"); |
1934 |
17 Apr 13 |
nicklas |
224 |
int numNames = Values.getInt(req.getParameter("numNames")); |
4883 |
04 Jul 18 |
nicklas |
225 |
json.put("names", PooledLibrary.getNextNames(dc, numNames)); |
2137 |
13 Nov 13 |
nicklas |
226 |
JSONObject poolInfo = new JSONObject(); |
3107 |
27 Jan 15 |
nicklas |
227 |
poolInfo.put("targetMolarity", DEFAULT_TARGET_MOLARITY_IN_POOL); |
2137 |
13 Nov 13 |
nicklas |
228 |
poolInfo.put("targetVolumePerLib", DEFAULT_TARGET_VOLUME_IN_POOL_PER_LIB); |
2137 |
13 Nov 13 |
nicklas |
229 |
poolInfo.put("extraLargeMixFactor", EXTRA_LARGE_MIX_FACTOR); |
2137 |
13 Nov 13 |
nicklas |
230 |
poolInfo.put("limitForExtraLargeMix", LIMIT_FOR_EXTRA_LARGE_MIX); |
2137 |
13 Nov 13 |
nicklas |
231 |
json.put("poolInfo", poolInfo); |
1934 |
17 Apr 13 |
nicklas |
232 |
} |
1959 |
03 May 13 |
nicklas |
233 |
else if ("GetUnprocessedPools".equals(cmd)) |
1959 |
03 May 13 |
nicklas |
234 |
{ |
1959 |
03 May 13 |
nicklas |
// Get all PooledLibrary items with no creation date |
6333 |
15 Jun 21 |
nicklas |
236 |
dc = sc.newDbControl(":Register pooled libraries"); |
1959 |
03 May 13 |
nicklas |
237 |
|
5434 |
17 May 19 |
nicklas |
238 |
List<PooledLibrary> pools = PooledLibrary.findUnprocessedPools(dc, Pipeline.RNA_SEQ); |
1959 |
03 May 13 |
nicklas |
239 |
JSONArray jsonPools = new JSONArray(); |
1959 |
03 May 13 |
nicklas |
240 |
for (PooledLibrary pool : pools) |
1959 |
03 May 13 |
nicklas |
241 |
{ |
2091 |
21 Oct 13 |
nicklas |
242 |
pool.loadLibPlates(dc); |
1959 |
03 May 13 |
nicklas |
243 |
pool.loadAnnotations(dc, "molarity", Annotationtype.POOL_MOLARITY, null); |
1959 |
03 May 13 |
nicklas |
244 |
pool.loadAnnotations(dc, "conc", Annotationtype.POOL_CONC, null); |
2141 |
18 Nov 13 |
nicklas |
245 |
pool.loadAnnotations(dc, "isManual", Annotationtype.POOL_IS_MANUAL, null); |
1959 |
03 May 13 |
nicklas |
246 |
pool.setAnnotation("remainingQuantity", pool.getExtract().getRemainingQuantity()); |
2044 |
07 Oct 13 |
nicklas |
247 |
pool.setAnnotation("comments", pool.getExtract().getDescription()); |
1959 |
03 May 13 |
nicklas |
248 |
jsonPools.add(pool.asJSONObject()); |
1959 |
03 May 13 |
nicklas |
249 |
} |
1959 |
03 May 13 |
nicklas |
250 |
json.put("pools", jsonPools); |
1959 |
03 May 13 |
nicklas |
251 |
} |
1959 |
03 May 13 |
nicklas |
252 |
|
1959 |
03 May 13 |
nicklas |
253 |
else if ("GetLibraryInfoForPools".equals(cmd)) |
1959 |
03 May 13 |
nicklas |
254 |
{ |
1959 |
03 May 13 |
nicklas |
// Get information about the libraries that are pooled in the given PooledLibrary items |
6333 |
15 Jun 21 |
nicklas |
256 |
dc = sc.newDbControl(":Lab protocols for pooling"); |
3762 |
19 Feb 16 |
nicklas |
257 |
SnapshotManager manager = new SnapshotManager(); |
1959 |
03 May 13 |
nicklas |
258 |
String[] tmp = req.getParameter("pools").split(","); |
1959 |
03 May 13 |
nicklas |
259 |
List<Integer> poolIds = Arrays.asList(Values.getInt(tmp)); |
1959 |
03 May 13 |
nicklas |
260 |
|
1959 |
03 May 13 |
nicklas |
261 |
ItemQuery<Extract> poolQuery = Extract.getQuery(); |
1959 |
03 May 13 |
nicklas |
262 |
poolQuery.restrict(Restrictions.in(Hql.property("id"), Expressions.parameter("pools", Type.INT))); |
1959 |
03 May 13 |
nicklas |
263 |
poolQuery.setParameter("pools", poolIds, Type.INT); |
1959 |
03 May 13 |
nicklas |
264 |
|
1959 |
03 May 13 |
nicklas |
265 |
List<PooledLibrary> pools = PooledLibrary.toList(poolQuery.list(dc)); |
1959 |
03 May 13 |
nicklas |
266 |
|
1959 |
03 May 13 |
nicklas |
267 |
JSONArray jsonPools = new JSONArray(); |
1959 |
03 May 13 |
nicklas |
268 |
for (PooledLibrary pool : pools) |
1959 |
03 May 13 |
nicklas |
269 |
{ |
1959 |
03 May 13 |
nicklas |
270 |
BioMaterialEvent poolCreationEvent = pool.getExtract().getCreationEvent(); |
1959 |
03 May 13 |
nicklas |
271 |
List<Library> libs = Library.getByPool(dc, pool); |
1959 |
03 May 13 |
nicklas |
272 |
JSONArray jsonLibs = new JSONArray(); |
1959 |
03 May 13 |
nicklas |
273 |
for (Library lib : libs) |
1959 |
03 May 13 |
nicklas |
274 |
{ |
1959 |
03 May 13 |
nicklas |
275 |
lib.loadBioPlateLocation(); |
2137 |
13 Nov 13 |
nicklas |
276 |
addPoolingCalculationsToLib(dc, lib, pool); |
1987 |
23 May 13 |
nicklas |
277 |
lib.setAnnotation("comment", lib.getExtract().getDescription()); |
3762 |
19 Feb 16 |
nicklas |
278 |
Rna rna = lib.getRna(dc, true); |
3762 |
19 Feb 16 |
nicklas |
279 |
lib.setAnnotation("specimen", rna.loadYellowLabelInfo(dc, manager)); |
1959 |
03 May 13 |
nicklas |
280 |
jsonLibs.add(lib.asJSONObject()); |
1959 |
03 May 13 |
nicklas |
281 |
} |
1959 |
03 May 13 |
nicklas |
282 |
|
1959 |
03 May 13 |
nicklas |
283 |
pool.setAnnotation("libraries", jsonLibs); |
1959 |
03 May 13 |
nicklas |
284 |
pool.loadAnnotations(dc, "molarity", Annotationtype.POOL_MOLARITY, null); |
1959 |
03 May 13 |
nicklas |
285 |
pool.loadAnnotations(dc, "conc", Annotationtype.POOL_CONC, null); |
2040 |
03 Oct 13 |
nicklas |
286 |
pool.setAnnotation("comments", HTML.niceFormat(pool.getExtract().getDescription())); |
2027 |
30 Sep 13 |
nicklas |
287 |
|
2027 |
30 Sep 13 |
nicklas |
288 |
Float targetVolumePerLib = (Float)Annotationtype.POOL_TARGET_VOLUME_PER_LIB.getAnnotationValue(dc, pool.getExtract()); |
2027 |
30 Sep 13 |
nicklas |
289 |
if (targetVolumePerLib == null) targetVolumePerLib = DEFAULT_TARGET_VOLUME_IN_POOL_PER_LIB; |
2027 |
30 Sep 13 |
nicklas |
290 |
pool.setAnnotation("targetVolumePerLib", targetVolumePerLib); |
2140 |
18 Nov 13 |
nicklas |
291 |
Float targetPoolMolarity = (Float)Annotationtype.POOL_TARGET_MOLARITY.getAnnotationValue(dc, pool.getExtract()); |
3107 |
27 Jan 15 |
nicklas |
292 |
if (targetPoolMolarity == null) targetPoolMolarity = DEFAULT_TARGET_MOLARITY_IN_POOL; |
2140 |
18 Nov 13 |
nicklas |
293 |
pool.setAnnotation("targetPoolMolarity", targetPoolMolarity); |
2041 |
04 Oct 13 |
nicklas |
294 |
String mixingStrategy = (String)Annotationtype.POOL_MIXING_STRATEGY.getAnnotationValue(dc, pool.getExtract()); |
2041 |
04 Oct 13 |
nicklas |
295 |
if (mixingStrategy == null) mixingStrategy = PooledLibrary.MIXING_STRATEGY_FIXED; |
2041 |
04 Oct 13 |
nicklas |
296 |
pool.setAnnotation("mixingStrategy", mixingStrategy); |
2041 |
04 Oct 13 |
nicklas |
297 |
|
1959 |
03 May 13 |
nicklas |
298 |
pool.setAnnotation("originalQuantity", pool.getExtract().getOriginalQuantity()); |
1959 |
03 May 13 |
nicklas |
299 |
jsonPools.add(pool.asJSONObject()); |
1959 |
03 May 13 |
nicklas |
300 |
} |
1959 |
03 May 13 |
nicklas |
301 |
json.put("pools", jsonPools); |
1959 |
03 May 13 |
nicklas |
302 |
|
1959 |
03 May 13 |
nicklas |
303 |
JSONObject poolInfo = new JSONObject(); |
2025 |
25 Sep 13 |
nicklas |
304 |
poolInfo.put("extraLargeMixFactor", EXTRA_LARGE_MIX_FACTOR); |
2025 |
25 Sep 13 |
nicklas |
305 |
poolInfo.put("limitForExtraLargeMix", LIMIT_FOR_EXTRA_LARGE_MIX); |
1959 |
03 May 13 |
nicklas |
306 |
json.put("poolInfo", poolInfo); |
1959 |
03 May 13 |
nicklas |
307 |
} |
1911 |
19 Mar 13 |
nicklas |
308 |
} |
1911 |
19 Mar 13 |
nicklas |
309 |
catch (Throwable t) |
1911 |
19 Mar 13 |
nicklas |
310 |
{ |
1911 |
19 Mar 13 |
nicklas |
311 |
t.printStackTrace(); |
1911 |
19 Mar 13 |
nicklas |
312 |
json.clear(); |
1911 |
19 Mar 13 |
nicklas |
313 |
json.put("status", "error"); |
1911 |
19 Mar 13 |
nicklas |
314 |
json.put("message", t.getMessage()); |
1911 |
19 Mar 13 |
nicklas |
315 |
json.put("stacktrace", ThrowableUtil.stackTraceToString(t)); |
1911 |
19 Mar 13 |
nicklas |
316 |
} |
1911 |
19 Mar 13 |
nicklas |
317 |
finally |
1911 |
19 Mar 13 |
nicklas |
318 |
{ |
1911 |
19 Mar 13 |
nicklas |
319 |
if (dc != null) dc.close(); |
1911 |
19 Mar 13 |
nicklas |
320 |
json.writeJSONString(resp.getWriter()); |
1911 |
19 Mar 13 |
nicklas |
321 |
} |
1911 |
19 Mar 13 |
nicklas |
322 |
|
1911 |
19 Mar 13 |
nicklas |
323 |
} |
1911 |
19 Mar 13 |
nicklas |
324 |
|
1911 |
19 Mar 13 |
nicklas |
325 |
@Override |
1911 |
19 Mar 13 |
nicklas |
326 |
protected void doPost(HttpServletRequest req, HttpServletResponse resp) |
1911 |
19 Mar 13 |
nicklas |
327 |
throws ServletException, IOException |
1911 |
19 Mar 13 |
nicklas |
328 |
{ |
1911 |
19 Mar 13 |
nicklas |
329 |
String cmd = req.getParameter("cmd"); |
2598 |
22 Aug 14 |
nicklas |
330 |
JsonUtil.setJsonResponseHeaders(resp); |
1911 |
19 Mar 13 |
nicklas |
331 |
|
1911 |
19 Mar 13 |
nicklas |
332 |
JSONObject json = new JSONObject(); |
1911 |
19 Mar 13 |
nicklas |
333 |
json.put("status", "ok"); |
1911 |
19 Mar 13 |
nicklas |
334 |
|
1911 |
19 Mar 13 |
nicklas |
335 |
JSONArray jsonMessages = new JSONArray(); |
1911 |
19 Mar 13 |
nicklas |
336 |
|
3975 |
26 May 16 |
nicklas |
337 |
final SessionControl sc = Reggie.getSessionControl(req); |
1911 |
19 Mar 13 |
nicklas |
338 |
DbControl dc = null; |
1911 |
19 Mar 13 |
nicklas |
339 |
try |
1911 |
19 Mar 13 |
nicklas |
340 |
{ |
1934 |
17 Apr 13 |
nicklas |
341 |
if ("CreatePools".equals(cmd)) |
1911 |
19 Mar 13 |
nicklas |
342 |
{ |
6333 |
15 Jun 21 |
nicklas |
343 |
dc = sc.newDbControl(":Create pooled libraries"); |
2161 |
09 Dec 13 |
nicklas |
344 |
|
2161 |
09 Dec 13 |
nicklas |
345 |
ReggieRole.checkPermission(dc, "'" + cmd + "' wizard", ReggieRole.LIBRARY_PREP, ReggieRole.ADMINISTRATOR); |
2161 |
09 Dec 13 |
nicklas |
346 |
|
1959 |
03 May 13 |
nicklas |
// Create PooledLibrary items from a Library bioplate |
3752 |
17 Feb 16 |
nicklas |
348 |
JSONObject jsonReq = JsonUtil.parseRequest(req); |
1934 |
17 Apr 13 |
nicklas |
349 |
JSONArray jsonPools = (JSONArray)jsonReq.get("pools"); |
1987 |
23 May 13 |
nicklas |
350 |
JSONArray jsonFlagged = (JSONArray)jsonReq.get("flagged"); |
1934 |
17 Apr 13 |
nicklas |
351 |
|
1934 |
17 Apr 13 |
nicklas |
352 |
ItemSubtype pooledLibraryType = Subtype.POOLED_LIBRARY.load(dc); |
1959 |
03 May 13 |
nicklas |
353 |
ItemSubtype libraryType = Subtype.LIBRARY.load(dc); |
1934 |
17 Apr 13 |
nicklas |
354 |
|
1959 |
03 May 13 |
nicklas |
//jsonMessages.add("Target molarity: " + TARGET_MOLARITY_IN_POOL + "; Mix " + TARGET_VOLUME_IN_POOL_PER_LIB + "µl, or " + (TARGET_VOLUME_IN_POOL_PER_LIB * (1+EXTRA_LARGE_MIX_FACTOR)) + " if < " + LIMIT_FOR_EXTRA_LARGE_MIX + "µl"); |
1959 |
03 May 13 |
nicklas |
356 |
|
1959 |
03 May 13 |
nicklas |
357 |
for (int poolNo = 0; poolNo < jsonPools.size(); poolNo++) |
1934 |
17 Apr 13 |
nicklas |
358 |
{ |
1959 |
03 May 13 |
nicklas |
359 |
JSONObject jsonPool = (JSONObject)jsonPools.get(poolNo); |
1934 |
17 Apr 13 |
nicklas |
360 |
JSONArray jsonLibs = (JSONArray)jsonPool.get("libs"); |
1987 |
23 May 13 |
nicklas |
361 |
JSONArray jsonExcluded = (JSONArray)jsonPool.get("excluded"); |
1934 |
17 Apr 13 |
nicklas |
362 |
|
2141 |
18 Nov 13 |
nicklas |
363 |
Number libPlateId = (Number)jsonPool.get("libPlate"); |
2184 |
09 Jan 14 |
nicklas |
364 |
String mixingStrategy = (String)jsonPool.get("mixingStrategy"); |
2184 |
09 Jan 14 |
nicklas |
365 |
Number targetVolumeInPoolPerLib = (Number)jsonPool.get("targetVolumeInPoolPerLib"); |
2184 |
09 Jan 14 |
nicklas |
366 |
Number targetPoolMolarity = (Number)jsonPool.get("targetPoolMolarity"); |
2141 |
18 Nov 13 |
nicklas |
367 |
|
1959 |
03 May 13 |
nicklas |
// Create PooledLibrary item |
1934 |
17 Apr 13 |
nicklas |
369 |
Extract pool = Extract.getNew(dc); |
1934 |
17 Apr 13 |
nicklas |
370 |
pool.setItemSubtype(pooledLibraryType); |
4897 |
10 Jul 18 |
nicklas |
371 |
pool.setName(ReggieItem.ensureNonExistingItem(dc, Subtype.POOLED_LIBRARY, (String)jsonPool.get("name"))); |
2042 |
04 Oct 13 |
nicklas |
372 |
pool.setDescription((String)jsonPool.get("comment")); |
5434 |
17 May 19 |
nicklas |
373 |
Pipeline.RNA_SEQ.setAnnotation(dc, pool); |
2027 |
30 Sep 13 |
nicklas |
374 |
Annotationtype.POOL_TARGET_VOLUME_PER_LIB.setAnnotationValue(dc, pool, targetVolumeInPoolPerLib.floatValue()); |
2140 |
18 Nov 13 |
nicklas |
375 |
Annotationtype.POOL_TARGET_MOLARITY.setAnnotationValue(dc, pool, targetPoolMolarity.floatValue()); |
2041 |
04 Oct 13 |
nicklas |
376 |
Annotationtype.POOL_MIXING_STRATEGY.setAnnotationValue(dc, pool, mixingStrategy); |
1934 |
17 Apr 13 |
nicklas |
377 |
|
2141 |
18 Nov 13 |
nicklas |
// Link with library plate |
2141 |
18 Nov 13 |
nicklas |
379 |
if (libPlateId != null) |
2141 |
18 Nov 13 |
nicklas |
380 |
{ |
2141 |
18 Nov 13 |
nicklas |
381 |
BioPlate libPlate = BioPlate.getById(dc, libPlateId.intValue()); |
2141 |
18 Nov 13 |
nicklas |
382 |
AnyToAny libPlateLink = AnyToAny.getNew(dc, pool, libPlate, "LibPlate", true); |
2141 |
18 Nov 13 |
nicklas |
383 |
dc.saveItemIf(pool, libPlateLink, false); |
2141 |
18 Nov 13 |
nicklas |
384 |
} |
2141 |
18 Nov 13 |
nicklas |
385 |
else |
2141 |
18 Nov 13 |
nicklas |
386 |
{ |
2141 |
18 Nov 13 |
nicklas |
387 |
Annotationtype.POOL_IS_MANUAL.setAnnotationValue(dc, pool, true); |
2141 |
18 Nov 13 |
nicklas |
388 |
} |
2141 |
18 Nov 13 |
nicklas |
389 |
|
1934 |
17 Apr 13 |
nicklas |
390 |
BioMaterialEvent poolEvent = pool.getCreationEvent(); |
1934 |
17 Apr 13 |
nicklas |
391 |
|
2027 |
30 Sep 13 |
nicklas |
// Total pool quantities |
2140 |
18 Nov 13 |
nicklas |
393 |
float poolVolume = ((Number)jsonPool.get("ebVolumeExtra")).floatValue(); // volume in pool (µl) |
2027 |
30 Sep 13 |
nicklas |
394 |
float poolQuantity = 0f; // quantity of DNA in pool (µg) |
2027 |
30 Sep 13 |
nicklas |
395 |
float poolAmount = 0f; // Amount of DNA in pool (nano-mole) |
1959 |
03 May 13 |
nicklas |
396 |
|
1959 |
03 May 13 |
nicklas |
397 |
for (int libNo = 0; libNo < jsonLibs.size(); libNo++) |
1934 |
17 Apr 13 |
nicklas |
398 |
{ |
1959 |
03 May 13 |
nicklas |
399 |
JSONObject jsonLib = (JSONObject)jsonLibs.get(libNo); |
1934 |
17 Apr 13 |
nicklas |
400 |
Number libId = (Number)jsonLib.get("id"); |
1934 |
17 Apr 13 |
nicklas |
401 |
|
1959 |
03 May 13 |
nicklas |
// Load the library item |
4886 |
04 Jul 18 |
nicklas |
403 |
Library l = Library.getById(dc, libId.intValue()); |
4886 |
04 Jul 18 |
nicklas |
404 |
Extract lib = l.getItem(); |
1987 |
23 May 13 |
nicklas |
405 |
lib.setDescription((String)jsonLib.get("comment")); |
1934 |
17 Apr 13 |
nicklas |
406 |
|
2027 |
30 Sep 13 |
nicklas |
// Load molarity and concentration for lib |
2454 |
23 May 14 |
nicklas |
408 |
Float libMolarity = (Float)Annotationtype.LIBRARY_MOLARITY_EST.getAnnotationValue(dc, lib); |
1934 |
17 Apr 13 |
nicklas |
409 |
Float originalConc = (Float)Annotationtype.QUBIT_CONC.getAnnotationValue(dc, lib); |
1934 |
17 Apr 13 |
nicklas |
410 |
Float speedVacConc = (Float)Annotationtype.QUBIT_CONC_AFTER_SPEEDVAC.getAnnotationValue(dc, lib); |
3310 |
07 May 15 |
nicklas |
411 |
Float libConcEst = (Float)Annotationtype.LIBRARY_CONC_EST.getAnnotationValue(dc, lib); |
3310 |
07 May 15 |
nicklas |
412 |
Float libConc = Reggie.firstNonNull(libConcEst, speedVacConc, originalConc); |
2027 |
30 Sep 13 |
nicklas |
413 |
|
2027 |
30 Sep 13 |
nicklas |
// Get mixing information from the request |
4887 |
05 Jul 18 |
nicklas |
415 |
float libVolumeInPool = ((Number)jsonLib.get("volume")).floatValue(); |
4887 |
05 Jul 18 |
nicklas |
416 |
float ebVolumeInPool = ((Number)jsonLib.get("eb")).floatValue(); |
2027 |
30 Sep 13 |
nicklas |
417 |
float mixFactor = ((Number)jsonLib.get("mixFactor")).floatValue(); |
1987 |
23 May 13 |
nicklas |
418 |
|
2027 |
30 Sep 13 |
nicklas |
// Calculate amount of DNA and resulting mix molarity |
4887 |
05 Jul 18 |
nicklas |
420 |
float libAmountInPool = libVolumeInPool * libMolarity; |
4887 |
05 Jul 18 |
nicklas |
421 |
float libQuantityInPool = libVolumeInPool * libConc / 1000; |
4887 |
05 Jul 18 |
nicklas |
422 |
float mixVolumeInPool = libVolumeInPool + ebVolumeInPool; |
4887 |
05 Jul 18 |
nicklas |
423 |
float mixMolarity = libAmountInPool / mixVolumeInPool; |
4887 |
05 Jul 18 |
nicklas |
424 |
float mixConc = 1000 * libQuantityInPool / mixVolumeInPool; |
2027 |
30 Sep 13 |
nicklas |
425 |
|
1959 |
03 May 13 |
nicklas |
// Add the library to the pooling event |
1959 |
03 May 13 |
nicklas |
427 |
BioMaterialEventSource poolSrc = poolEvent.addSource(lib); |
4887 |
05 Jul 18 |
nicklas |
428 |
poolSrc.setUsedQuantity(libQuantityInPool); |
1952 |
24 Apr 13 |
nicklas |
429 |
|
1975 |
15 May 13 |
nicklas |
430 |
if (mixFactor > 1.001) |
1959 |
03 May 13 |
nicklas |
431 |
{ |
1959 |
03 May 13 |
nicklas |
// Create 'dil' extract for keeping track of remaining quantity that has been mixed |
4887 |
05 Jul 18 |
nicklas |
433 |
float totalMixVolume = mixVolumeInPool * mixFactor; |
4887 |
05 Jul 18 |
nicklas |
434 |
float extraQuantity = libQuantityInPool * (mixFactor - 1f); |
1959 |
03 May 13 |
nicklas |
435 |
Extract dil = Extract.getNew(dc); |
1959 |
03 May 13 |
nicklas |
436 |
dil.setItemSubtype(libraryType); |
4886 |
04 Jul 18 |
nicklas |
437 |
dil.setName(l.getNextTemporaryDilName(dc)); |
2186 |
10 Jan 14 |
nicklas |
438 |
Number targetVolume = (Number)jsonLib.get("targetVolume"); |
2186 |
10 Jan 14 |
nicklas |
439 |
if (targetVolume != null) |
2186 |
10 Jan 14 |
nicklas |
440 |
{ |
2186 |
10 Jan 14 |
nicklas |
441 |
Annotationtype.POOL_TARGET_VOLUME_PER_LIB.setAnnotationValue(dc, dil, targetVolume.floatValue()); |
2186 |
10 Jan 14 |
nicklas |
442 |
} |
4887 |
05 Jul 18 |
nicklas |
443 |
dil.setDescription("Represents the remaining " + Values.formatNumber(totalMixVolume - mixVolumeInPool, 1) + |
4887 |
05 Jul 18 |
nicklas |
444 |
"µl aliquot after mixing " + Values.formatNumber(totalMixVolume, 1) + |
2104 |
25 Oct 13 |
nicklas |
445 |
"µl solution before pooling. Stored at a temporary location until the pool has been completed."); |
1959 |
03 May 13 |
nicklas |
446 |
BioMaterialEventSource libSrc = dil.getCreationEvent().addSource(lib); |
2027 |
30 Sep 13 |
nicklas |
447 |
Annotationtype.POOL_MOLARITY.setAnnotationValue(dc, dil, mixMolarity); |
2027 |
30 Sep 13 |
nicklas |
448 |
Annotationtype.POOL_CONC.setAnnotationValue(dc, dil, mixConc); |
2027 |
30 Sep 13 |
nicklas |
449 |
libSrc.setUsedQuantity(extraQuantity); |
2027 |
30 Sep 13 |
nicklas |
450 |
dil.setOriginalQuantity(extraQuantity); |
1976 |
15 May 13 |
nicklas |
451 |
dil.setTag(lib.getTag()); |
1959 |
03 May 13 |
nicklas |
452 |
dc.saveItem(dil); |
2027 |
30 Sep 13 |
nicklas |
453 |
/* |
2027 |
30 Sep 13 |
nicklas |
jsonMessages.add("Created " + dil.getName() + |
2027 |
30 Sep 13 |
nicklas |
"; " + Values.formatNumber(mixMolarity, 2) + "nM / "+ |
2027 |
30 Sep 13 |
nicklas |
Values.formatNumber(1000 * extraQuantity / mixConc, 1) + "µl"); |
2027 |
30 Sep 13 |
nicklas |
457 |
*/ |
1959 |
03 May 13 |
nicklas |
458 |
} |
1959 |
03 May 13 |
nicklas |
459 |
|
2027 |
30 Sep 13 |
nicklas |
// Summarize quantity, volumes, molarity for the pool |
4887 |
05 Jul 18 |
nicklas |
461 |
poolQuantity += libQuantityInPool; |
4887 |
05 Jul 18 |
nicklas |
462 |
poolVolume += mixVolumeInPool; |
4887 |
05 Jul 18 |
nicklas |
463 |
poolAmount += libAmountInPool; |
2027 |
30 Sep 13 |
nicklas |
464 |
|
2027 |
30 Sep 13 |
nicklas |
465 |
/* |
2027 |
30 Sep 13 |
nicklas |
jsonMessages.add("Using " + Values.formatNumber(libQuantity*1000, 2) + "+" + |
2027 |
30 Sep 13 |
nicklas |
Values.formatNumber(extraQuantity*1000, 2) +"ng of " + |
2027 |
30 Sep 13 |
nicklas |
Values.formatNumber(lib.getOriginalQuantity()*1000,2) + "ng from " + |
2027 |
30 Sep 13 |
nicklas |
lib.getName()+"; molarity="+Values.formatNumber(libMolarity, 2) + " (" + Values.formatNumber(mixMolarity, 2) + ")"); |
2027 |
30 Sep 13 |
nicklas |
470 |
*/ |
1934 |
17 Apr 13 |
nicklas |
471 |
} |
1934 |
17 Apr 13 |
nicklas |
472 |
|
2027 |
30 Sep 13 |
nicklas |
473 |
float poolConc = 1000 * poolQuantity / poolVolume; |
2027 |
30 Sep 13 |
nicklas |
474 |
float poolMolarity = poolAmount / poolVolume; |
2027 |
30 Sep 13 |
nicklas |
475 |
|
1959 |
03 May 13 |
nicklas |
476 |
pool.setOriginalQuantity(poolQuantity); |
2027 |
30 Sep 13 |
nicklas |
477 |
Annotationtype.POOL_CONC.setAnnotationValue(dc, pool, poolConc); |
2027 |
30 Sep 13 |
nicklas |
478 |
Annotationtype.POOL_MOLARITY.setAnnotationValue(dc, pool, poolMolarity); |
1934 |
17 Apr 13 |
nicklas |
479 |
dc.saveItem(pool); |
1934 |
17 Apr 13 |
nicklas |
480 |
|
1987 |
23 May 13 |
nicklas |
481 |
String excluded = ""; |
1987 |
23 May 13 |
nicklas |
482 |
if (jsonExcluded.size() > 0) |
1987 |
23 May 13 |
nicklas |
483 |
{ |
1987 |
23 May 13 |
nicklas |
484 |
for (int libNo = 0; libNo < jsonExcluded.size(); libNo++) |
1987 |
23 May 13 |
nicklas |
485 |
{ |
1987 |
23 May 13 |
nicklas |
486 |
JSONObject jsonLib = (JSONObject)jsonExcluded.get(libNo); |
1987 |
23 May 13 |
nicklas |
487 |
Number libId = (Number)jsonLib.get("id"); |
1987 |
23 May 13 |
nicklas |
488 |
|
1987 |
23 May 13 |
nicklas |
// Load the library item |
1987 |
23 May 13 |
nicklas |
490 |
Extract lib = Extract.getById(dc, libId.intValue()); |
1987 |
23 May 13 |
nicklas |
491 |
lib.setDescription((String)jsonLib.get("comment")); |
1987 |
23 May 13 |
nicklas |
492 |
Annotationtype.FLAG.setAnnotationValue(dc, lib, Rna.FLAG_EXCLUDED_FROM_POOL); |
1987 |
23 May 13 |
nicklas |
493 |
} |
1987 |
23 May 13 |
nicklas |
494 |
|
1987 |
23 May 13 |
nicklas |
495 |
excluded = " (" + jsonExcluded.size() + " excluded)"; |
1987 |
23 May 13 |
nicklas |
496 |
} |
1987 |
23 May 13 |
nicklas |
497 |
|
2027 |
30 Sep 13 |
nicklas |
498 |
jsonMessages.add("Created '" + pool.getName() + "' from " + jsonLibs.size() + " libraries" + excluded + |
2027 |
30 Sep 13 |
nicklas |
499 |
"; " + Values.formatNumber(poolMolarity, 2) + "nM / " + |
2027 |
30 Sep 13 |
nicklas |
500 |
Values.formatNumber(poolVolume, 1) + "µl"); |
1934 |
17 Apr 13 |
nicklas |
501 |
} |
1975 |
15 May 13 |
nicklas |
502 |
|
1987 |
23 May 13 |
nicklas |
// Process flagged items; add parent RNA to the 'Flagged RNA' list |
1987 |
23 May 13 |
nicklas |
504 |
if (jsonFlagged.size() > 0) |
1987 |
23 May 13 |
nicklas |
505 |
{ |
1987 |
23 May 13 |
nicklas |
506 |
int numFlagged = 0; |
3247 |
14 Apr 15 |
nicklas |
507 |
ItemList flaggedList = BiomaterialList.FLAGGED_RNA.load(dc); |
1987 |
23 May 13 |
nicklas |
508 |
for (int flagNo = 0; flagNo < jsonFlagged.size(); flagNo++) |
1987 |
23 May 13 |
nicklas |
509 |
{ |
1987 |
23 May 13 |
nicklas |
510 |
JSONObject jsonLib = (JSONObject)jsonFlagged.get(flagNo); |
1987 |
23 May 13 |
nicklas |
511 |
Number libId = (Number)jsonLib.get("id"); |
1987 |
23 May 13 |
nicklas |
512 |
|
1987 |
23 May 13 |
nicklas |
// Load the library item |
1987 |
23 May 13 |
nicklas |
514 |
Extract lib = Extract.getById(dc, libId.intValue()); |
5553 |
12 Aug 19 |
nicklas |
515 |
if (!Reggie.isExternalItem(lib.getName())) |
1987 |
23 May 13 |
nicklas |
516 |
{ |
2907 |
07 Nov 14 |
nicklas |
517 |
Library l = Library.get(lib); |
3309 |
06 May 15 |
nicklas |
518 |
Rna r = l.getRna(dc, false); |
2907 |
07 Nov 14 |
nicklas |
519 |
Extract rna = r.getExtract(); |
1987 |
23 May 13 |
nicklas |
520 |
Annotationtype.FLAG.setAnnotationValue(dc, rna, jsonLib.get("flag")); |
1987 |
23 May 13 |
nicklas |
521 |
rna.setDescription((String)jsonLib.get("comment")); |
1987 |
23 May 13 |
nicklas |
522 |
flaggedList.add(rna); |
1987 |
23 May 13 |
nicklas |
523 |
numFlagged++; |
1987 |
23 May 13 |
nicklas |
524 |
} |
1987 |
23 May 13 |
nicklas |
525 |
|
1987 |
23 May 13 |
nicklas |
526 |
} |
1987 |
23 May 13 |
nicklas |
527 |
if (numFlagged > 0) |
1987 |
23 May 13 |
nicklas |
528 |
{ |
1987 |
23 May 13 |
nicklas |
529 |
jsonMessages.add(numFlagged + " RNA items flagged for re-processing"); |
1987 |
23 May 13 |
nicklas |
530 |
} |
1987 |
23 May 13 |
nicklas |
531 |
} |
1987 |
23 May 13 |
nicklas |
532 |
|
2829 |
17 Oct 14 |
nicklas |
533 |
dc.commit(); |
1970 |
08 May 13 |
nicklas |
534 |
} |
1970 |
08 May 13 |
nicklas |
535 |
else if ("RegisterPooledLibraries".equals(cmd)) |
1970 |
08 May 13 |
nicklas |
536 |
{ |
6333 |
15 Jun 21 |
nicklas |
537 |
dc = sc.newDbControl(":Register pooled libraries"); |
2161 |
09 Dec 13 |
nicklas |
538 |
|
2161 |
09 Dec 13 |
nicklas |
539 |
ReggieRole.checkPermission(dc, "'" + cmd + "' wizard", ReggieRole.LIBRARY_PREP, ReggieRole.ADMINISTRATOR); |
2161 |
09 Dec 13 |
nicklas |
540 |
|
3752 |
17 Feb 16 |
nicklas |
541 |
JSONObject jsonReq = JsonUtil.parseRequest(req); |
1934 |
17 Apr 13 |
nicklas |
542 |
|
1970 |
08 May 13 |
nicklas |
543 |
Number poolProtocolId = (Number)jsonReq.get("poolProtocol"); |
1970 |
08 May 13 |
nicklas |
544 |
Date poolDate = Reggie.CONVERTER_STRING_TO_DATE.convert((String)jsonReq.get("poolDate")); |
1970 |
08 May 13 |
nicklas |
545 |
String operator = Values.getStringOrNull((String)jsonReq.get("poolOperator")); |
1970 |
08 May 13 |
nicklas |
546 |
|
1970 |
08 May 13 |
nicklas |
547 |
Protocol poolProtocol = poolProtocolId == null ? null : Protocol.getById(dc, poolProtocolId.intValue()); |
1976 |
15 May 13 |
nicklas |
548 |
|
1976 |
15 May 13 |
nicklas |
549 |
ItemQuery<Extract> dilQuery = Extract.getQuery(); |
4886 |
04 Jul 18 |
nicklas |
550 |
dilQuery.restrict(Restrictions.like(Hql.property("name"), Expressions.parameter("dilName", Type.STRING))); |
1976 |
15 May 13 |
nicklas |
551 |
dilQuery.restrict(Restrictions.eq(Hql.property("creationEvent.eventDate"), null)); |
1976 |
15 May 13 |
nicklas |
552 |
dilQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT); |
1970 |
08 May 13 |
nicklas |
553 |
|
4886 |
04 Jul 18 |
nicklas |
554 |
JSONArray jsonPools = (JSONArray)jsonReq.get("pools"); |
5382 |
24 Apr 19 |
nicklas |
555 |
int numLibs = 0; |
1970 |
08 May 13 |
nicklas |
556 |
for (int i = 0; i < jsonPools.size(); i++) |
1970 |
08 May 13 |
nicklas |
557 |
{ |
2044 |
07 Oct 13 |
nicklas |
558 |
JSONObject jsonPool = (JSONObject)jsonPools.get(i); |
2044 |
07 Oct 13 |
nicklas |
559 |
Number poolId = (Number)jsonPool.get("id"); |
1976 |
15 May 13 |
nicklas |
560 |
PooledLibrary pool = PooledLibrary.getById(dc, poolId.intValue()); |
1976 |
15 May 13 |
nicklas |
561 |
Extract poolExtract = pool.getExtract(); |
1976 |
15 May 13 |
nicklas |
562 |
BioMaterialEvent creationEvent = poolExtract.getCreationEvent(); |
1970 |
08 May 13 |
nicklas |
563 |
|
1970 |
08 May 13 |
nicklas |
564 |
creationEvent.setEventDate(poolDate); |
1970 |
08 May 13 |
nicklas |
565 |
creationEvent.setProtocol(poolProtocol); |
2044 |
07 Oct 13 |
nicklas |
566 |
poolExtract.setDescription(Values.getStringOrNull((String)jsonPool.get("comments"))); |
2191 |
13 Jan 14 |
nicklas |
567 |
Annotationtype.POOL_OPERATOR.setAnnotationValue(dc, poolExtract, operator); |
2066 |
15 Oct 13 |
nicklas |
568 |
Annotationtype.POOL_DATE.setAnnotationValue(dc, poolExtract, poolDate); |
1970 |
08 May 13 |
nicklas |
569 |
|
1976 |
15 May 13 |
nicklas |
// Check if there are any .dil items |
1976 |
15 May 13 |
nicklas |
571 |
List<Library> libs = Library.getByPool(dc, pool); |
5382 |
24 Apr 19 |
nicklas |
572 |
numLibs += libs.size(); |
1976 |
15 May 13 |
nicklas |
573 |
for (Library lib : libs) |
1976 |
15 May 13 |
nicklas |
574 |
{ |
4886 |
04 Jul 18 |
nicklas |
575 |
dilQuery.setParameter("dilName", lib.getName()+".dil%", Type.STRING); |
1976 |
15 May 13 |
nicklas |
576 |
List<Extract> result = dilQuery.list(dc); |
1976 |
15 May 13 |
nicklas |
577 |
if (result.size() == 1) |
1976 |
15 May 13 |
nicklas |
578 |
{ |
1976 |
15 May 13 |
nicklas |
579 |
Extract dil = result.get(0); |
1976 |
15 May 13 |
nicklas |
580 |
BioMaterialEvent dilEvent = dil.getCreationEvent(); |
1976 |
15 May 13 |
nicklas |
581 |
dilEvent.setEventDate(poolDate); |
1976 |
15 May 13 |
nicklas |
582 |
dilEvent.setProtocol(poolProtocol); |
2104 |
25 Oct 13 |
nicklas |
583 |
|
2104 |
25 Oct 13 |
nicklas |
// Create event for destroying the biomaterial |
2104 |
25 Oct 13 |
nicklas |
585 |
BioMaterialEvent discardDil = dil.newEvent(); |
2104 |
25 Oct 13 |
nicklas |
586 |
discardDil.setEventDate(poolDate); |
2104 |
25 Oct 13 |
nicklas |
587 |
discardDil.setProtocol(poolProtocol); |
2104 |
25 Oct 13 |
nicklas |
588 |
discardDil.setUsedQuantity(dil.getOriginalQuantity()); |
2104 |
25 Oct 13 |
nicklas |
589 |
discardDil.setComment("Destroyed this aliquot after pooling was completed."); |
2104 |
25 Oct 13 |
nicklas |
590 |
dc.saveItem(discardDil); |
2104 |
25 Oct 13 |
nicklas |
591 |
|
2104 |
25 Oct 13 |
nicklas |
592 |
BioWell libWell = lib.getExtract().getBioWell(); |
2104 |
25 Oct 13 |
nicklas |
593 |
String location = libWell == null ? "" : " (" + libWell.getCoordinate() + ")"; |
2104 |
25 Oct 13 |
nicklas |
594 |
|
2104 |
25 Oct 13 |
nicklas |
595 |
jsonMessages.add(dil.getName() + location + " aliquot registered as destroyed"); |
1976 |
15 May 13 |
nicklas |
596 |
} |
5384 |
26 Apr 19 |
nicklas |
597 |
} |
2104 |
25 Oct 13 |
nicklas |
598 |
jsonMessages.add(pool.getName() + " registered as completed."); |
1970 |
08 May 13 |
nicklas |
599 |
} |
5384 |
26 Apr 19 |
nicklas |
600 |
String nPools = jsonPools.size() == 1 ? "one pool" : jsonPools.size() + " pools"; |
5421 |
13 May 19 |
nicklas |
601 |
ActivityDef.POOLED_LIBRARIES.create(dc, nPools, numLibs); |
1970 |
08 May 13 |
nicklas |
602 |
|
1959 |
03 May 13 |
nicklas |
603 |
dc.commit(); |
1911 |
19 Mar 13 |
nicklas |
604 |
} |
1911 |
19 Mar 13 |
nicklas |
605 |
json.put("messages", jsonMessages); |
3059 |
19 Dec 14 |
nicklas |
606 |
CounterService.getInstance().setForceCount(); |
1911 |
19 Mar 13 |
nicklas |
607 |
} |
1911 |
19 Mar 13 |
nicklas |
608 |
catch (Throwable t) |
1911 |
19 Mar 13 |
nicklas |
609 |
{ |
1911 |
19 Mar 13 |
nicklas |
610 |
t.printStackTrace(); |
1911 |
19 Mar 13 |
nicklas |
611 |
json.clear(); |
1911 |
19 Mar 13 |
nicklas |
612 |
json.put("status", "error"); |
1911 |
19 Mar 13 |
nicklas |
613 |
json.put("message", t.getMessage()); |
1911 |
19 Mar 13 |
nicklas |
614 |
json.put("stacktrace", ThrowableUtil.stackTraceToString(t)); |
1911 |
19 Mar 13 |
nicklas |
615 |
} |
1911 |
19 Mar 13 |
nicklas |
616 |
finally |
1911 |
19 Mar 13 |
nicklas |
617 |
{ |
1911 |
19 Mar 13 |
nicklas |
618 |
if (dc != null) dc.close(); |
1911 |
19 Mar 13 |
nicklas |
619 |
json.writeJSONString(resp.getWriter()); |
1911 |
19 Mar 13 |
nicklas |
620 |
} |
1911 |
19 Mar 13 |
nicklas |
621 |
|
1911 |
19 Mar 13 |
nicklas |
622 |
} |
1911 |
19 Mar 13 |
nicklas |
623 |
|
1959 |
03 May 13 |
nicklas |
624 |
|
2137 |
13 Nov 13 |
nicklas |
625 |
private void addPoolingCalculationsToLib(DbControl dc, Library lib, PooledLibrary pool) |
1911 |
19 Mar 13 |
nicklas |
626 |
{ |
1959 |
03 May 13 |
nicklas |
// Load original and SpeedVac:ed concentrations |
1959 |
03 May 13 |
nicklas |
// Note that most libs have not been speedvaced and only have an original concentration |
1959 |
03 May 13 |
nicklas |
629 |
Extract libEx = lib.getExtract(); |
1959 |
03 May 13 |
nicklas |
630 |
Float originalConc = (Float)Annotationtype.QUBIT_CONC.getAnnotationValue(dc, libEx); |
1959 |
03 May 13 |
nicklas |
631 |
Float speedVacConc = (Float)Annotationtype.QUBIT_CONC_AFTER_SPEEDVAC.getAnnotationValue(dc, libEx); |
3309 |
06 May 15 |
nicklas |
632 |
Float libConcEst = (Float)Annotationtype.LIBRARY_CONC_EST.getAnnotationValue(dc, libEx); |
3309 |
06 May 15 |
nicklas |
633 |
|
1959 |
03 May 13 |
nicklas |
634 |
lib.setAnnotation("originalConc", originalConc); |
1959 |
03 May 13 |
nicklas |
635 |
lib.setAnnotation("speedVacConc", speedVacConc); |
3309 |
06 May 15 |
nicklas |
636 |
lib.setAnnotation("libConcEst", libConcEst); |
1911 |
19 Mar 13 |
nicklas |
637 |
|
3309 |
06 May 15 |
nicklas |
638 |
Float usedConc = Reggie.firstNonNull(libConcEst, speedVacConc, originalConc); |
3309 |
06 May 15 |
nicklas |
639 |
|
1959 |
03 May 13 |
nicklas |
// Load molarity as calculated from Caliper/Qubit measurements |
2454 |
23 May 14 |
nicklas |
641 |
Float molarity = (Float)Annotationtype.LIBRARY_MOLARITY_EST.getAnnotationValue(dc, libEx); |
1959 |
03 May 13 |
nicklas |
642 |
lib.setAnnotation("molarity", molarity); |
2454 |
23 May 14 |
nicklas |
643 |
lib.loadAnnotations(dc, "libraryFracAdpt", Annotationtype.LIBRARY_FRAC_ADPT, null); |
1959 |
03 May 13 |
nicklas |
644 |
|
1959 |
03 May 13 |
nicklas |
// Load remaining quantity of the lib |
2137 |
13 Nov 13 |
nicklas |
646 |
Float remain = libEx.getRemainingQuantity(); |
1959 |
03 May 13 |
nicklas |
647 |
|
1959 |
03 May 13 |
nicklas |
648 |
if (pool != null) |
1911 |
19 Mar 13 |
nicklas |
649 |
{ |
1959 |
03 May 13 |
nicklas |
// A pool has been "designed", use the quantities as stored in the database |
1959 |
03 May 13 |
nicklas |
651 |
Float usedQuantity = pool.getExtract().getCreationEvent().getUsedQuantity(libEx); |
1959 |
03 May 13 |
nicklas |
652 |
lib.setAnnotation("usedQuantity", usedQuantity); |
1959 |
03 May 13 |
nicklas |
653 |
Float usedVolumeForMix = 1000 * usedQuantity / usedConc; |
2025 |
25 Sep 13 |
nicklas |
654 |
|
2140 |
18 Nov 13 |
nicklas |
// Add the used quantity back since we want the remaining quantity *before* pooling |
2140 |
18 Nov 13 |
nicklas |
656 |
if (remain != null) remain += usedQuantity; |
1959 |
03 May 13 |
nicklas |
657 |
|
2140 |
18 Nov 13 |
nicklas |
// The actual volume used when pooling |
2140 |
18 Nov 13 |
nicklas |
659 |
lib.setAnnotation("actualVolume", usedVolumeForMix); |
2140 |
18 Nov 13 |
nicklas |
660 |
|
2027 |
30 Sep 13 |
nicklas |
// Check if '.dil' exists |
1959 |
03 May 13 |
nicklas |
662 |
ItemQuery<Extract> query = Extract.getQuery(); |
4886 |
04 Jul 18 |
nicklas |
663 |
query.restrict(Restrictions.like(Hql.property("name"), Expressions.string(lib.getName()+".dil%"))); |
1959 |
03 May 13 |
nicklas |
664 |
query.restrict(Restrictions.eq(Hql.property("creationEvent.eventDate"), null)); |
1959 |
03 May 13 |
nicklas |
665 |
query.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT); |
1959 |
03 May 13 |
nicklas |
666 |
List<Extract> result = query.list(dc); |
1959 |
03 May 13 |
nicklas |
667 |
if (result.size() == 1) |
1959 |
03 May 13 |
nicklas |
668 |
{ |
1959 |
03 May 13 |
nicklas |
669 |
Extract dil = result.get(0); |
1959 |
03 May 13 |
nicklas |
670 |
Float dilQuantity = dil.getOriginalQuantity(); |
1975 |
15 May 13 |
nicklas |
671 |
lib.setAnnotation("mixFactor", (dilQuantity + usedQuantity) / usedQuantity); |
2184 |
09 Jan 14 |
nicklas |
// Add the used quantity back since we want the remaining quantity *before* pooling |
2186 |
10 Jan 14 |
nicklas |
673 |
Float targetVolume = (Float)Annotationtype.POOL_TARGET_VOLUME_PER_LIB.getAnnotationValue(dc, dil); |
2186 |
10 Jan 14 |
nicklas |
674 |
if (targetVolume != null) |
2186 |
10 Jan 14 |
nicklas |
675 |
{ |
2186 |
10 Jan 14 |
nicklas |
676 |
lib.setAnnotation("targetVolume", targetVolume); |
2186 |
10 Jan 14 |
nicklas |
677 |
} |
2184 |
09 Jan 14 |
nicklas |
678 |
if (remain != null) remain += dilQuantity; |
4886 |
04 Jul 18 |
nicklas |
679 |
} |
1959 |
03 May 13 |
nicklas |
680 |
|
1959 |
03 May 13 |
nicklas |
681 |
lib.setAnnotation("dils", result.size()); |
1911 |
19 Mar 13 |
nicklas |
682 |
} |
2140 |
18 Nov 13 |
nicklas |
683 |
|
2140 |
18 Nov 13 |
nicklas |
684 |
lib.setAnnotation("remainingQuantity", remain); |
3309 |
06 May 15 |
nicklas |
685 |
if (remain != null && usedConc != null) |
2140 |
18 Nov 13 |
nicklas |
686 |
{ |
2140 |
18 Nov 13 |
nicklas |
// Remaining volume in µl |
3309 |
06 May 15 |
nicklas |
688 |
lib.setAnnotation("remainingVolume", 1000 * remain / usedConc); |
2140 |
18 Nov 13 |
nicklas |
689 |
} |
1911 |
19 Mar 13 |
nicklas |
690 |
} |
1959 |
03 May 13 |
nicklas |
691 |
|
2137 |
13 Nov 13 |
nicklas |
692 |
|
1959 |
03 May 13 |
nicklas |
693 |
private JSONObject getJSONForLibPlate(DbControl dc, BioPlate libPlate) |
1959 |
03 May 13 |
nicklas |
694 |
{ |
1959 |
03 May 13 |
nicklas |
695 |
JSONObject jsonPlate = new JSONObject(); |
1959 |
03 May 13 |
nicklas |
696 |
jsonPlate.put("id", libPlate.getId()); |
1959 |
03 May 13 |
nicklas |
697 |
jsonPlate.put("name", libPlate.getName()); |
1959 |
03 May 13 |
nicklas |
698 |
jsonPlate.put("comments", libPlate.getDescription()); |
1959 |
03 May 13 |
nicklas |
699 |
jsonPlate.put("poolSchema", Annotationtype.POOL_SCHEMA.getAnnotationValue(dc, libPlate)); |
1959 |
03 May 13 |
nicklas |
700 |
jsonPlate.put("barcodeVariant", Annotationtype.BARCODE_VARIANT.getAnnotationValue(dc, libPlate)); |
3310 |
07 May 15 |
nicklas |
701 |
jsonPlate.put("rows", libPlate.getRows()); |
3310 |
07 May 15 |
nicklas |
702 |
jsonPlate.put("columns", libPlate.getColumns()); |
1959 |
03 May 13 |
nicklas |
703 |
return jsonPlate; |
1959 |
03 May 13 |
nicklas |
704 |
} |
1911 |
19 Mar 13 |
nicklas |
705 |
} |