Esempio n. 1
0
 def normalize_transmission(self, im: Exposure, datared: Dict):
     transmission = im.header.transmission
     im /= im.header.transmission
     datared['history'].append('Divided by transmission: ' + str(im.header.transmission))
     datared['statistics']['04_normalize_transmission'] = im.get_statistics()
     self._logger.debug('Done normalizing by transmission FSN {:d}'.format(im.header.fsn))
     return im, datared
Esempio n. 2
0
 def subtractdarkbackground(self, im: Exposure, datared: Dict):
     if im.header.title == self.config['datareduction']['darkbackgroundname']:
         self._lastdarkbackground = im.mean()
         self._logger.debug('Determined background level: {:g} cps per pixel'.format(self._lastdarkbackground))
         self._logger.debug('Done darkbgsub FSN {:d}: this is dark background'.format(im.header.fsn))
         datared['history'].append(
             'This is a dark background measurement. Level: {:g} cps per pixel (overall {:g} cps)'.format(
                 self._lastdarkbackground, self._lastdarkbackground * im.shape[0] * im.shape[1]))
         raise DataReductionEnd()
     # otherwise subtract the background.
     im -= self._lastdarkbackground
     datared['history'].append(
         'Subtracted dark background level: {:g} cps per pixel (overall {:g} cps)'.format(
             self._lastdarkbackground, self._lastdarkbackground * im.shape[0] * im.shape[1]))
     datared['darkbackgroundlevel'] = self._lastdarkbackground
     datared['statistics']['03_subtractdarkbackground'] = im.get_statistics()
     self._logger.debug('Done darkbgsub FSN {:d}'.format(im.header.fsn))
     return im, datared
Esempio n. 3
0
    def on_image(self, exposureanalyzer, prefix, fsn, matrix, params, mask):

        im = Exposure(matrix, header=Header(params), mask=mask)
        try:
            sample = im.header.title
        except KeyError:
            sample = "unknown sample"
        legend = "FSN #{:d}, {} at {:.2f} mm".format(im.header.fsn, sample, float(im.header.distance))
        if self.builder.get_object("plotimage_check").get_active():
            if self.builder.get_object("reuseimage_check").get_active():
                imgwin = PlotImageWindow.get_latest_window()
            else:
                imgwin = PlotImageWindow()
            imgwin.set_image(im.intensity)
            imgwin.set_mask(im.mask)
            imgwin.set_distance(im.header.distance)
            imgwin.set_beampos(im.header.beamcenterx, im.header.beamcentery)
            assert im.header.pixelsizex == im.header.pixelsizey
            imgwin.set_pixelsize(im.header.pixelsizex)
            imgwin.set_wavelength(im.header.wavelength)
            imgwin.set_title(legend)
        if self.builder.get_object("plotradial_check").get_active():
            if self.builder.get_object("reuseradial_check").get_active():
                curvewin = PlotCurveWindow.get_latest_window()
            else:
                curvewin = PlotCurveWindow()
            curve = im.radial_average()
            assert im.header.pixelsizex == im.header.pixelsizey
            curvewin.addcurve(
                curve.q,
                curve.Intensity,
                curve.qError,
                curve.Error,
                legend,
                "q",
                im.header.pixelsizex,
                im.header.distance,
                im.header.wavelength,
            )
        self._images_done += 1
        if self._images_done >= self._nimages:
            self.instrument.services["exposureanalyzer"].disconnect(self._expanalyzerconnection)
            self._expanalyzerconnection = None
Esempio n. 4
0
 def load_exposure(self, prefix: str, fsn: int) -> Exposure:
     header = self.load_header(prefix, fsn)
     cbfbasename = self.exposurefileformat(prefix, fsn) + '.cbf'
     imgpath = self.instrument.config['path']['directories']['images']
     for path in [os.path.join(imgpath, prefix), imgpath]:
         try:
             return Exposure.new_from_file(
                 os.path.join(path, cbfbasename), header,
                 self.get_mask(header.maskname))
         except FileNotFoundError:
             continue
     raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), cbfbasename)
