Coverage for /opt/conda/envs/apienv/lib/python3.10/site-packages/daiquiri/core/metadata/ispyalchemy/xrf.py: 89%
174 statements
« prev ^ index » next coverage.py v7.6.4, created at 2024-11-14 02:13 +0000
« prev ^ index » next coverage.py v7.6.4, created at 2024-11-14 02:13 +0000
1# -*- coding: utf-8 -*-
2from flask import g
3import numpy as np
4from sqlalchemy import orm, func
5from sqlalchemy.sql.expression import or_, distinct
7from daiquiri.core.metadata.ispyalchemy.handler import IspyalchemyHandler
8from daiquiri.core.metadata.xrf import (
9 generate_histogram,
10 gunzip_json,
11 gzip_json,
12 autoscale_min_max,
13)
16class XRFHandler(IspyalchemyHandler):
17 exported = [
18 "get_xrf_maps",
19 "add_xrf_map",
20 "update_xrf_map",
21 "remove_xrf_map",
22 "get_xrf_composites",
23 "add_xrf_composite",
24 "update_xrf_composite",
25 "remove_xrf_composite",
26 "get_xrf_map_rois",
27 "add_xrf_map_roi",
28 "add_xrf_map_roi_scalar",
29 "update_xrf_map_roi",
30 "remove_xrf_map_roi",
31 ]
33 def get_xrf_maps(self, mapid=None, **kwargs):
34 with self.session_scope() as ses:
35 xrfmaps = (
36 ses.query(
37 self.XRFFluorescenceMapping.xrffluorescencemappingid.label("mapid"),
38 self.XRFFluorescenceMapping.xrffluorescencemappingroiid.label(
39 "maproiid"
40 ),
41 self.XRFFluorescenceMapping.opacity,
42 self.XRFFluorescenceMapping.colourmap,
43 self.XRFFluorescenceMapping.scale,
44 self.XRFFluorescenceMapping.points,
45 self.XRFFluorescenceMapping.min,
46 self.XRFFluorescenceMapping.max,
47 self.XRFFluorescenceMappingROI.element,
48 self.XRFFluorescenceMappingROI.edge,
49 self.XRFFluorescenceMappingROI.scalar,
50 self.GridInfo.steps_x.label("w"),
51 self.GridInfo.steps_y.label("h"),
52 self.GridInfo.snaked,
53 self.GridInfo.orientation,
54 func.count(
55 distinct(
56 self.XFEFluorescenceComposite.xfefluorescencecompositeid
57 )
58 ).label("composites"),
59 self.DataCollection.datacollectionid.label("datacollectionid"),
60 self.DataCollection.datacollectiongroupid.label(
61 "datacollectiongroupid"
62 ),
63 self.DataCollection.datacollectionnumber.label(
64 "datacollectionnumber"
65 ),
66 self.DataCollection.blsubsampleid.label("subsampleid"),
67 self.DataCollectionGroup.blsampleid.label("sampleid"),
68 func.concat(
69 f"/{self._base_url}/xrf/maps/",
70 self.XRFFluorescenceMapping.xrffluorescencemappingid,
71 ).label("url"),
72 )
73 .join(
74 self.XRFFluorescenceMappingROI,
75 self.XRFFluorescenceMapping.xrffluorescencemappingroiid
76 == self.XRFFluorescenceMappingROI.xrffluorescencemappingroiid,
77 )
78 .join(
79 self.GridInfo,
80 self.XRFFluorescenceMapping.gridinfoid == self.GridInfo.gridinfoid,
81 )
82 .join(
83 self.DataCollection,
84 self.GridInfo.datacollectionid
85 == self.DataCollection.datacollectionid,
86 )
87 .join(
88 self.DataCollectionGroup,
89 self.DataCollectionGroup.datacollectiongroupid
90 == self.DataCollection.datacollectiongroupid,
91 )
92 .join(
93 self.BLSession,
94 self.DataCollectionGroup.sessionid == self.BLSession.sessionid,
95 )
96 .outerjoin(
97 self.XFEFluorescenceComposite,
98 or_(
99 self.XFEFluorescenceComposite.r
100 == self.XRFFluorescenceMapping.xrffluorescencemappingid,
101 or_(
102 self.XFEFluorescenceComposite.g
103 == self.XRFFluorescenceMapping.xrffluorescencemappingid,
104 self.XFEFluorescenceComposite.b
105 == self.XRFFluorescenceMapping.xrffluorescencemappingid,
106 ),
107 ),
108 )
109 .group_by(self.XRFFluorescenceMapping.xrffluorescencemappingid)
110 )
112 if kwargs.get("data") or kwargs.get("histogram"):
113 xrfmaps = xrfmaps.add_columns(self.XRFFluorescenceMapping.data)
115 if not kwargs.get("no_context"):
116 xrfmaps = xrfmaps.filter(
117 self.BLSession.sessionid == g.blsession.get("sessionid")
118 )
120 if kwargs.get("datacollectiongroupid"):
121 xrfmaps = xrfmaps.filter(
122 self.DataCollection.datacollectiongroupid
123 == kwargs.get("datacollectiongroupid")
124 )
126 if kwargs.get("sampleid"):
127 xrfmaps = xrfmaps.filter(
128 self.DataCollectionGroup.blsampleid == kwargs.get("sampleid")
129 )
131 if kwargs.get("subsampleid"):
132 xrfmaps = xrfmaps.filter(
133 self.DataCollection.blsubsampleid == kwargs.get("subsampleid")
134 )
136 if mapid:
137 xrfmaps = xrfmaps.filter(
138 self.XRFFluorescenceMapping.xrffluorescencemappingid == mapid
139 )
140 xrfmap = xrfmaps.first()
141 if xrfmap:
142 xmap = xrfmap._asdict()
143 xmap = self._additional(
144 xmap,
145 histogram=kwargs.get("histogram"),
146 autoscale=kwargs.get("autoscale"),
147 )
148 return xmap
150 else:
151 maps = [r._asdict() for r in xrfmaps.all()]
152 for m in maps:
153 m = self._additional(
154 m,
155 histogram=kwargs.get("histogram"),
156 autoscale=kwargs.get("autoscale"),
157 )
159 return {"total": len(maps), "rows": maps}
161 def _additional(self, row, histogram=False, autoscale=False):
162 if row.get("data"):
163 row["data"] = gunzip_json(row["data"])
165 if histogram:
166 row["histogram"] = generate_histogram(row["data"], autoscale=autoscale)
168 return row
170 def add_xrf_map(self, **kwargs):
171 with self.session_scope() as ses:
172 gridinfo = (
173 ses.query(self.GridInfo.gridinfoid).filter(
174 self.GridInfo.datacollectionid == kwargs["datacollectionid"]
175 )
176 ).first()
178 if not gridinfo:
179 return
181 xrfmap = self.XRFFluorescenceMapping(
182 gridinfoid=gridinfo.gridinfoid,
183 xrffluorescencemappingroiid=kwargs["maproiid"],
184 data=gzip_json(kwargs["data"]),
185 dataformat="json+gzip",
186 points=kwargs.get("points"),
187 )
189 ses.add(xrfmap)
190 ses.commit()
192 return self.get_xrf_maps(
193 mapid=xrfmap.xrffluorescencemappingid,
194 no_context=kwargs.get("no_context"),
195 data=kwargs.get("return_data"),
196 )
198 def update_xrf_map(self, mapid, **kwargs):
199 with self.session_scope() as ses:
200 chk = self.get_xrf_maps(mapid=mapid, no_context=kwargs.get("no_context"))
201 if chk:
202 xrfmap = (
203 ses.query(self.XRFFluorescenceMapping)
204 .filter(
205 self.XRFFluorescenceMapping.xrffluorescencemappingid == mapid
206 )
207 .first()
208 )
209 updatable = [
210 "opacity",
211 "min",
212 "max",
213 "data",
214 "colourmap",
215 "scale",
216 "points",
217 ]
218 for k, v in kwargs.items():
219 if k in updatable:
220 tv = v
221 if k == "data":
222 tv = gzip_json(v)
224 setattr(xrfmap, k, tv)
226 if k == "autoscale":
227 map_ = self.get_xrf_maps(
228 mapid=mapid, no_context=kwargs.get("no_context"), data=True
229 )
230 autoscale = autoscale_min_max(np.array(map_["data"]))
231 xrfmap.min = autoscale.min
232 xrfmap.max = autoscale.max
234 ses.commit()
236 return self.get_xrf_maps(
237 mapid=mapid, no_context=kwargs.get("no_context")
238 )
240 def remove_xrf_map(self, mapid):
241 with self.session_scope() as ses:
242 chk = self.get_xrf_maps(mapid=mapid)
243 if chk:
244 xrfmap = (
245 ses.query(self.XRFFluorescenceMapping)
246 .filter(
247 self.XRFFluorescenceMapping.xrffluorescencemappingid == mapid
248 )
249 .first()
250 )
252 roi = (
253 ses.query(self.XRFFluorescenceMappingROI)
254 .filter(
255 self.XRFFluorescenceMappingROI.xrffluorescencemappingroiid
256 == xrfmap.xrffluorescencemappingroiid
257 )
258 .first()
259 )
261 ses.delete(xrfmap)
263 if roi.blsampleid is None:
264 ses.delete(roi)
266 ses.commit()
268 return True
270 # # XRF Composites
271 def get_xrf_composites(self, compositeid=None, **kwargs):
272 with self.session_scope() as ses:
273 xrfmap2 = orm.aliased(self.XRFFluorescenceMapping)
274 xrfmap3 = orm.aliased(self.XRFFluorescenceMapping)
276 xrfmaproi2 = orm.aliased(self.XRFFluorescenceMappingROI)
277 xrfmaproi3 = orm.aliased(self.XRFFluorescenceMappingROI)
279 composites = (
280 ses.query(
281 self.XFEFluorescenceComposite.xfefluorescencecompositeid.label(
282 "compositeid"
283 ),
284 self.XFEFluorescenceComposite.r,
285 self.XFEFluorescenceComposite.g,
286 self.XFEFluorescenceComposite.b,
287 func.ifnull(
288 func.concat(
289 self.XRFFluorescenceMappingROI.element,
290 "-",
291 self.XRFFluorescenceMappingROI.edge,
292 ),
293 self.XRFFluorescenceMappingROI.scalar,
294 ).label("rroi"),
295 func.ifnull(
296 func.concat(xrfmaproi2.element, "-", xrfmaproi2.edge),
297 xrfmaproi2.scalar,
298 ).label("groi"),
299 func.ifnull(
300 func.concat(xrfmaproi3.element, "-", xrfmaproi3.edge),
301 xrfmaproi3.scalar,
302 ).label("broi"),
303 self.XFEFluorescenceComposite.ropacity,
304 self.XFEFluorescenceComposite.gopacity,
305 self.XFEFluorescenceComposite.bopacity,
306 self.XFEFluorescenceComposite.opacity,
307 func.max(self.DataCollectionGroup.blsampleid).label("sampleid"),
308 func.max(self.DataCollection.blsubsampleid).label("subsampleid"),
309 func.concat(
310 f"/{self._base_url}/xrf/maps/composite/",
311 self.XFEFluorescenceComposite.xfefluorescencecompositeid,
312 ).label("url"),
313 )
314 .join(
315 self.XRFFluorescenceMapping,
316 self.XRFFluorescenceMapping.xrffluorescencemappingid
317 == self.XFEFluorescenceComposite.r,
318 )
319 .join(
320 self.XRFFluorescenceMappingROI,
321 self.XRFFluorescenceMappingROI.xrffluorescencemappingroiid
322 == self.XRFFluorescenceMapping.xrffluorescencemappingroiid,
323 )
324 .join(
325 xrfmap2,
326 xrfmap2.xrffluorescencemappingid == self.XFEFluorescenceComposite.g,
327 )
328 .join(
329 xrfmaproi2,
330 xrfmaproi2.xrffluorescencemappingroiid
331 == xrfmap2.xrffluorescencemappingroiid,
332 )
333 .join(
334 xrfmap3,
335 xrfmap3.xrffluorescencemappingid == self.XFEFluorescenceComposite.b,
336 )
337 .join(
338 xrfmaproi3,
339 xrfmaproi3.xrffluorescencemappingroiid
340 == xrfmap3.xrffluorescencemappingroiid,
341 )
342 .join(
343 self.GridInfo,
344 self.GridInfo.gridinfoid == self.XRFFluorescenceMapping.gridinfoid
345 or self.GridInfo.gridinfoid == xrfmap2.gridinfoid
346 or self.GridInfo.gridinfoid == xrfmap3.gridinfoid,
347 )
348 .join(
349 self.DataCollection,
350 self.GridInfo.datacollectionid
351 == self.DataCollection.datacollectionid,
352 )
353 .join(
354 self.DataCollectionGroup,
355 self.DataCollectionGroup.datacollectiongroupid
356 == self.DataCollection.datacollectiongroupid,
357 )
358 .filter(
359 self.DataCollectionGroup.sessionid == g.blsession.get("sessionid")
360 )
361 .group_by(self.XFEFluorescenceComposite.xfefluorescencecompositeid)
362 )
364 if kwargs.get("sampleid"):
365 composites = composites.filter(
366 self.DataCollectionGroup.blsampleid == kwargs.get("sampleid")
367 )
369 if kwargs.get("subsampleid"):
370 composites = composites.filter(
371 self.DataCollection.blsubsampleid == kwargs.get("subsampleid")
372 )
374 if compositeid:
375 composites = composites.filter(
376 self.XFEFluorescenceComposite.xfefluorescencecompositeid
377 == compositeid
378 )
379 composite = composites.first()
380 if composite:
381 return composite._asdict()
383 else:
384 xrf_composites = [r._asdict() for r in composites.all()]
385 return {"total": len(xrf_composites), "rows": xrf_composites}
387 def add_xrf_composite(self, **kwargs):
388 with self.session_scope() as ses:
389 opacities = {}
390 for mapid in ["r", "g", "b"]:
391 opacities[f"{mapid}opacity"] = kwargs.get(f"{mapid}opacity")
392 m = self.get_xrf_maps(mapid=kwargs[mapid])
393 if m is None:
394 return
396 xrf_composite = self.XFEFluorescenceComposite(
397 r=kwargs["r"], g=kwargs["g"], b=kwargs["b"], **opacities
398 )
400 ses.add(xrf_composite)
401 ses.commit()
403 return self.get_xrf_composites(
404 compositeid=xrf_composite.xfefluorescencecompositeid
405 )
407 def update_xrf_composite(self, compositeid, **kwargs):
408 with self.session_scope() as ses:
409 chk = self.get_xrf_composites(
410 compositeid=compositeid, no_context=kwargs.get("no_context")
411 )
412 if chk:
413 xrf_composite = (
414 ses.query(self.XFEFluorescenceComposite)
415 .filter(
416 self.XFEFluorescenceComposite.xfefluorescencecompositeid
417 == compositeid
418 )
419 .first()
420 )
422 updatable = ["opacity", "ropacity", "gopacity", "bopacity"]
423 for k, v in kwargs.items():
424 if k in updatable:
425 setattr(xrf_composite, k, v)
427 ses.commit()
429 return self.get_xrf_composites(
430 compositeid=compositeid, no_context=kwargs.get("no_context")
431 )
433 def remove_xrf_composite(self, compositeid):
434 with self.session_scope() as ses:
435 chk = self.get_xrf_composites(compositeid=compositeid)
436 if chk:
437 xrf_composite = (
438 ses.query(self.XFEFluorescenceComposite)
439 .filter(
440 self.XFEFluorescenceComposite.xfefluorescencecompositeid
441 == compositeid
442 )
443 .first()
444 )
445 ses.delete(xrf_composite)
446 ses.commit()
448 return True
450 # # XRF ROIs
451 def get_xrf_map_rois(self, maproiid=None, **kwargs):
452 with self.session_scope() as ses:
453 rois = (
454 ses.query(
455 self.XRFFluorescenceMappingROI.xrffluorescencemappingroiid.label(
456 "maproiid"
457 ),
458 self.XRFFluorescenceMappingROI.startenergy.label("start"),
459 self.XRFFluorescenceMappingROI.endenergy.label("end"),
460 self.XRFFluorescenceMappingROI.blsampleid.label("sampleid"),
461 func.concat(
462 self.XRFFluorescenceMappingROI.element,
463 "-",
464 self.XRFFluorescenceMappingROI.edge,
465 ).label("name"),
466 self.XRFFluorescenceMappingROI.element,
467 self.XRFFluorescenceMappingROI.edge,
468 func.count(
469 self.XRFFluorescenceMapping.xrffluorescencemappingid
470 ).label("maps"),
471 )
472 .outerjoin(self.XRFFluorescenceMapping)
473 .group_by(self.XRFFluorescenceMappingROI.xrffluorescencemappingroiid)
474 )
476 if kwargs.get("sampleid"):
477 rois = rois.filter(
478 self.XRFFluorescenceMappingROI.blsampleid == kwargs["sampleid"]
479 )
481 if not kwargs.get("no_context"):
482 rois = (
483 rois.join(self.BLSample)
484 .join(self.Crystal)
485 .join(self.Protein)
486 .filter(self.Protein.proposalid == g.blsession.get("proposalid"))
487 )
489 if maproiid:
490 rois = rois.filter(
491 self.XRFFluorescenceMappingROI.xrffluorescencemappingroiid
492 == maproiid
493 )
494 roi = rois.first()
495 if roi:
496 return roi._asdict()
498 else:
499 xrf_map_rois = [r._asdict() for r in rois.all()]
500 return {"total": len(xrf_map_rois), "rows": xrf_map_rois}
502 def add_xrf_map_roi(self, **kwargs):
503 with self.session_scope() as ses:
504 sample = (
505 ses.query(self.BLSample.blsampleid)
506 .join(self.Crystal)
507 .join(self.Protein)
508 .filter(self.Protein.proposalid == g.blsession.get("proposalid"))
509 .filter(self.BLSample.blsampleid == kwargs["sampleid"])
510 ).first()
512 if not sample:
513 return
515 maproi = self.XRFFluorescenceMappingROI(
516 blsampleid=sample.blsampleid,
517 startenergy=kwargs["start"],
518 endenergy=kwargs["end"],
519 element=kwargs["element"],
520 edge=kwargs["edge"],
521 )
523 ses.add(maproi)
524 ses.commit()
526 return self.get_xrf_map_rois(maproiid=maproi.xrffluorescencemappingroiid)
528 def add_xrf_map_roi_scalar(self, **kwargs):
529 with self.session_scope() as ses:
530 maproi = self.XRFFluorescenceMappingROI(
531 scalar=kwargs["scalar"], startenergy=0, endenergy=0
532 )
534 ses.add(maproi)
535 ses.commit()
537 return self.get_xrf_map_rois(
538 maproiid=maproi.xrffluorescencemappingroiid, no_context=True
539 )
541 def update_xrf_map_roi(self, maproiid, **kwargs):
542 with self.session_scope() as ses:
543 chk = self.get_xrf_map_rois(maproiid=maproiid)
544 if chk:
545 xrf_map_roi = (
546 ses.query(self.XRFFluorescenceMappingROI)
547 .filter(
548 self.XRFFluorescenceMappingROI.xrffluorescencemappingroiid
549 == maproiid
550 )
551 .first()
552 )
553 updatable = {
554 "start": "startenergy",
555 "end": "endenergy",
556 "element": "element",
557 "edge": "edge",
558 }
559 for k, v in kwargs.items():
560 if k in updatable:
561 setattr(xrf_map_roi, updatable[k], v)
563 ses.commit()
565 return self.get_xrf_map_rois(maproiid=maproiid)
567 def remove_xrf_map_roi(self, maproiid):
568 with self.session_scope() as ses:
569 chk = self.get_xrf_map_rois(maproiid=maproiid)
570 if chk:
571 xrf_map_roi = (
572 ses.query(self.XRFFluorescenceMappingROI)
573 .filter(
574 self.XRFFluorescenceMappingROI.xrffluorescencemappingroiid
575 == maproiid
576 )
577 .first()
578 )
579 ses.delete(xrf_map_roi)
580 ses.commit()
582 return True