Coverage for /opt/conda/envs/apienv/lib/python3.10/site-packages/daiquiri/implementors/imageviewer/poiscan.py: 35%
97 statements
« prev ^ index » next coverage.py v7.6.5, created at 2024-11-15 02:12 +0000
« prev ^ index » next coverage.py v7.6.5, created at 2024-11-15 02:12 +0000
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3import logging
4from marshmallow import fields, validate, validates_schema, ValidationError
5import mmh3
6import numpy
8from bliss.config.static import get_config
9from bliss.common.scans import ascan
10from bliss.scanning.group import Sequence
11from bliss.scanning.chain import AcquisitionChannel
13from daiquiri.core.components import ComponentActor, ComponentActorSchema
14from daiquiri.core.utils import to_wavelength
15from daiquiri.core.schema.components import RegionSchema
16from daiquiri.core.hardware.bliss.session import *
17from daiquiri.core.hardware.blissdata.helpers import get_scan_key
19from .createmap import CreatemapActor
20from .beamlineparams import BeamlineParamsSchema
23logger = logging.getLogger(__name__)
24cfg = get_config()
27class PoiscanSchema(ComponentActorSchema):
28 subsampleid = fields.Int(required=True)
29 repeats = fields.Int(
30 required=True,
31 metadata={"title": "No. Repeats"},
32 validate=validate.Range(min=1),
33 dump_default=1,
34 )
35 regions = fields.List(
36 fields.Nested(RegionSchema),
37 metadata={"title": "Energy Regions", "minItems": 1},
38 required=True,
39 )
40 reference = fields.Float(
41 metadata={"title": "Energy Reference", "unit": "keV"},
42 validate=validate.Range(min=0.1),
43 required=True,
44 )
46 beamlineparams = fields.Nested(
47 BeamlineParamsSchema, metadata={"title": "Beamline Parameters"}
48 )
49 enqueue = fields.Bool(metadata={"title": "Queue Scan"}, dump_default=True)
51 @validates_schema
52 def schema_validate(self, data, **kwargs):
53 objs = data.get("objects")
54 if objs:
55 if len(objs) > 1 and data.get("enqueue") is False:
56 raise ValidationError(
57 f"Can only queue scan when more than one object is selected. {len(objs)} objects selected"
58 )
60 class Meta:
61 uiorder = [
62 "subsampleid",
63 "reference",
64 "regions",
65 "repeats",
66 "beamlineparams",
67 "enqueue",
68 ]
69 uischema = {
70 "subsampleid": {"classNames": "hidden-row", "ui:widget": "hidden"},
71 "enqueue": {"classNames": "hidden-row", "ui:widget": "hidden"},
72 "regions": {"ui:field": "arrayTable"},
73 "beamlineparams": {"ui:field": "optionalParams"},
74 }
77class PoiscanActor(ComponentActor):
78 schema = PoiscanSchema
79 metatype = "Energy scan"
80 name = "poiscan"
82 def method(self, **kwargs):
83 print("Add poiscan", kwargs)
85 print("moving to poi")
86 kwargs["absol"]["move_to"](kwargs["absol"])
88 print("moving to addiional positions")
89 kwargs["absol"]["move_to_additional"](kwargs["absol"]["positions"])
91 print("capture params and image")
92 kwargs["before_scan_starts"](self)
94 points = int(
95 (kwargs["regions"][0]["end_e"] - kwargs["regions"][0]["start_e"])
96 / kwargs["regions"][0]["step"]
97 )
99 print("points", points)
101 mca = cfg.get("simu1")
102 mca.block_size = 10
104 seq = Sequence()
105 seq.add_custom_channel(AcquisitionChannel("avg_energy", float, ()))
107 rois = kwargs["get_rois"]()["rois"]
108 roi_data = {}
109 for roi in rois:
110 seq.add_custom_channel(AcquisitionChannel(f"avg_{roi['name']}", float, ()))
111 roi_data[roi["maproiid"]] = {"name": roi["name"], "data": []}
113 diodes = []
114 for i in range(4):
115 diodes.append(config.get(f"diode{i+2}"))
117 with seq.sequence_context() as scan_seq:
118 scans = []
119 for i in range(kwargs["repeats"]):
120 scan = ascan(
121 omega,
122 kwargs["reference"],
123 kwargs["reference"] + kwargs["regions"][0]["end_e"] / 1000,
124 # Intervals vs points !
125 points - 1,
126 kwargs["regions"][0]["dwell"],
127 diode,
128 diodes[0],
129 diodes[1],
130 diodes[2],
131 diodes[3],
132 mca,
133 run=False,
134 )
135 scans.append(scan)
136 scan_seq.add(scan)
138 kwargs["update_datacollection"](
139 self,
140 datacollectionnumber=mmh3.hash(get_scan_key(seq)) & 0xFFFFFFFF,
141 imagecontainersubpath="1.1/measurement",
142 exposuretime=kwargs["regions"][0]["dwell"],
143 numberofimages=points,
144 numberofpasses=kwargs["repeats"],
145 wavelength=to_wavelength(kwargs["reference"] * 1e3),
146 emit_start=True,
147 )
149 scan_number = None
150 for i, scan in enumerate(scans):
151 scan.run()
153 scan_number = mmh3.hash(get_scan_key(scan)) & 0xFFFFFFFF
154 spectra = kwargs["scans"].get_scan_spectra(scan_number, allpoints=True)
156 mapsActor = CreatemapActor()
157 maps = mapsActor.method(spectra=spectra, rois=rois)
159 if maps:
160 for j, mroi in enumerate(maps[0]["maps"]):
161 roi_data[mroi["maproiid"]]["data"].append(mroi["data"])
163 if j == 0:
164 kwargs["add_scanqualityindicators"](
165 self, point=i + 1, total=sum(mroi["data"])
166 )
168 avg_len = 0
169 avgs = {}
170 for roi in roi_data.values():
171 avg = numpy.average(roi["data"], axis=0)
172 avg_len = len(avg)
173 seq.custom_channels[f"avg_{roi['name']}"].emit(avg)
174 avgs[roi["name"]] = avg
176 energy_counter = "axis:omega"
177 energy = []
178 scalars = kwargs["scans"].get_scan_data(
179 scan_number, per_page=1e10, scalars=["axis:omega"]
180 )
181 if energy_counter in scalars["data"]:
182 energy = scalars["data"][energy_counter]["data"]
183 else:
184 logger.warning("Cannot find energy counter")
185 energy = range(avg_len)
187 seq.custom_channels["avg_energy"].emit(energy)
189 with kwargs["open_attachment"](
190 self, "xy", suffix="_average", ext="asc"
191 ) as avgf:
192 headers = "\t".join(avgs.keys())
193 data = numpy.array([energy] + list(avgs.values())).T
194 numpy.savetxt(
195 avgf,
196 data,
197 delimiter="\t",
198 header=f"{energy_counter}\t{headers}",
199 )