Esempio n. 5
0
 def subtractemptybeambackground(self, im: Exposure, datared: Dict):
     if im.header.title == self.config['datareduction']['backgroundname']:
         self._lastbackground = im
         self._logger.debug('Done bgsub FSN {:d}: this is background'.format(im.header.fsn))
         datared['history'].append('This is an empty beam measurement.')
         raise DataReductionEnd()
     if ((im.header.distance - self._lastbackground.header.distance).abs() <
             self.config['datareduction']['distancetolerance']):
         im -= self._lastbackground
         datared['history'].append(
             'Subtracted background FSN #{:d}'.format(self._lastbackground.header.fsn))
         datared['emptybeamFSN'] = self._lastbackground.header.fsn
     else:
         raise ServiceError('Last seen background measurement does not match the exposure under reduction.')
     datared['statistics']['05_subtractbackground'] = im.get_statistics()
     self._logger.debug('Done bgsub FSN {:d}'.format(im.header.fsn))
     return im, datared
Esempio n. 6
0
 def datareduction(self, intensity: np.ndarray, mask: np.ndarray, params: dict):
     im = Exposure(intensity, intensity ** 0.5, Header(params), mask)
     im.mask_negative()
     im.mask_nonfinite()
     im.mask_nan()
     self._logger.debug('Commencing data reduction of FSN #{:d} (sample {}).'.format(im.header.fsn, im.header.title))
     datared = {'history': [], 'statistics': {'01_initial': im.get_statistics()}}
     try:
         self.normalize_flux(im, datared)
         self.subtractdarkbackground(im, datared)
         self.normalize_transmission(im, datared)
         self.subtractemptybeambackground(im, datared)
         self.correctgeometry(im, datared)
         self.dividebythickness(im, datared)
         self.absolutescaling(im, datared)
     except DataReductionEnd:
         pass
     self._logger.info('Data reduction history for FSN #{:d}:\n  '.format(im.header.fsn) +
                       '\n  '.join(h for h in datared['history']))
     im.header.param['datareduction'] = datared
     return im
Esempio n. 7
0
 def correctgeometry(self, im: Exposure, datared: Dict):
     tth = im.twotheta
     assert isinstance(tth, ErrorValue)
     datared['tthval_statistics'] = self.get_matrix_statistics(tth.val)
     datared['ttherr_statistics'] = self.get_matrix_statistics(tth.err)
     assert im.header.pixelsizex == im.header.pixelsizey
     corr_sa = solidangle(tth.val, tth.err, im.header.distance.val,
                          im.header.distance.err, im.header.pixelsizex)
     im *= corr_sa
     datared['history'].append('Corrected for solid angle')
     datared['solidangle_matrixval_statistics'] = self.get_matrix_statistics(corr_sa.val)
     datared['solidangle_matrixerr_statistics'] = self.get_matrix_statistics(corr_sa.err)
     corr_ada = angledependentabsorption(tth.val, tth.err, im.header.transmission.val,
                                         im.header.transmission.err)
     im *= corr_ada
     datared['angledependentabsorption_matrixval_statistics'] = self.get_matrix_statistics(
         corr_ada.val)
     datared['angledependentabsorption_matrixerr_statistics'] = self.get_matrix_statistics(
         corr_ada.err)
     datared['history'].append('Corrected for angle-dependent absorption')
     try:
         vacuum = im.header.vacuum
     except KeyError:
         datared['history'].append(
             'Skipped angle-dependent air absorption correction: no pressure value.')
     else:
         corr_adat = angledependentairtransmission(tth.val, tth.err, vacuum,
                                                   im.header.distance.val,
                                                   im.header.distance.err,
                                                   self.config['datareduction']['mu_air'],
                                                   self.config['datareduction']['mu_air.err'])
         im *= corr_adat
         datared[
             'angledependentairtransmission_matrixval_statistics'] = self.get_matrix_statistics(corr_adat.val)
         datared[
             'angledependentairtransmission_matrixerr_statistics'] = self.get_matrix_statistics(corr_adat.err)
         datared['history'].append(
             'Corrected for angle-dependent air absorption. Pressure: {:f} mbar'.format(
                 im.header.vacuum))
     datared['statistics']['06_correctgeometry'] = im.get_statistics()
     self._logger.debug('Done correctgeometry FSN {:d}'.format(im.header.fsn))
     return im, datared
