diff options
author | Onderwaater <onderwaa@esrf.fr> | 2015-08-18 13:38:27 +0200 |
---|---|---|
committer | Onderwaater <onderwaa@esrf.fr> | 2015-08-18 13:38:27 +0200 |
commit | a1a9b8e60cc46bb2b3326e87039a054b694c5dea (patch) | |
tree | 05bc0d1e6c51a88b10cd74ad383a1ec5aedce462 | |
parent | d5ca55fc7b393ab8ebd7cd00f1308ffda291c8c0 (diff) |
id03 backend update
- gisaxs class
- projection on pixels
- masking is now optional
- slight restructuring
- error correction in the UCCD reporting
- improved error reporting
-rw-r--r-- | BINoculars/backends/id03.py | 124 |
1 files changed, 103 insertions, 21 deletions
diff --git a/BINoculars/backends/id03.py b/BINoculars/backends/id03.py index 69c8a02..507df77 100644 --- a/BINoculars/backends/id03.py +++ b/BINoculars/backends/id03.py @@ -13,6 +13,15 @@ except ImportError: from .. import backend, errors, util + +class pixels(backend.ProjectionBase): + def project(self, wavelength, UB, gamma, delta, theta, mu, chi, phi): + y,x = numpy.mgrid[slice(None,gamma.shape[0]), slice(None,delta.shape[0])] + return (y, x) + + def get_axis_labels(self): + return 'y','x' + class HKLProjection(backend.ProjectionBase): # arrays: gamma, delta # scalars: theta, mu, chi, phi @@ -248,42 +257,33 @@ class ID03Input(backend.InputBase): for pp, image in itertools.izip(pointparams, images): yield self.process_image(scanparams, pp, image) except Exception as exc: - args = exc.args - if not args: - arg0 = '' - else: - arg0 = args[0] - arg0 += ', for scan {0} at point {1}'.format(self.dbg_scanno, self.dbg_pointno) - exc.args = (arg0, ) + exc.args = errors.addmessage(exc.args, ', An error occured for scan {0} at point {1}. See above for more information'.format(self.dbg_scanno, self.dbg_pointno)) raise def parse_config(self, config): super(ID03Input, self).parse_config(config) - self.config.xmask = util.parse_multi_range(config.pop('xmask'))#image range in the x direction - self.config.ymask = util.parse_multi_range(config.pop('ymask'))#image range in the y direction + self.config.xmask = util.parse_multi_range(config.pop('xmask', None))#Optional, select a subset of the image range in the x direction. all by default + self.config.ymask = util.parse_multi_range(config.pop('ymask', None))#Optional, select a subset of the image range in the y direction. all by default self.config.specfile = config.pop('specfile')#Location of the specfile self.config.imagefolder = config.pop('imagefolder', None) #Optional, takes specfile folder tag by default - self.config.UB = config.pop('ub', None) #Optional, takes specfile matrix by default self.config.pr = config.pop('pr', None) #Optional, all range by default - self.config.hr = config.pop('hr', None) #Optional, hexapod rotations in miliradians. At the entered value the sample is assumed flat, if not entered the sample is assumed flat at the spec values. self.config.background = config.pop('background', None) #Optional, if supplied a space of this image is constructed self.config.th_offset = float(config.pop('th_offset', 0)) #Optional; Only used in zapscans, zero by default. - if self.config.UB: - self.config.UB = util.parse_tuple(self.config.UB, length=9, type=float) - if self.config.hr: - self.config.hr = util.parse_tuple(self.config.hr, length=2, type=float) + if self.config.xmask is None: + self.config.xmask = slice(None) + if self.config.ymask is None: + self.config.ymask = slice(None) if self.config.pr: self.config.pr = util.parse_tuple(self.config.pr, length=2, type=int) self.config.sdd = float(config.pop('sdd'))# sample to detector distance (mm) self.config.pixelsize = util.parse_tuple(config.pop('pixelsize'), length=2, type=float)# pixel size x/y (mm) (same dimension as sdd) - self.config.centralpixel = util.parse_tuple(config.pop('centralpixel'), length=2, type=int) #x,y def get_destination_options(self, command): if not command: return False command = ','.join(command).replace(' ', ',') scans = util.parse_multi_range(command) - return dict(first=min(scans), last=max(scans), range=','.join(command)) + return dict(first=min(scans), last=max(scans), range=','.join(str(scan) for scan in scans)) # CONVENIENCE FUNCTIONS _spec = None @@ -460,11 +460,13 @@ class ID03Input(backend.InputBase): imagefolder = imagefolder.format(UCCD=UCCD, rUCCD=list(reversed(UCCD))) except Exception as e: raise errors.ConfigError("invalid 'imagefolder' specification '{0}': {1}".format(self.config.imagefolder, e)) + else: + if not os.path.exists(imagefolder): + raise errors.ConfigError("invalid 'imagefolder' specification '{0}'. Path {1} does not exist".format(self.config.imagefolder, imagefolder)) else: - imagefolder = os.path.join(UCCD[:-1]) - - if not os.path.exists(imagefolder): - raise errors.ConfigError("invalid 'imagefolder' specification '{0}'. Path {1} does not exist".format(self.config.imagefolder, imagefolder)) + imagefolder = os.path.join(*UCCD) + if not os.path.exists(imagefolder): + raise errors.ConfigError("invalid UCCD tag '{0}'. The UCCD tag in the specfile does not point to an existing folder. Specify the imagefolder in the configuration file.".format(imagefolder)) return os.path.join(imagefolder, '*') @@ -472,6 +474,16 @@ class ID03Input(backend.InputBase): class EH1(ID03Input): monitor_counter = 'mon' + def parse_config(self, config): + super(EH1, self).parse_config(config) + self.config.centralpixel = util.parse_tuple(config.pop('centralpixel'), length=2, type=int) #x,y + self.config.hr = config.pop('hr', None) #Optional, hexapod rotations in miliradians. At the entered value the sample is assumed flat, if not entered the sample is assumed flat at the spec values. + self.config.UB = config.pop('ub', None) #Optional, takes specfile matrix by default + if self.config.UB: + self.config.UB = util.parse_tuple(self.config.UB, length=9, type=float) + if self.config.hr: + self.config.hr = util.parse_tuple(self.config.hr, length=2, type=float) + def process_image(self, scanparams, pointparams, image): gamma, delta, theta, chi, phi, mu, mon, transm, hrx, hry = pointparams @@ -519,6 +531,10 @@ class EH2(ID03Input): def parse_config(self, config): super(EH2, self).parse_config(config) + self.config.centralpixel = util.parse_tuple(config.pop('centralpixel'), length=2, type=int) #x,y + self.config.UB = config.pop('ub', None) #Optional, takes specfile matrix by default + if self.config.UB: + self.config.UB = util.parse_tuple(self.config.UB, length=9, type=float) def process_image(self, scanparams, pointparams, image): @@ -606,3 +622,69 @@ class EH2(ID03Input): +class GisaxsDetector(ID03Input): + monitor_counter = 'mon' + + def process_image(self, scanparams, pointparams, image): + ccdy, ccdz, theta, chi, phi, mu, mon, transm= pointparams + + image = numpy.rot90(image, self.config.drotation) + image = numpy.fliplr(image) + + wavelength, UB = scanparams + + if self.config.background: + data = image / mon + else: + data = image / mon / transm + + if mon == 0: + raise errors.BackendError('Monitor is zero, this results in empty output. Scannumber = {0}, pointnumber = {1}. Did you forget to open the shutter?'.format(self.dbg_scanno, self.dbg_pointno)) + + print '{4}| ccdy: {0}, ccdz: {1}, theta: {2}, mu: {3}'.format(ccdy, ccdz, theta, mu, time.ctime(time.time())) + + # pixels to angles + pixelsize = numpy.array(self.config.pixelsize) + sdd = self.config.sdd + + app = numpy.arctan(pixelsize / sdd) * 180 / numpy.pi + + directbeam = (self.config.directbeam[0] - (ccdy - self.config.directbeam_coords[0]) * pixelsize[0], self.config.directbeam[1] - (ccdz - self.config.directbeam_coords[1]) * pixelsize[1]) + gamma_range= app[0] * (numpy.arange(data.shape[0]) - directbeam[0]) - mu + delta_range= app[1] * (numpy.arange(data.shape[1]) - directbeam[1]) + + # masking + gamma_range = gamma_range[self.config.ymask] + delta_range = delta_range[self.config.xmask] + intensity = self.apply_mask(data, self.config.xmask, self.config.ymask) + + return intensity, (wavelength, UB, gamma_range, delta_range, theta, mu, chi, phi) + + def parse_config(self, config): + super(GisaxsDetector, self).parse_config(config) + self.config.drotation = int(config.pop('drotation', 0)) #Optional; Rotation of the detector, takes standard orientation by default. input 1 for 90 dgree rotation, 2 for 180 and 3 for 270. + self.config.directbeam = util.parse_tuple(config.pop('directbeam'), length=2, type=int) + self.config.directbeam_coords = util.parse_tuple(config.pop('directbeam_coords'), length=2, type=float) #Coordinates of ccdy and ccdz at the direct beam position + + def get_point_params(self, scan, first, last): + sl = slice(first, last+1) + + CCDY, CCDZ, TH, CHI, PHI, MU, MON, TRANSM = range(8) + params = numpy.zeros((last - first + 1, 8)) # gamma delta theta chi phi mu mon transm + params[:, CHI] = scan.motorpos('Chi') + params[:, PHI] = scan.motorpos('Phi') + params[:, CCDY] = scan.motorpos('ccdy') + params[:, CCDZ] = scan.motorpos('ccdz') + + params[:, TH] = scan.datacol('thcnt')[sl] + + try: + params[:, MON] = scan.datacol(self.monitor_counter)[sl] # differs in EH1/EH2 + except: + raise errors.BackendError('The specfile does not accept {2} as a monitor label. Have you selected the right hutch? Scannumber = {0}, pointnumber = {1}'.format(self.dbg_scanno, self.dbg_pointno, self.monitor_counter)) + + params[:, TRANSM] = scan.datacol('transm')[sl] + params[:, MU] = scan.datacol('mucnt')[sl] + return params + + |