Coverage for /opt/conda/envs/apienv/lib/python3.10/site-packages/daiquiri/core/metadata/ispyalchemy/dc.py: 80%
298 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 -*-
2import os
3import json
5from flask import g
7import sqlalchemy
8from sqlalchemy import func, or_
9from sqlalchemy.sql.expression import cast
11from daiquiri.core.metadata.ispyalchemy.handler import IspyalchemyHandler
12from daiquiri.core.metadata.ispyalchemy.utils import page, order
15class DCHandler(IspyalchemyHandler):
16 exported = [
17 "get_datacollections",
18 "add_datacollection",
19 "update_datacollection",
20 "get_datacollection_attachments",
21 "add_datacollection_attachment",
22 "add_sampleaction",
23 "update_sampleaction",
24 "get_sampleactions",
25 "get_sampleaction_positions",
26 "add_sampleaction_position",
27 "remove_sampleaction_position",
28 "get_scanqualityindicators",
29 "add_scanqualityindicators",
30 "get_datacollectionplans",
31 "add_datacollectionplan",
32 "update_datacollectionplan",
33 "remove_datacollectionplan",
34 "_decode_scanparameters",
35 ]
37 def get_datacollections(self, datacollectionid=None, **kwargs):
38 with self.session_scope() as ses:
39 duration = func.time_to_sec(
40 func.timediff(
41 self.DataCollection.endtime,
42 self.DataCollection.starttime,
43 )
44 )
45 dcid = self.DataCollection.datacollectionid
46 starttime = self.DataCollection.starttime
47 endtime = self.DataCollection.endtime
49 if not kwargs.get("datacollectiongroupid") and not kwargs.get("ungroup"):
50 duration = func.sum(duration)
51 dcid = func.min(self.DataCollection.datacollectionid).label(
52 "datacollectionid"
53 )
54 starttime = func.min(self.DataCollection.starttime).label("starttime")
55 endtime = func.max(self.DataCollection.endtime).label("endtime")
57 datacollections = (
58 ses.query(
59 dcid,
60 self.DataCollectionGroup.datacollectiongroupid,
61 self.DataCollectionGroup.blsampleid.label("sampleid"),
62 self.BLSample.name.label("sample"),
63 self.DataCollection.blsubsampleid.label("subsampleid"),
64 self.DataCollection.datacollectionnumber,
65 self.DataCollection.comments,
66 starttime,
67 endtime,
68 self.DataCollection.xtalsnapshotfullpath1,
69 self.DataCollection.xtalsnapshotfullpath2,
70 self.DataCollection.xtalsnapshotfullpath3,
71 self.DataCollection.xtalsnapshotfullpath4,
72 self.DataCollection.filetemplate,
73 self.DataCollection.imagedirectory,
74 duration.label("duration"),
75 self.DataCollection.runstatus,
76 self.DataCollectionGroup.experimenttype,
77 self.DataCollection.exposuretime,
78 self.DataCollection.numberofimages,
79 self.DataCollection.numberofpasses,
80 self.DataCollection.wavelength,
81 self.DataCollection.xbeam,
82 self.DataCollection.ybeam,
83 self.DataCollection.beamsizeatsamplex,
84 self.DataCollection.beamsizeatsampley,
85 cast(self.GridInfo.steps_x, sqlalchemy.Integer).label("steps_x"),
86 cast(self.GridInfo.steps_y, sqlalchemy.Integer).label("steps_y"),
87 self.GridInfo.patchesx,
88 self.GridInfo.patchesy,
89 self.GridInfo.dx_mm.label("dx_mm"),
90 self.GridInfo.dy_mm.label("dy_mm"),
91 self.DataCollection.datacollectionplanid,
92 )
93 .join(
94 self.DataCollectionGroup,
95 self.DataCollectionGroup.datacollectiongroupid
96 == self.DataCollection.datacollectiongroupid,
97 )
98 .outerjoin(
99 self.BLSample,
100 self.BLSample.blsampleid == self.DataCollectionGroup.blsampleid,
101 )
102 .join(self.BLSession)
103 .outerjoin(
104 self.GridInfo,
105 self.GridInfo.datacollectionid
106 == self.DataCollection.datacollectionid,
107 )
108 )
110 if kwargs.get("datacollectiongroupid"):
111 datacollections = datacollections.filter(
112 self.DataCollection.datacollectiongroupid
113 == kwargs["datacollectiongroupid"]
114 )
115 elif kwargs.get("ungroup") is not None:
116 pass
117 else:
118 datacollections = datacollections.add_columns(
119 func.count(
120 func.distinct(self.DataCollection.datacollectionid)
121 ).label("datacollections")
122 )
123 datacollections = datacollections.group_by(
124 self.DataCollection.datacollectiongroupid
125 )
127 if not kwargs.get("no_context"):
128 datacollections = datacollections.filter(
129 self.BLSession.sessionid == g.blsession.get("sessionid")
130 )
132 if not g.user.staff():
133 datacollections = datacollections.join(
134 self.Session_has_Person
135 ).filter(self.Session_has_Person.personid == g.user.get("personid"))
137 if kwargs.get("sampleid"):
138 datacollections = datacollections.filter(
139 self.DataCollectionGroup.blsampleid == kwargs.get("sampleid")
140 )
142 if kwargs.get("subsampleid"):
143 datacollections = datacollections.filter(
144 self.DataCollection.blsubsampleid == kwargs.get("subsampleid")
145 )
147 if kwargs.get("status"):
148 datacollections = datacollections.filter(
149 self.DataCollection.runstatus == kwargs.get("status")
150 )
152 if datacollectionid:
153 datacollections = datacollections.filter(
154 self.DataCollection.datacollectionid == datacollectionid
155 )
156 datacollection = datacollections.first()
157 if datacollection:
158 datacollection = datacollection._asdict()
159 return self._check_snapshots(datacollection)
161 else:
162 total = datacollections.count()
163 datacollections = order(
164 datacollections,
165 {
166 "id": self.DataCollection.datacollectionid,
167 "starttime": self.DataCollection.starttime,
168 "runstatus": self.DataCollection.runstatus,
169 "experimenttype": self.DataCollectionGroup.experimenttype,
170 "duration": duration,
171 },
172 default=["id", "desc"],
173 **kwargs,
174 )
175 datacollections = page(datacollections, **kwargs)
177 dcs = [r._asdict() for r in datacollections.all()]
178 for dc in dcs:
179 dc = self._check_snapshots(dc)
181 return {"total": total, "rows": dcs}
183 def add_datacollection(self, **kwargs):
184 with self.session_scope() as ses:
185 dcg_id = kwargs.get("datacollectiongroupid")
186 if dcg_id is None:
187 dcg = self.DataCollectionGroup(
188 sessionid=kwargs.get("sessionid"),
189 # New location of sampleid
190 blsampleid=kwargs.get("sampleid"),
191 experimenttype=kwargs.get("experimenttype"),
192 scanparameters=kwargs.get("scanparameters"),
193 )
195 ses.add(dcg)
196 ses.commit()
198 dcg_id = dcg.datacollectiongroupid
200 dc = self.DataCollection(
201 datacollectiongroupid=dcg_id,
202 filetemplate=kwargs.get("filetemplate"),
203 imagedirectory=kwargs.get("imagedirectory"),
204 starttime=kwargs.get("starttime"),
205 # This is set in dcg, not dc
206 # experimenttype=kwargs.get("experimenttype"),
207 datacollectionplanid=kwargs.get("datacollectionplanid"),
208 # Legacy, but still used in synchweb, should be in dcg above
209 blsampleid=kwargs.get("sampleid"),
210 blsubsampleid=kwargs.get("subsampleid"),
211 datacollectionnumber=kwargs.get("datacollectionnumber", None),
212 exposuretime=kwargs.get("exposuretime", None),
213 numberofimages=kwargs.get("numberofimages", None),
214 xtalsnapshotfullpath1=kwargs.get("xtalsnapshotfullpath1"),
215 beamsizeatsamplex=kwargs.get("beamsizeatsamplex"),
216 beamsizeatsampley=kwargs.get("beamsizeatsampley"),
217 )
219 ses.add(dc)
220 ses.commit()
222 if kwargs.get("steps_x") or kwargs.get("steps_y"):
223 grid = self.GridInfo(
224 datacollectionid=dc.datacollectionid,
225 steps_x=kwargs.get("steps_x"),
226 steps_y=kwargs.get("steps_y"),
227 patchesx=kwargs.get("patchesx"),
228 patchesy=kwargs.get("patchesy"),
229 dx_mm=kwargs.get("dx_mm"),
230 dy_mm=kwargs.get("dy_mm"),
231 pixelspermicronx=kwargs.get("pixelspermicronx"),
232 pixelspermicrony=kwargs.get("pixelspermicrony"),
233 snapshot_offsetxpixel=kwargs.get("snapshot_offsetxpixel"),
234 snapshot_offsetypixel=kwargs.get("snapshot_offsetypixel"),
235 )
237 ses.add(grid)
238 ses.commit()
240 return self.get_datacollections(
241 datacollectionid=dc.datacollectionid, no_context=True
242 )
244 def update_datacollection(self, datacollectionid, **kwargs):
245 with self.session_scope() as ses:
246 chk = self.get_datacollections(
247 datacollectionid=datacollectionid, no_context=kwargs.get("no_context")
248 )
249 if chk:
250 dc = (
251 ses.query(self.DataCollection)
252 .filter(self.DataCollection.datacollectionid == datacollectionid)
253 .first()
254 )
256 updatable = [
257 "runstatus",
258 "endtime",
259 "comments",
260 "datacollectionnumber",
261 "numberofimages",
262 "numberofpasses",
263 "xtalsnapshotfullpath1",
264 "xtalsnapshotfullpath2",
265 "xtalsnapshotfullpath3",
266 "xtalsnapshotfullpath4",
267 "wavelength",
268 "transmission",
269 "xbeam",
270 "ybeam",
271 "beamsizeatsamplex",
272 "beamsizeatsampley",
273 "imageprefix",
274 "imagedirectory",
275 "imagesuffix",
276 "filetemplate",
277 "imagecontainersubpath",
278 "detectordistance",
279 "detectorid",
280 "flux",
281 "exposuretime",
282 ]
283 for kw in kwargs:
284 if kw in updatable:
285 setattr(dc, kw, kwargs[kw])
287 gridinfo = (
288 ses.query(self.GridInfo)
289 .filter(self.GridInfo.datacollectionid == dc.datacollectionid)
290 .first()
291 )
293 gr_updatable = [
294 "orientation",
295 "steps_x",
296 "steps_y",
297 "dx_mm",
298 "dy_mm",
299 "pixelspermicronx",
300 "pixelspermicrony",
301 "snapshot_offsetxpixel",
302 "snapshot_offsetypixel",
303 ]
304 update_grid = False
305 for kw in kwargs:
306 if kw in gr_updatable:
307 update_grid = True
309 if update_grid:
310 if not gridinfo:
311 gridinfo = self.GridInfo(datacollectionid=dc.datacollectionid)
312 ses.add(gridinfo)
313 ses.commit()
315 for kw in kwargs:
316 if kw in gr_updatable:
317 setattr(gridinfo, kw, kwargs[kw])
319 ses.commit()
321 return self.get_datacollections(
322 datacollectionid=datacollectionid,
323 no_context=kwargs.get("no_context"),
324 )
326 def get_datacollection_attachments(self, datacollectionattachmentid=None, **kwargs):
327 with self.session_scope() as ses:
328 attachments = (
329 ses.query(
330 self.DataCollectionFileAttachment.datacollectionfileattachmentid,
331 self.DataCollectionFileAttachment.filefullpath,
332 self.DataCollectionFileAttachment.filetype,
333 )
334 .join(self.DataCollection)
335 .join(self.DataCollectionGroup)
336 )
338 if not kwargs.get("no_context"):
339 attachments = attachments.filter(
340 self.DataCollectionGroup.sessionid == g.blsession.get("sessionid")
341 )
343 if kwargs.get("datacollectionid"):
344 attachments = attachments.filter(
345 self.DataCollection.datacollectionid == kwargs["datacollectionid"]
346 )
348 if kwargs.get("filetype"):
349 attachments = attachments.filter(
350 self.DataCollectionFileAttachment.filetype == kwargs["filetype"]
351 )
353 if datacollectionattachmentid:
354 attachments = attachments.filter(
355 self.DataCollectionFileAttachment.datacollectionfileattachmentid
356 == datacollectionattachmentid
357 )
358 attachment = attachments.first()
359 if attachment:
360 return self._add_file_to_attachment(attachment._asdict())
362 else:
363 attachments = [
364 self._add_file_to_attachment(r._asdict()) for r in attachments.all()
365 ]
366 return {"total": len(attachments), "rows": attachments}
368 def _add_file_to_attachment(self, attachment):
369 attachment["filename"] = os.path.basename(attachment["filefullpath"])
370 attachment["extension"] = (
371 os.path.splitext(attachment["filename"])[1][1:].strip().lower()
372 )
373 return attachment
375 def add_datacollection_attachment(self, **kwargs):
376 dc = self.get_datacollections(
377 datacollectionid=kwargs.get("datacollectionid"),
378 no_context=kwargs.get("no_context"),
379 )
381 if dc:
382 with self.session_scope() as ses:
383 attachment = self.DataCollectionFileAttachment(
384 datacollectionid=kwargs.get("datacollectionid"),
385 filetype=kwargs.get("filetype"),
386 filefullpath=kwargs.get("filepath"),
387 )
389 ses.add(attachment)
390 ses.commit()
392 return self.get_datacollection_attachments(
393 attachment.datacollectionfileattachmentid,
394 no_context=kwargs.get("no_context"),
395 )
397 def get_sampleactions(self, sampleactionid=None, **kwargs):
398 with self.session_scope() as ses:
399 sampleactions = ses.query(
400 self.RobotAction.robotactionid.label("sampleactionid"),
401 self.RobotAction.blsessionid.label("sessionid"),
402 self.RobotAction.blsampleid.label("sampleid"),
403 self.RobotAction.actiontype,
404 self.RobotAction.starttimestamp,
405 self.RobotAction.endtimestamp,
406 self.RobotAction.status,
407 self.RobotAction.message,
408 self.RobotAction.xtalsnapshotbefore,
409 self.RobotAction.xtalsnapshotafter,
410 self.RobotAction.resultfilepath,
411 )
413 if not kwargs.get("no_context"):
414 sampleactions = sampleactions.filter(
415 self.RobotAction.blsessionid == g.blsession.get("sessionid")
416 )
418 if kwargs.get("actiontype"):
419 sampleactions = sampleactions.filter(
420 self.RobotAction.actiontype == kwargs["actiontype"]
421 )
423 if kwargs.get("sampleid"):
424 sampleactions = sampleactions.filter(
425 self.RobotAction.blsampleid == kwargs["sampleid"]
426 )
428 if sampleactionid:
429 sampleactions = sampleactions.filter(
430 self.RobotAction.robotactionid == sampleactionid
431 )
432 sampleaction = sampleactions.first()
433 if sampleaction:
434 sampleaction = sampleaction._asdict()
435 sampleaction = self._check_result(sampleaction)
436 return sampleaction
438 else:
439 sampleactions = [r._asdict() for r in sampleactions.all()]
440 for sampleaction in sampleactions:
441 sampleaction = self._check_result(sampleaction)
442 return {"total": len(sampleactions), "rows": sampleactions}
444 def _check_result(self, sampleaction):
445 sampleaction["has_result"] = (
446 os.path.exists(sampleaction["resultfilepath"])
447 if sampleaction["resultfilepath"]
448 else False
449 )
450 return sampleaction
452 def add_sampleaction(self, **kwargs):
453 with self.session_scope() as ses:
454 sample = self.get_samples(
455 sampleid=kwargs["sampleid"], no_context=kwargs.get("no_context")
456 )
458 if sample:
459 sampleaction = self.RobotAction(
460 blsessionid=kwargs.get("sessionid"),
461 blsampleid=kwargs.get("sampleid"),
462 actiontype=kwargs.get("actiontype"),
463 starttimestamp=kwargs.get("starttime"),
464 status=kwargs.get("status"),
465 message=kwargs.get("message"),
466 xtalsnapshotbefore=kwargs.get("xtalsnapshotbefore"),
467 xtalsnapshotafter=kwargs.get("xtalsnapshotafter"),
468 )
470 ses.add(sampleaction)
471 ses.commit()
473 return self.get_sampleactions(
474 sampleactionid=sampleaction.robotactionid,
475 no_context=kwargs.get("no_context"),
476 )
478 def update_sampleaction(self, sampleactionid, **kwargs):
479 with self.session_scope() as ses:
480 chk = self.get_sampleactions(
481 sampleactionid=sampleactionid, no_context=kwargs.get("no_context")
482 )
483 if chk:
484 sampleaction = (
485 ses.query(self.RobotAction)
486 .filter(self.RobotAction.robotactionid == sampleactionid)
487 .first()
488 )
490 updatable = [
491 "starttimestamp",
492 "endtimestamp",
493 "status",
494 "message",
495 "xtalsnapshotbefore",
496 "xtalsnapshotafter",
497 "resultfilepath",
498 ]
499 for kw in kwargs:
500 if kw in updatable:
501 val = kwargs[kw]
503 if kw == "message":
504 val = val[:255]
506 setattr(sampleaction, kw, val)
508 ses.commit()
510 return self.get_sampleactions(
511 sampleactionid=sampleactionid, no_context=kwargs.get("no_context")
512 )
514 def get_sampleaction_positions(
515 self,
516 sampleactionpositionid=None,
517 sampleactionid=None,
518 type=None,
519 no_context=None,
520 ):
521 with self.session_scope() as ses:
522 sampleactionspositions = (
523 ses.query(
524 self.RobotActionPosition.robotactionpositionid.label(
525 "sampleactionpositionid"
526 ),
527 self.RobotActionPosition.type,
528 self.RobotActionPosition.id,
529 self.RobotActionPosition.posx,
530 self.RobotActionPosition.posy,
531 )
532 .join(
533 self.RobotAction,
534 self.RobotAction.robotactionid
535 == self.RobotActionPosition.robotactionid,
536 )
537 .group_by(self.RobotActionPosition.robotactionpositionid)
538 )
540 if not no_context:
541 sampleactionspositions = sampleactionspositions.filter(
542 self.RobotAction.blsessionid == g.blsession.get("sessionid")
543 )
545 if sampleactionid:
546 sampleactionspositions = sampleactionspositions.filter(
547 self.RobotActionPosition.robotactionid == sampleactionid
548 )
550 if type:
551 sampleactionspositions = sampleactionspositions.filter(
552 self.RobotActionPosition.type == type
553 )
555 if sampleactionpositionid:
556 sampleactionspositions = sampleactionspositions.filter(
557 self.RobotActionPosition.robotactionpositionid
558 == sampleactionpositionid
559 )
560 sampleactionspositions = sampleactionspositions.first()
561 if sampleactionspositions:
562 return sampleactionspositions._asdict()
564 else:
565 sampleactionspositions = [
566 r._asdict() for r in sampleactionspositions.all()
567 ]
568 return {
569 "total": len(sampleactionspositions),
570 "rows": sampleactionspositions,
571 }
573 def add_sampleaction_position(self, *, sampleactionid, posx, posy, type, id):
574 sampleaction = self.get_sampleactions(sampleactionid=sampleactionid)
575 if not sampleaction:
576 return
578 with self.session_scope() as ses:
579 sampleactionposition = self.RobotActionPosition(
580 robotactionid=sampleactionid,
581 posx=posx,
582 posy=posy,
583 type=type,
584 id=id,
585 )
586 ses.add(sampleactionposition)
587 ses.commit()
589 return self.get_sampleaction_positions(
590 sampleactionpositionid=sampleactionposition.robotactionpositionid
591 )
593 def remove_sampleaction_position(self, sampleactionpositionid, **kargs) -> bool:
594 with self.session_scope() as ses:
595 chk = self.get_sampleaction_positions(
596 sampleactionpositionid=sampleactionpositionid
597 )
598 if chk:
599 sampleactionposition = (
600 ses.query(self.RobotActionPosition)
601 .filter(
602 self.RobotActionPosition.robotactionpositionid
603 == sampleactionpositionid
604 )
605 .first()
606 )
608 ses.delete(sampleactionposition)
609 ses.commit()
611 return True
613 return False
615 def get_scanqualityindicators(self, **kwargs):
616 with self.session_scope() as ses:
617 sqis = (
618 ses.query(
619 self.ImageQualityIndicators.imagenumber.label("point"),
620 self.ImageQualityIndicators.totalintegratedsignal.label("total"),
621 self.ImageQualityIndicators.spottotal.label("spots"),
622 self.ImageQualityIndicators.autoprocprogramid,
623 )
624 .join(
625 self.DataCollection,
626 self.DataCollection.datacollectionid
627 == self.ImageQualityIndicators.datacollectionid,
628 )
629 .join(self.DataCollectionGroup)
630 )
632 if not kwargs.get("no_context"):
633 sqis = sqis.filter(
634 self.DataCollectionGroup.sessionid == g.blsession.get("sessionid")
635 )
637 sqis = sqis.filter(
638 self.DataCollection.datacollectionid == kwargs.get("datacollectionid")
639 )
641 sqis = sqis.order_by(self.ImageQualityIndicators.imagenumber)
643 data = {}
644 for sqi in sqis.all():
645 row = sqi._asdict()
646 for k in ["point", "total", "spots", "autoprocprogramid"]:
647 if k not in data:
648 data[k] = []
650 data[k].append(row[k])
652 return data
654 def add_scanqualityindicators(self, **kwargs):
655 with self.session_scope() as ses:
656 dc = self.get_datacollections(
657 datacollectionid=kwargs["datacollectionid"],
658 no_context=kwargs.get("no_context"),
659 )
661 if dc:
662 args = {}
663 for key in ["total", "spots"]:
664 args[key] = None
665 if kwargs.get(key) is not None:
666 args[key] = float(kwargs[key])
668 sqi = self.ImageQualityIndicators(
669 datacollectionid=kwargs["datacollectionid"],
670 imagenumber=kwargs["point"],
671 totalintegratedsignal=args["total"],
672 spottotal=args["spots"],
673 )
675 ses.add(sqi)
676 ses.commit()
678 return f"{sqi.datacollectionid}-{sqi.imagenumber}"
680 def get_datacollectionplans(
681 self,
682 datacollectionplanid=None,
683 blsampleid=None,
684 status=None,
685 queued=None,
686 no_context=False,
687 **kwargs,
688 ):
689 with self.session_scope() as ses:
690 datacollectionplans = (
691 ses.query(
692 self.DiffractionPlan.diffractionplanid.label(
693 "datacollectionplanid"
694 ),
695 self.DiffractionPlan.scanparameters,
696 self.DiffractionPlan.experimentkind,
697 self.DiffractionPlan.recordtimestamp.label("timestamp"),
698 self.DiffractionPlan.energy,
699 self.DiffractionPlan.exposuretime,
700 self.BLSample.blsampleid.label("sampleid"),
701 self.BLSubSample.blsubsampleid.label("subsampleid"),
702 self.BLSample.name.label("sample"),
703 self.Protein.acronym.label("component"),
704 self.BLSample_has_DataCollectionPlan.planorder,
705 self.DataCollection.datacollectionid,
706 self.ContainerQueueSample.containerqueuesampleid,
707 func.IF(
708 self.DataCollection.datacollectionid, "executed", "pending"
709 ).label("status"),
710 func.IF(
711 self.ContainerQueueSample.containerqueuesampleid, True, False
712 ).label("queued"),
713 func.IF(
714 self.BLSample_has_DataCollectionPlan.blsampleid,
715 True,
716 False,
717 ).label("linked"),
718 )
719 .outerjoin(
720 self.BLSample_has_DataCollectionPlan,
721 self.DiffractionPlan.diffractionplanid
722 == self.BLSample_has_DataCollectionPlan.datacollectionplanid,
723 )
724 .outerjoin(
725 self.ContainerQueueSample,
726 self.ContainerQueueSample.datacollectionplanid
727 == self.DiffractionPlan.diffractionplanid,
728 )
729 .outerjoin(
730 self.BLSubSample,
731 self.BLSubSample.blsubsampleid
732 == self.ContainerQueueSample.blsubsampleid,
733 )
734 .outerjoin(
735 self.BLSample,
736 or_(
737 self.BLSample.blsampleid
738 == self.BLSample_has_DataCollectionPlan.blsampleid,
739 self.BLSample.blsampleid
740 == self.ContainerQueueSample.blsampleid,
741 self.BLSample.blsampleid == self.BLSubSample.blsampleid,
742 ),
743 )
744 .outerjoin(
745 self.Crystal, self.Crystal.crystalid == self.BLSample.crystalid
746 )
747 .outerjoin(
748 self.Protein, self.Crystal.proteinid == self.Protein.proteinid
749 )
750 .outerjoin(
751 self.DataCollection,
752 self.DataCollection.datacollectionplanid
753 == self.DiffractionPlan.diffractionplanid,
754 )
755 )
757 if not no_context:
758 datacollectionplans = datacollectionplans.filter(
759 self.Protein.proposalid == g.blsession.get("proposalid")
760 )
762 if blsampleid:
763 datacollectionplans = datacollectionplans.filter(
764 self.BLSample_has_DataCollectionPlan.blsampleid == blsampleid
765 )
767 if status:
768 if status == "executed":
769 datacollectionplans = datacollectionplans.filter(
770 self.DataCollection.datacollectionid != None # noqa: E711
771 )
772 else:
773 datacollectionplans = datacollectionplans.filter(
774 self.DataCollection.datacollectionid == None # noqa: E711
775 )
777 if queued:
778 datacollectionplans = datacollectionplans.filter(
779 self.ContainerQueueSample.containerqueuesampleid
780 != None # noqa: E711
781 )
783 if datacollectionplanid:
784 datacollectionplans = datacollectionplans.filter(
785 self.DiffractionPlan.diffractionplanid == datacollectionplanid
786 )
787 datacollectionplan = datacollectionplans.first()
788 if datacollectionplan:
789 return self._decode_scanparameters(datacollectionplan._asdict())
791 else:
792 datacollectionplans = order(
793 datacollectionplans,
794 {
795 "sampleid": self.BLSample.blsampleid,
796 "planorder": self.BLSample_has_DataCollectionPlan.planorder,
797 "datacollectionplanid": self.DiffractionPlan.diffractionplanid,
798 },
799 default=["datacollectionplanid", "desc"],
800 **kwargs,
801 )
803 datacollectionplans = [
804 self._decode_scanparameters(r._asdict())
805 for r in datacollectionplans.all()
806 ]
807 return {"total": len(datacollectionplans), "rows": datacollectionplans}
809 def _decode_scanparameters(self, datacollectionplan):
810 if datacollectionplan["scanparameters"]:
811 datacollectionplan["scanparameters"] = json.loads(
812 datacollectionplan["scanparameters"]
813 )
814 return datacollectionplan
816 def add_datacollectionplan(
817 self,
818 *,
819 scanparameters,
820 sampleid=None,
821 energy=None,
822 exposuretime=None,
823 experimentkind=None,
824 planorder=None,
825 no_context=False,
826 ):
827 with self.session_scope() as ses:
828 datacollectionplan = self.DiffractionPlan(
829 scanparameters=json.dumps(scanparameters),
830 experimentkind=experimentkind,
831 energy=energy,
832 exposuretime=exposuretime,
833 )
835 ses.add(datacollectionplan)
836 ses.commit()
838 if sampleid:
839 sample_has_datacollectionplan = self.BLSample_has_DataCollectionPlan(
840 blsampleid=sampleid,
841 datacollectionplanid=datacollectionplan.diffractionplanid,
842 planorder=planorder,
843 )
845 ses.add(sample_has_datacollectionplan)
846 ses.commit()
848 return self.get_datacollectionplans(
849 datacollectionplanid=datacollectionplan.diffractionplanid,
850 no_context=no_context,
851 )
853 def update_datacollectionplan(
854 self, datacollectionplanid, no_context=False, **kwargs
855 ):
856 with self.session_scope() as ses:
857 chk = self.get_datacollectionplans(
858 datacollectionplanid=datacollectionplanid,
859 no_context=kwargs.get("no_context"),
860 )
861 if chk:
862 datacollectionplan = (
863 ses.query(self.DiffractionPlan)
864 .filter(
865 self.DiffractionPlan.diffractionplanid == datacollectionplanid
866 )
867 .first()
868 )
870 updatable = [
871 "scanparameters",
872 "experimentkind",
873 "exposuretime",
874 "energy",
875 ]
876 for kw in kwargs:
877 if kw in updatable:
878 val = kwargs[kw]
880 if kw == "scanparameters":
881 val = json.dumps(val)
883 setattr(datacollectionplan, kw, val)
885 sample_has_datacollectionplan = (
886 ses.query(self.BLSample_has_DataCollectionPlan)
887 .filter(
888 self.BLSample_has_DataCollectionPlan.datacollectionplanid
889 == datacollectionplanid,
890 )
891 .first()
892 )
894 updatable_in_sample = ["planorder"]
895 for kw in kwargs:
896 if kw in updatable_in_sample:
897 val = kwargs[kw]
899 setattr(sample_has_datacollectionplan, kw, val)
901 ses.commit()
903 return self.get_datacollectionplans(
904 datacollectionplanid=datacollectionplanid, no_context=no_context
905 )
907 def remove_datacollectionplan(self, datacollectionplanid, **kwargs):
908 with self.session_scope() as ses:
909 chk = self.get_datacollectionplans(
910 datacollectionplanid=datacollectionplanid,
911 no_context=kwargs.get("no_context"),
912 )
914 if chk:
915 if chk["datacollectionid"]:
916 raise RuntimeError(
917 "Data collection plan has been executed, it cannot be deleted"
918 )
920 if chk["queued"]:
921 raise RuntimeError(
922 "Data collection plan has been queued, it cannot be deleted without being unqueued"
923 )
925 dp = (
926 ses.query(
927 self.DiffractionPlan,
928 )
929 .filter(
930 self.DiffractionPlan.diffractionplanid == datacollectionplanid,
931 )
932 .first()
933 )
935 sample_has_datacollectionplan = (
936 ses.query(self.BLSample_has_DataCollectionPlan)
937 .filter(
938 self.BLSample_has_DataCollectionPlan.datacollectionplanid
939 == datacollectionplanid
940 )
941 .first()
942 )
944 if sample_has_datacollectionplan:
945 ses.delete(sample_has_datacollectionplan)
946 ses.commit()
948 ses.delete(dp)
949 ses.commit()
951 return True