Esempio n. 8
0
 def absolutescaling(self, im: Exposure, datared: Dict):
     if im.header.title == self.config['datareduction']['absintrefname']:
         self._logger.debug('History: {}'.format('\n'.join([h for h in datared['history']])))
         dataset = np.loadtxt(self.config['datareduction']['absintrefdata'])
         self._logger.debug('Q-range of absint dataset: {:g} to {:g}, {:d} points.'.format(
             dataset[:, 0].min(), dataset[:, 0].max(), len(dataset[:, 0])))
         testradavg = im.radial_average()
         self._logger.debug('Auto-Q-range of the measured dataset: {:g} to {:g}, {:d} points.'.format(
             testradavg.q.min(), testradavg.q.max(), len(testradavg)))
         # noinspection PyPep8Naming,PyPep8Naming
         q, dq, I, dI, area = im.radial_average(qrange=dataset[:, 0], raw_result=True)
         dataset = dataset[area > 0, :]
         # noinspection PyPep8Naming
         I = I[area > 0]
         # noinspection PyPep8Naming
         dI = dI[area > 0]
         q = q[area > 0]
         self._logger.debug('Common q-range: {:g} to {:g}, {:d} points.'.format(q.min(), q.max(), len(q)))
         scalingfactor, stat = nonlinear_odr(I, dataset[:, 1], dI, dataset[:, 2], lambda x, a: a * x, [1])
         datared['absintscaling'] = {'q': q, 'area': area, 'Imeas': I, 'dImeas': dI,
                                     'Iref': dataset[:, 1], 'dIref': dataset[:, 2],
                                     'factor.val': scalingfactor.val,
                                     'factor.err': scalingfactor.err, 'stat': stat}
         self._logger.debug('Scaling factor: ' + str(scalingfactor))
         self._logger.debug('Chi2: {:f}'.format(stat['Chi2_reduced']))
         self._lastabsintref = im
         self._absintscalingfactor = scalingfactor
         self._absintstat = stat
         self._absintqrange = q
         datared['history'].append(
             'This is an absolute intensity reference measurement. '
             'Determined absolute intensity scaling factor: {}. Reduced Chi2: {:f}. DoF: {:d}. '
             'This corresponds to beam flux {} photons*eta/sec'.format(
                 self._absintscalingfactor, self._absintstat['Chi2_reduced'], self._absintstat['DoF'],
                 1 / self._absintscalingfactor))
     if ((im.header.distance - self._lastabsintref.header.distance).abs() <
             self.config['datareduction']['distancetolerance']):
         im *= self._absintscalingfactor
         datared['statistics']['08_absolutescaling'] = im.get_statistics()
         datared['history'].append(
             'Using absolute intensity factor {} from measurement FSN #{:d} '
             'for absolute intensity calibration.'.format(
                 self._absintscalingfactor, self._lastabsintref.header.fsn))
         datared['history'].append('Absint factor was determined with Chi2 {:f} (DoF {:d})'.format(
             self._absintstat['Chi2_reduced'], self._absintstat['DoF']))
         datared['history'].append('Estimated flux: {} photons*eta/sec'.format(
             self._absintscalingfactor.__reciprocal__()))
         datared['absintrefFSN'] = self._lastabsintref.header.fsn
         datared['flux'] = self._absintscalingfactor.__reciprocal__().val
         datared['flux.err'] = self._absintscalingfactor.__reciprocal__().err
         datared['absintchi2'] = self._absintstat['Chi2_reduced']
         datared['absintdof'] = self._absintstat['DoF']
         datared['absintfactor'] = self._absintscalingfactor.val
         datared['absintfactor.err'] = self._absintscalingfactor.err
         datared['absintqmin'] = self._absintqrange.min()
         datared['absintqmax'] = self._absintqrange.max()
     else:
         raise ServiceError(
             'S-D distance of the last seen absolute intensity reference measurement '
             'does not match the exposure under reduction.')
     self._logger.debug('Done absint FSN ' + str(im.header.fsn))
     return im, datared
Esempio n. 9
0
 def dividebythickness(self, im: Exposure, datared: Dict):
     im /= im.header.thickness
     datared['history'].append('Divided by thickness {:g} cm'.format(im.header.thickness))
     datared['statistics']['07_dividebythickness'] = im.get_statistics()
     self._logger.debug('Done dividebythickness FSN {:d}'.format(im.header.fsn))
     return im, datared
Esempio n. 10
0
 def normalize_flux(self, im: Exposure, datared: Dict):
     im /= im.header.exposuretime
     datared['history'].append('Divided by exposure time')
     datared['statistics']['02_normalize_flux'] = im.get_statistics()
     self._logger.debug('Done normalizing by flux FSN {:d}'.format(im.header.fsn))
     return im, datared