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

1# -*- coding: utf-8 -*- 

2from flask import g 

3import numpy as np 

4from sqlalchemy import orm, func 

5from sqlalchemy.sql.expression import or_, distinct 

6 

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) 

14 

15 

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 ] 

32 

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 ) 

111 

112 if kwargs.get("data") or kwargs.get("histogram"): 

113 xrfmaps = xrfmaps.add_columns(self.XRFFluorescenceMapping.data) 

114 

115 if not kwargs.get("no_context"): 

116 xrfmaps = xrfmaps.filter( 

117 self.BLSession.sessionid == g.blsession.get("sessionid") 

118 ) 

119 

120 if kwargs.get("datacollectiongroupid"): 

121 xrfmaps = xrfmaps.filter( 

122 self.DataCollection.datacollectiongroupid 

123 == kwargs.get("datacollectiongroupid") 

124 ) 

125 

126 if kwargs.get("sampleid"): 

127 xrfmaps = xrfmaps.filter( 

128 self.DataCollectionGroup.blsampleid == kwargs.get("sampleid") 

129 ) 

130 

131 if kwargs.get("subsampleid"): 

132 xrfmaps = xrfmaps.filter( 

133 self.DataCollection.blsubsampleid == kwargs.get("subsampleid") 

134 ) 

135 

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 

149 

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 ) 

158 

159 return {"total": len(maps), "rows": maps} 

160 

161 def _additional(self, row, histogram=False, autoscale=False): 

162 if row.get("data"): 

163 row["data"] = gunzip_json(row["data"]) 

164 

165 if histogram: 

166 row["histogram"] = generate_histogram(row["data"], autoscale=autoscale) 

167 

168 return row 

169 

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() 

177 

178 if not gridinfo: 

179 return 

180 

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 ) 

188 

189 ses.add(xrfmap) 

190 ses.commit() 

191 

192 return self.get_xrf_maps( 

193 mapid=xrfmap.xrffluorescencemappingid, 

194 no_context=kwargs.get("no_context"), 

195 data=kwargs.get("return_data"), 

196 ) 

197 

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) 

223 

224 setattr(xrfmap, k, tv) 

225 

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 

233 

234 ses.commit() 

235 

236 return self.get_xrf_maps( 

237 mapid=mapid, no_context=kwargs.get("no_context") 

238 ) 

239 

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 ) 

251 

252 roi = ( 

253 ses.query(self.XRFFluorescenceMappingROI) 

254 .filter( 

255 self.XRFFluorescenceMappingROI.xrffluorescencemappingroiid 

256 == xrfmap.xrffluorescencemappingroiid 

257 ) 

258 .first() 

259 ) 

260 

261 ses.delete(xrfmap) 

262 

263 if roi.blsampleid is None: 

264 ses.delete(roi) 

265 

266 ses.commit() 

267 

268 return True 

269 

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) 

275 

276 xrfmaproi2 = orm.aliased(self.XRFFluorescenceMappingROI) 

277 xrfmaproi3 = orm.aliased(self.XRFFluorescenceMappingROI) 

278 

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 ) 

363 

364 if kwargs.get("sampleid"): 

365 composites = composites.filter( 

366 self.DataCollectionGroup.blsampleid == kwargs.get("sampleid") 

367 ) 

368 

369 if kwargs.get("subsampleid"): 

370 composites = composites.filter( 

371 self.DataCollection.blsubsampleid == kwargs.get("subsampleid") 

372 ) 

373 

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() 

382 

383 else: 

384 xrf_composites = [r._asdict() for r in composites.all()] 

385 return {"total": len(xrf_composites), "rows": xrf_composites} 

386 

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 

395 

396 xrf_composite = self.XFEFluorescenceComposite( 

397 r=kwargs["r"], g=kwargs["g"], b=kwargs["b"], **opacities 

398 ) 

399 

400 ses.add(xrf_composite) 

401 ses.commit() 

402 

403 return self.get_xrf_composites( 

404 compositeid=xrf_composite.xfefluorescencecompositeid 

405 ) 

406 

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 ) 

421 

422 updatable = ["opacity", "ropacity", "gopacity", "bopacity"] 

423 for k, v in kwargs.items(): 

424 if k in updatable: 

425 setattr(xrf_composite, k, v) 

426 

427 ses.commit() 

428 

429 return self.get_xrf_composites( 

430 compositeid=compositeid, no_context=kwargs.get("no_context") 

431 ) 

432 

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() 

447 

448 return True 

449 

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 ) 

475 

476 if kwargs.get("sampleid"): 

477 rois = rois.filter( 

478 self.XRFFluorescenceMappingROI.blsampleid == kwargs["sampleid"] 

479 ) 

480 

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 ) 

488 

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() 

497 

498 else: 

499 xrf_map_rois = [r._asdict() for r in rois.all()] 

500 return {"total": len(xrf_map_rois), "rows": xrf_map_rois} 

501 

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() 

511 

512 if not sample: 

513 return 

514 

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 ) 

522 

523 ses.add(maproi) 

524 ses.commit() 

525 

526 return self.get_xrf_map_rois(maproiid=maproi.xrffluorescencemappingroiid) 

527 

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 ) 

533 

534 ses.add(maproi) 

535 ses.commit() 

536 

537 return self.get_xrf_map_rois( 

538 maproiid=maproi.xrffluorescencemappingroiid, no_context=True 

539 ) 

540 

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) 

562 

563 ses.commit() 

564 

565 return self.get_xrf_map_rois(maproiid=maproiid) 

566 

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() 

581 

582 return True