Example #1
0
class ImageViewer(object):
    def __init__(self, parent = None):
        self.parent = parent

        self.maxPercentile = 0
        self.minPercentile = 0
        self.displayMaxPercentile = 99.0
        self.displayMinPercentile = 1.0

        self.rb = None

        ## Dock 1: Image Panel
        self.d1 = Dock("Image Panel", size=(500, 400))
        self.w1 = pg.ImageView(view=pg.PlotItem())
        self.w1.getView().invertY(False)
        self.img_feature = pg.ImageItem()
        self.w1.getView().addItem(self.img_feature)
        self.ring_feature = pg.ScatterPlotItem()
        self.centre_feature = pg.ScatterPlotItem()
        self.peak_feature = pg.ScatterPlotItem()
        self.indexedPeak_feature = pg.ScatterPlotItem()
        self.z_direction = pg.ScatterPlotItem()
        self.z_direction1 = pg.ScatterPlotItem()
        self.w1.getView().addItem(self.ring_feature)
        self.w1.getView().addItem(self.centre_feature)
        self.w1.getView().addItem(self.peak_feature)
        self.w1.getView().addItem(self.indexedPeak_feature)
        self.w1.getView().addItem(self.z_direction)
        self.w1.getView().addItem(self.z_direction1)
        self.abc_text = pg.TextItem(html='', anchor=(0,0)) # unit cell display
        self.w1.getView().addItem(self.abc_text)
        self.peak_text = pg.TextItem(html='', anchor=(0,0)) # peak display
        self.w1.getView().addItem(self.peak_text)

        # # Isocurve drawing
        # self.iso = pg.IsocurveItem(level=0.8, pen='r')
        # self.iso.setParentItem(self.img_feature)
        # self.iso.setZValue(2)
        # # Contrast/color control
        # self.hist = pg.HistogramLUTItem()
        # self.hist.setImageItem(self.img_feature)
        # self.w1.getView().addItem(self.hist)
        # # Draggable line for setting isocurve level
        # self.isoLine = pg.InfiniteLine(angle=0, movable=True, pen='g')
        # self.hist.vb.addItem(self.isoLine)
        # self.hist.vb.setMouseEnabled(y=False)  # makes user interaction a little easier
        # self.isoLine.setValue(1.8)
        # self.isoLine.setZValue(1000)  # bring iso line above contrast controls

        self.d1.addWidget(self.w1)

        self.drawLabCoordinates()  # FIXME: This does not match the lab coordinates yet!

    def clearPeakMessage(self):
        self.w1.getView().removeItem(self.peak_text)
        self.peak_feature.setData([], [], pxMode=False)
        if self.parent.args.v >= 1: print "Done clearPeakMessage"

    def drawLabCoordinates(self):
        (cenX,cenY) = (-20,-20) # no offset
        # Draw xy arrows
        symbolSize = 40
        cutoff=symbolSize/2
        headLen=30
        tailLen=30-cutoff
        xArrow = pg.ArrowItem(angle=180, tipAngle=30, baseAngle=20, headLen=headLen, tailLen=tailLen, tailWidth=8, pen=None, brush='b', pxMode=False)
        xArrow.setPos(2*headLen+cenX, 0+cenY)
        self.w1.getView().addItem(xArrow)
        yArrow = pg.ArrowItem(angle=-90, tipAngle=30, baseAngle=20, headLen=headLen, tailLen=tailLen, tailWidth=8, pen=None, brush='r', pxMode=False)
        yArrow.setPos(0+cenX, 2*headLen+cenY)
        self.w1.getView().addItem(yArrow)

        # Lab coordinates: Add z-direction
        self.z_direction.setData([0+cenX], [0+cenY], symbol='o', \
                                 size=symbolSize, brush='w', \
                                 pen={'color': 'k', 'width': 4}, pxMode=False)
        self.z_direction1.setData([0+cenX], [0+cenY], symbol='o', \
                                 size=symbolSize/6, brush='k', \
                                 pen={'color': 'k', 'width': 4}, pxMode=False)
        # Lab coordinates: Add xyz text
        self.x_text = pg.TextItem(html='<div style="text-align: center"><span style="color: #0000FF; font-size: 16pt;">x</span></div>', anchor=(0,0))
        self.w1.getView().addItem(self.x_text)
        self.x_text.setPos(2*headLen+cenX, 0+cenY)
        self.y_text = pg.TextItem(html='<div style="text-align: center"><span style="color: #FF0000; font-size: 16pt;">y</span></div>', anchor=(1,1))
        self.w1.getView().addItem(self.y_text)
        self.y_text.setPos(0+cenX, 2*headLen+cenY)
        self.z_text = pg.TextItem(html='<div style="text-align: center"><span style="color: #FFFFFF; font-size: 16pt;">z</span></div>', anchor=(1,0))
        self.w1.getView().addItem(self.z_text)
        self.z_text.setPos(-headLen+cenX, 0+cenY)

        # Label xy axes
        self.x_axis = self.w1.getView().getAxis('bottom')
        self.x_axis.setLabel('X-axis (pixels)')
        self.y_axis = self.w1.getView().getAxis('left')
        self.y_axis.setLabel('Y-axis (pixels)')

    def updateImage(self,calib=None):
        if self.parent.hasExperimentName and self.parent.hasRunNumber and self.parent.hasDetInfo:
            if calib is None:
                self.parent.calib, self.parent.data = self.getDetImage(self.parent.eventNumber)
            else:
                _, self.parent.data = self.getDetImage(self.parent.eventNumber, calib=calib)

            if self.parent.firstUpdate:
                if self.parent.exp.logscaleOn:
                    self.w1.setImage(np.log10(abs(self.parent.data) + self.parent.eps))
                    self.parent.firstUpdate = False
                else:
                    self.minPercentile = np.percentile(self.parent.data, self.displayMinPercentile)
                    if self.minPercentile < 0: self.minPercentile = 0
                    self.maxPercentile = np.percentile(self.parent.data, self.displayMaxPercentile)
                    self.w1.setImage(self.parent.data, levels=(self.minPercentile, self.maxPercentile))
                    self.parent.firstUpdate = False
            else:
                if self.parent.exp.logscaleOn:
                    self.w1.setImage(np.log10(abs(self.parent.data) + self.parent.eps),
                                     autoRange=False, autoLevels=False, autoHistogramRange=False)
                else:
                    if self.minPercentile == 0 and self.maxPercentile == 0:
                        self.minPercentile = np.percentile(self.parent.data, self.displayMinPercentile)
                        if self.minPercentile < 0: self.minPercentile = 0
                        self.maxPercentile = np.percentile(self.parent.data, self.displayMaxPercentile)
                        self.w1.setImage(self.parent.data, levels=(self.minPercentile, self.maxPercentile))
                    else:
                        self.w1.setImage(self.parent.data, autoRange=False, autoLevels=False, autoHistogramRange=False)

            try:
                fname = "/reg/d/psdm/cxi/cxitut13/res/psocake/log/" + \
                        self.parent.exp.username + "_" + self.parent.experimentName + "_" \
                        + str(self.parent.runNumber) + "_" + self.parent.detInfo + ".txt"
                with open(fname, "a") as myfile:
                    date = datetime.datetime.today().strftime('%Y-%m-%d-%H-%M-%S')
                    myStr = date + ": " + str(self.parent.eventNumber) + '\n'
                    myfile.write(myStr)
            except:
                pass

        # Load peak parameters if exists
        if 'sfx' in self.parent.args.mode and self.parent.pk.userUpdate is None:
            self.parent.pk.updateParam()

        if self.parent.args.v >= 1: print "Done updateImage"

    def getCalib(self, evtNumber):
        if self.parent.exp.run is not None:
            self.parent.evt = self.parent.exp.getEvt(evtNumber)
            if self.parent.exp.applyCommonMode: # play with different common mode
                if self.parent.exp.commonMode[0] == 5: # Algorithm 5
                    calib = self.parent.det.calib(self.parent.evt,
                                                  cmpars=(self.parent.exp.commonMode[0], self.parent.exp.commonMode[1]))
                else: # Algorithms 1 to 4
                    print "### Overriding common mode: ", self.parent.exp.commonMode
                    calib = self.parent.det.calib(self.parent.evt,
                                                  cmpars=(self.parent.exp.commonMode[0], self.parent.exp.commonMode[1],
                                                          self.parent.exp.commonMode[2], self.parent.exp.commonMode[3]))
            else:
                calib = self.parent.det.calib(self.parent.evt)
            return calib
        else:
            return None

    def getCommonModeCorrected(self, evtNumber):
        if self.parent.exp.run is not None:
            try:
                self.parent.evt = self.parent.exp.getEvt(evtNumber)
                pedestalCorrected = self.parent.det.raw(self.parent.evt) - self.parent.det.pedestals(self.parent.evt)
                if self.parent.exp.applyCommonMode:  # play with different common mode
                    if self.parent.exp.commonMode[0] == 5:  # Algorithm 5
                        commonMode = self.parent.det.common_mode_correction(self.parent.evt, pedestalCorrected,
                                                                            cmpars=(self.parent.exp.commonMode[0],
                                                                                    self.parent.exp.commonMode[1]))
                        commonModeCorrected = pedestalCorrected - commonMode
                    else:  # Algorithms 1 to 4
                        print "### Overriding common mode: ", self.parent.exp.commonMode
                        commonMode = self.parent.det.common_mode_correction(self.parent.evt, pedestalCorrected,
                                                                     cmpars=(self.parent.exp.commonMode[0], self.parent.exp.commonMode[1],
                                                                             self.parent.exp.commonMode[2], self.parent.exp.commonMode[3]))
                        commonModeCorrected = pedestalCorrected - commonMode
                else:
                    commonMode = self.parent.det.common_mode_correction(self.parent.evt, pedestalCorrected)
                    commonModeCorrected = pedestalCorrected + commonMode # WHAT! You need to ADD common mode?!!
                return commonModeCorrected
            except:
                return None
        else:
            return None

    def getCommonMode(self, evtNumber):
        if self.parent.exp.run is not None:
            self.parent.evt = self.parent.exp.getEvt(evtNumber)
            pedestalCorrected = self.parent.det.raw(self.parent.evt) - self.parent.det.pedestals(self.parent.evt)
            if self.parent.exp.applyCommonMode: # play with different common mode
                print "### Overriding common mode: ", self.parent.exp.commonMode
                if self.parent.exp.commonMode[0] == 5: # Algorithm 5
                    cm = self.parent.det.common_mode_correction(self.parent.evt, pedestalCorrected,
                                                                cmpars=(self.parent.exp.commonMode[0],
                                                                        self.parent.exp.commonMode[1]))
                else: # Algorithms 1 to 4
                    cm = self.parent.det.common_mode_correction(self.parent.evt, pedestalCorrected,
                                                                cmpars=(self.parent.exp.commonMode[0],
                                                                        self.parent.exp.commonMode[1],
                                                                        self.parent.exp.commonMode[2],
                                                                        self.parent.exp.commonMode[3]))
            else:
                cm = self.parent.det.common_mode_correction(self.parent.evt, pedestalCorrected)
            return cm
        else:
            return None

    def getAssembledImage(self, arg, calib):
        if arg == 'lcls':
            _calib = calib.copy() # this is important
            tic = time.time()
            if self.parent.exp.applyFriedel: # Apply Friedel symmetry
                print "Apply Friedel symmetry"
                centre = self.parent.det.point_indexes(self.parent.evt, pxy_um=(0, 0))
                self.fs = FriedelSym(self.parent.exp.detGuaranteedData.shape, centre)
                data = self.parent.det.image(self.parent.evt, _calib)
                if self.parent.mk.combinedMask is not None:
                    data = self.fs.applyFriedel(data, mask=self.parent.det.image(self.parent.evt, self.parent.mk.combinedMask), mode='same')
                else:
                    data = self.fs.applyFriedel(data, mask=None, mode='same')
            else:
                data = self.parent.det.image(self.parent.evt, _calib)
            if data is None: data = _calib
            toc = time.time()
            if self.parent.args.v >= 1: print "time assemble: ", toc-tic
            return data

    def setupRadialBackground(self):
        self.parent.geom.findPsanaGeometry()
        if self.parent.geom.calibFile is not None:
            if self.parent.args.v >= 1: print "calibFile: ", self.parent.geom.calibPath+'/'+self.parent.geom.calibFile
            self.geo = self.parent.det.geometry(self.parent.runNumber) #self.geo = GeometryAccess(self.parent.geom.calibPath+'/'+self.parent.geom.calibFile)
            self.xarr, self.yarr, self.zarr = self.geo.get_pixel_coords()
            self.iX, self.iY = self.geo.get_pixel_coord_indexes()
            self.mask = self.geo.get_pixel_mask(mbits=0377)  # mask for 2x1 edges, two central columns, and unbound pixels with their neighbours
            self.rb = RadialBkgd(self.xarr, self.yarr, mask=self.mask, radedges=None, nradbins=100, phiedges=(0, 360), nphibins=1)
            if self.parent.args.v >= 1: print "Done setupRadialBackground"
        else:
            self.rb = None

    def updatePolarizationFactor(self):
        if self.rb is not None:
            self.pf = polarization_factor(self.rb.pixel_rad(), self.rb.pixel_phi(), self.parent.detectorDistance*1e6) # convert to um
            if self.parent.args.v >= 1: print "Done updatePolarizationFactor"

    def updateDetectorCentre(self, arg):
        if arg == 'lcls':
            self.parent.cx, self.parent.cy = self.parent.det.point_indexes(self.parent.evt, pxy_um=(0, 0))
            if self.parent.cx is None:
                data = self.parent.det.image(self.parent.evt, self.parent.exp.detGuaranteed)
                self.parent.cx, self.parent.cy = self.getCentre(data.shape)
            if self.parent.args.v >= 1: print "cx, cy: ", self.parent.cx, self.parent.cy

    def getDetImage(self, evtNumber, calib=None):
        if calib is None:
            if self.parent.exp.image_property == self.parent.exp.disp_medianCorrection:  # median subtraction
                calib = self.getCalib(evtNumber)
                if calib is None: calib = np.zeros_like(self.parent.exp.detGuaranteed, dtype='float32')
                calib -= median_filter_ndarr(calib, self.parent.exp.medianFilterRank)
            elif self.parent.exp.image_property == self.parent.exp.disp_radialCorrection:  # radial subtraction + polarization corrected
                calib = self.getCalib(evtNumber)
                if calib is None: calib = np.zeros_like(self.parent.exp.detGuaranteed, dtype='float32')
                self.pf.shape = calib.shape # FIXME: shape is 1d
                calib = self.rb.subtract_bkgd(calib * self.pf)
                calib.shape = self.parent.calib.shape # FIXME: shape is 1d
            elif self.parent.exp.image_property == self.parent.exp.disp_adu: # gain and hybrid gain corrected
                calib = self.getCalib(evtNumber)
                if calib is None: calib = np.zeros_like(self.parent.exp.detGuaranteed, dtype='float32')
            elif self.parent.exp.image_property == self.parent.exp.disp_commonModeCorrected: # common mode corrected
                calib = self.getCommonModeCorrected(evtNumber)
                if calib is None: calib = np.zeros_like(self.parent.exp.detGuaranteed, dtype='float32')
            elif self.parent.exp.image_property == self.parent.exp.disp_pedestalCorrected: # pedestal corrected
                calib = self.parent.det.raw(self.parent.evt).astype('float32')
                if calib is None:
                    calib = np.zeros_like(self.parent.exp.detGuaranteed, dtype='float32')
                else:
                    calib -= self.parent.det.pedestals(self.parent.evt)
            elif self.parent.exp.image_property == self.parent.exp.disp_raw: # raw
                calib = self.parent.det.raw(self.parent.evt)
                if calib is None:
                    calib = np.zeros_like(self.parent.exp.detGuaranteed, dtype='float32')
                self.parent.firstUpdate = True
            elif self.parent.exp.image_property == self.parent.exp.disp_photons: # photon counts
                calib = self.parent.det.photons(self.parent.evt, mask=self.parent.mk.userMask, adu_per_photon=self.parent.exp.aduPerPhoton)
                if calib is None:
                    calib = np.zeros_like(self.parent.exp.detGuaranteed, dtype='int32')
                self.parent.firstUpdate = True
            elif self.parent.exp.image_property == self.parent.exp.disp_pedestal: # pedestal
                calib = self.parent.det.pedestals(self.parent.evt)
                self.parent.firstUpdate = True
            elif self.parent.exp.image_property == self.parent.exp.disp_status: # status
                calib = self.parent.det.status(self.parent.evt)
                self.parent.firstUpdate = True
            elif self.parent.exp.image_property == self.parent.exp.disp_rms: # rms
                calib = self.parent.det.rms(self.parent.evt)
                self.parent.firstUpdate = True
            elif self.parent.exp.image_property == self.parent.exp.disp_commonMode: # common mode
                calib = self.getCommonMode(evtNumber)
                self.parent.firstUpdate = True
            elif self.parent.exp.image_property == self.parent.exp.disp_gain: # gain
                calib = self.parent.det.gain(self.parent.evt)
                self.parent.firstUpdate = True
            elif self.parent.exp.image_property == self.parent.exp.disp_gainMask: # gain_mask
                calib = self.parent.det.gain_mask(self.parent.evt)
                self.parent.firstUpdate = True
            elif self.parent.exp.image_property == self.parent.exp.disp_coordx: # coords_x
                calib = self.parent.det.coords_x(self.parent.evt)
                self.parent.firstUpdate = True
            elif self.parent.exp.image_property == self.parent.exp.disp_coordy: # coords_y
                calib = self.parent.det.coords_y(self.parent.evt)
                self.parent.firstUpdate = True

            shape = self.parent.det.shape(self.parent.evt)
            if len(shape) == 3:
                if self.parent.exp.image_property == self.parent.exp.disp_quad: # quad ind
                    calib = np.zeros(shape)
                    for i in range(shape[0]):
                        # TODO: handle detectors properly
                        if shape[0] == 32: # cspad
                            calib[i,:,:] = int(i)%8
                        elif shape[0] == 2: # cspad2x2
                            calib[i,:,:] = int(i)%2
                        elif shape[0] == 4: # pnccd
                            calib[i,:,:] = int(i)%4
                    self.parent.firstUpdate = True
                elif self.parent.exp.image_property == self.parent.exp.disp_seg: # seg ind
                    calib = np.zeros(shape)
                    if shape[0] == 32: # cspad
                        for i in range(32):
                            calib[i,:,:] = int(i)/8
                    elif shape[0] == 2: # cspad2x2
                        for i in range(2):
                            calib[i,:,:] = int(i)
                    elif shape[0] == 4: # pnccd
                        for i in range(4):
                            calib[i,:,:] = int(i)
                    self.parent.firstUpdate = True
                elif self.parent.exp.image_property == self.parent.exp.disp_row: # row ind
                    calib = np.zeros(shape)
                    if shape[0] == 32: # cspad
                        for i in range(185):
                            calib[:,i,:] = i
                    elif shape[0] == 2: # cspad2x2
                        for i in range(185):
                            calib[:,i,:] = i
                    elif shape[0] == 4: # pnccd
                        for i in range(512):
                            calib[:,i,:] = i
                    self.parent.firstUpdate = True
                elif self.parent.exp.image_property == self.parent.exp.disp_col: # col ind
                    calib = np.zeros(shape)
                    if shape[0] == 32: # cspad
                        for i in range(388):
                            calib[:,:,i] = i
                    elif shape[0] == 2: # cspad2x2
                        for i in range(388):
                            calib[:,:,i] = i
                    elif shape[0] == 4: # pnccd
                        for i in range(512):
                            calib[:,:,i] = i
                    self.parent.firstUpdate = True

        # Update photon energy
        self.parent.exp.updatePhotonEnergy('lcls')

        # Update clen
        self.parent.geom.updateClen('lcls')

        # Write a temporary geom file
        self.parent.geom.deployCrystfelGeometry('lcls')
        self.parent.geom.writeCrystfelGeom('lcls') # Hack to override coffset

        # Get assembled image
        if calib is not None:
            data = self.getAssembledImage('lcls', calib)
        else:
            calib = np.zeros_like(self.parent.exp.detGuaranteed, dtype='float32')
            data = self.getAssembledImage('lcls', calib)

        # Update detector centre
        self.updateDetectorCentre('lcls')

        # Update ROI histogram
        if self.parent.roi.roiCurrent == 'rect':
            self.parent.roi.updateRoi(self.parent.roi.roi)
        elif self.parent.roi.roiCurrent == 'poly':
            self.parent.roi.updateRoi(self.parent.roi.roiPoly)
        elif self.parent.roi.roiCurrent == 'circ':
            self.parent.roi.updateRoi(self.parent.roi.roiCircle)

        return calib, data

    def getCentre(self,shape):
        cx = shape[1]/2
        cy = shape[0]/2
        return cx,cy
Example #2
0
class PeakFinder:
    def __init__(self,
                 exp,
                 run,
                 detname,
                 evt,
                 detector,
                 algorithm,
                 hitParam_alg_npix_min,
                 hitParam_alg_npix_max,
                 hitParam_alg_amax_thr,
                 hitParam_alg_atot_thr,
                 hitParam_alg_son_min,
                 streakMask_on,
                 streakMask_sigma,
                 streakMask_width,
                 userMask_path,
                 psanaMask_on,
                 psanaMask_calib,
                 psanaMask_status,
                 psanaMask_edges,
                 psanaMask_central,
                 psanaMask_unbond,
                 psanaMask_unbondnrs,
                 medianFilterOn=0,
                 medianRank=5,
                 radialFilterOn=0,
                 distance=0.0,
                 windows=None,
                 **kwargs):
        self.exp = exp
        self.run = run
        self.detname = detname
        self.det = detector
        self.algorithm = algorithm
        self.maxRes = 0

        self.npix_min = hitParam_alg_npix_min
        self.npix_max = hitParam_alg_npix_max
        self.amax_thr = hitParam_alg_amax_thr
        self.atot_thr = hitParam_alg_atot_thr
        self.son_min = hitParam_alg_son_min

        self.streakMask_on = str2bool(streakMask_on)
        self.streakMask_sigma = streakMask_sigma
        self.streakMask_width = streakMask_width
        self.userMask_path = userMask_path
        self.psanaMask_on = str2bool(psanaMask_on)
        self.psanaMask_calib = str2bool(psanaMask_calib)
        self.psanaMask_status = str2bool(psanaMask_status)
        self.psanaMask_edges = str2bool(psanaMask_edges)
        self.psanaMask_central = str2bool(psanaMask_central)
        self.psanaMask_unbond = str2bool(psanaMask_unbond)
        self.psanaMask_unbondnrs = str2bool(psanaMask_unbondnrs)

        self.medianFilterOn = medianFilterOn
        self.medianRank = medianRank
        self.radialFilterOn = radialFilterOn
        self.distance = distance

        self.windows = windows

        self.userMask = None
        self.psanaMask = None
        self.streakMask = None
        self.userPsanaMask = None
        self.combinedMask = None

        # Make user mask
        if self.userMask_path is not None:
            self.userMask = np.load(self.userMask_path)

        # Make psana mask
        if self.psanaMask_on:
            self.psanaMask = detector.mask(evt,
                                           calib=self.psanaMask_calib,
                                           status=self.psanaMask_status,
                                           edges=self.psanaMask_edges,
                                           central=self.psanaMask_central,
                                           unbond=self.psanaMask_unbond,
                                           unbondnbrs=self.psanaMask_unbondnrs)

        # Combine userMask and psanaMask
        self.userPsanaMask = np.ones_like(self.det.calib(evt))
        if self.userMask is not None:
            self.userPsanaMask *= self.userMask
        if self.psanaMask is not None:
            self.userPsanaMask *= self.psanaMask

        # Powder of hits and misses
        self.powderHits = np.zeros_like(self.userPsanaMask)
        self.powderMisses = np.zeros_like(self.userPsanaMask)

        self.alg = PyAlgos(windows=self.windows,
                           mask=self.userPsanaMask,
                           pbits=0)
        # set peak-selector parameters:
        self.alg.set_peak_selection_pars(npix_min=self.npix_min, npix_max=self.npix_max, \
                                        amax_thr=self.amax_thr, atot_thr=self.atot_thr, \
                                        son_min=self.son_min)
        # set algorithm specific parameters
        if algorithm == 1:
            self.hitParam_alg1_thr_low = kwargs["alg1_thr_low"]
            self.hitParam_alg1_thr_high = kwargs["alg1_thr_high"]
            self.hitParam_alg1_rank = int(kwargs["alg1_rank"])
            self.hitParam_alg1_radius = int(kwargs["alg1_radius"])
            self.hitParam_alg1_dr = kwargs["alg1_dr"]
        elif algorithm == 3:
            self.hitParam_alg3_rank = kwargs["alg3_rank"]
            self.hitParam_alg3_r0 = int(kwargs["alg3_r0"])
            self.hitParam_alg3_dr = kwargs["alg3_dr"]
        elif algorithm == 4:
            self.hitParam_alg4_thr_low = kwargs["alg4_thr_low"]
            self.hitParam_alg4_thr_high = kwargs["alg4_thr_high"]
            self.hitParam_alg4_rank = int(kwargs["alg4_rank"])
            self.hitParam_alg4_r0 = int(kwargs["alg4_r0"])
            self.hitParam_alg4_dr = kwargs["alg4_dr"]

        self.maxNumPeaks = 2048
        self.StreakMask = myskbeam.StreakMask(self.det,
                                              evt,
                                              width=self.streakMask_width,
                                              sigma=self.streakMask_sigma)
        self.cx, self.cy = self.det.point_indexes(evt, pxy_um=(0, 0))
        self.iX = np.array(self.det.indexes_x(evt), dtype=np.int64)
        self.iY = np.array(self.det.indexes_y(evt), dtype=np.int64)
        if len(self.iX.shape) == 2:
            self.iX = np.expand_dims(self.iX, axis=0)
            self.iY = np.expand_dims(self.iY, axis=0)

        # Initialize radial background subtraction
        self.setupExperiment()
        if self.radialFilterOn:
            self.setupRadialBackground()
            self.updatePolarizationFactor()

    def setupExperiment(self):
        self.ds = psana.DataSource('exp=' + str(self.exp) + ':run=' +
                                   str(self.run) + ':idx')
        self.run = self.ds.runs().next()
        self.times = self.run.times()
        self.eventTotal = len(self.times)
        self.env = self.ds.env()
        self.evt = self.run.event(self.times[0])
        self.det = psana.Detector(str(self.detname), self.env)
        self.det.do_reshape_2d_to_3d(flag=True)

    def setupRadialBackground(self):
        self.geo = self.det.geometry(
            self.run
        )  # self.geo = GeometryAccess(self.parent.geom.calibPath+'/'+self.parent.geom.calibFile)
        self.xarr, self.yarr, self.zarr = self.geo.get_pixel_coords()
        self.ix = self.det.indexes_x(self.evt)
        self.iy = self.det.indexes_y(self.evt)
        if self.ix is None:
            self.iy = np.tile(np.arange(self.userMask.shape[1]),
                              [self.userMask.shape[2], 1])
            self.ix = np.transpose(self.iy)
        self.iX = np.array(self.ix, dtype=np.int64)
        self.iY = np.array(self.iy, dtype=np.int64)
        if len(self.iX.shape) == 2:
            self.iX = np.expand_dims(self.iX, axis=0)
            self.iY = np.expand_dims(self.iY, axis=0)
        self.mask = self.geo.get_pixel_mask(
            mbits=0377
        )  # mask for 2x1 edges, two central columns, and unbound pixels with their neighbours
        self.rb = RadialBkgd(self.xarr,
                             self.yarr,
                             mask=self.mask,
                             radedges=None,
                             nradbins=100,
                             phiedges=(0, 360),
                             nphibins=1)

    def updatePolarizationFactor(self):
        self.pf = polarization_factor(self.rb.pixel_rad(), self.rb.pixel_phi(),
                                      self.distance * 1e6)  # convert to um

    def findPeaks(self, calib, evt):

        if self.streakMask_on:  # make new streak mask
            self.streakMask = self.StreakMask.getStreakMaskCalib(evt)

        # Apply background correction
        if self.medianFilterOn:
            calib -= median_filter_ndarr(calib, self.medianRank)

        if self.radialFilterOn:
            self.pf.shape = calib.shape  # FIXME: shape is 1d
            calib = self.rb.subtract_bkgd(calib * self.pf)
            calib.shape = self.userPsanaMask.shape  # FIXME: shape is 1d

        if self.streakMask is not None:
            self.combinedMask = self.userPsanaMask * self.streakMask
        else:
            self.combinedMask = self.userPsanaMask
        # set new mask
        #self.alg = PyAlgos(windows=self.windows, mask=self.combinedMask, pbits=0)
        # set peak-selector parameters:
        #self.alg.set_peak_selection_pars(npix_min=self.npix_min, npix_max=self.npix_max, \
        #                                amax_thr=self.amax_thr, atot_thr=self.atot_thr, \
        #                                son_min=self.son_min)
        self.alg.set_mask(self.combinedMask)  # This doesn't work reliably
        # set algorithm specific parameters
        if self.algorithm == 1:
            # v1 - aka Droplet Finder - two-threshold peak-finding algorithm in restricted region
            #                           around pixel with maximal intensity.
            self.peaks = self.alg.peak_finder_v4r2(
                calib,
                thr_low=self.hitParam_alg1_thr_low,
                thr_high=self.hitParam_alg1_thr_high,
                rank=self.hitParam_alg1_rank,
                r0=self.hitParam_alg1_radius,
                dr=self.hitParam_alg1_dr)
        elif self.algorithm == 3:
            self.peaks = self.alg.peak_finder_v3(calib,
                                                 rank=self.hitParam_alg3_rank,
                                                 r0=self.hitParam_alg3_r0,
                                                 dr=self.hitParam_alg3_dr)
        elif self.algorithm == 4:
            # v4 - aka iDroplet Finder - two-threshold peak-finding algorithm in restricted region
            #                            around pixel with maximal intensity.
            self.peaks = self.alg.peak_finder_v4(calib, thr_low=self.hitParam_alg4_thr_low, thr_high=self.hitParam_alg4_thr_high, \
                                   rank=self.hitParam_alg4_rank, r0=self.hitParam_alg4_r0, dr=self.hitParam_alg4_dr)
        self.numPeaksFound = self.peaks.shape[0]

        if self.numPeaksFound > 0:
            cenX = self.iX[np.array(self.peaks[:, 0], dtype=np.int64),
                           np.array(self.peaks[:, 1], dtype=np.int64),
                           np.array(self.peaks[:, 2], dtype=np.int64)] + 0.5
            cenY = self.iY[np.array(self.peaks[:, 0], dtype=np.int64),
                           np.array(self.peaks[:, 1], dtype=np.int64),
                           np.array(self.peaks[:, 2], dtype=np.int64)] + 0.5
            self.maxRes = getMaxRes(cenX, cenY, self.cx, self.cy)
        else:
            self.maxRes = 0

        if self.numPeaksFound >= 15:
            self.powderHits = np.maximum(self.powderHits, calib)
        else:
            self.powderMisses = np.maximum(self.powderMisses, calib)
Example #3
0
class ImageViewer(object):
    def __init__(self, parent=None):
        self.parent = parent

        self.maxPercentile = 0
        self.minPercentile = 0
        self.displayMaxPercentile = 99.0
        self.displayMinPercentile = 1.0

        self.rb = None

        ## Dock 1: Image Panel
        self.d1 = Dock("Image Panel", size=(500, 400))
        self.w1 = pg.ImageView(view=pg.PlotItem())
        self.w1.getView().invertY(False)
        self.img_feature = pg.ImageItem()
        self.w1.getView().addItem(self.img_feature)
        self.ring_feature = pg.ScatterPlotItem()
        self.centre_feature = pg.ScatterPlotItem()
        self.peak_feature = pg.ScatterPlotItem()
        self.indexedPeak_feature = pg.ScatterPlotItem()
        self.z_direction = pg.ScatterPlotItem()
        self.z_direction1 = pg.ScatterPlotItem()
        self.w1.getView().addItem(self.ring_feature)
        self.w1.getView().addItem(self.centre_feature)
        self.w1.getView().addItem(self.peak_feature)
        self.w1.getView().addItem(self.indexedPeak_feature)
        self.w1.getView().addItem(self.z_direction)
        self.w1.getView().addItem(self.z_direction1)
        self.abc_text = pg.TextItem(html='',
                                    anchor=(0, 0))  # unit cell display
        self.w1.getView().addItem(self.abc_text)
        self.peak_text = pg.TextItem(html='', anchor=(0, 0))  # peak display
        self.w1.getView().addItem(self.peak_text)

        # # Isocurve drawing
        # self.iso = pg.IsocurveItem(level=0.8, pen='r')
        # self.iso.setParentItem(self.img_feature)
        # self.iso.setZValue(2)
        # # Contrast/color control
        # self.hist = pg.HistogramLUTItem()
        # self.hist.setImageItem(self.img_feature)
        # self.w1.getView().addItem(self.hist)
        # # Draggable line for setting isocurve level
        # self.isoLine = pg.InfiniteLine(angle=0, movable=True, pen='g')
        # self.hist.vb.addItem(self.isoLine)
        # self.hist.vb.setMouseEnabled(y=False)  # makes user interaction a little easier
        # self.isoLine.setValue(1.8)
        # self.isoLine.setZValue(1000)  # bring iso line above contrast controls

        self.d1.addWidget(self.w1)

        self.drawLabCoordinates(
        )  # FIXME: This does not match the lab coordinates yet!

    def clearPeakMessage(self):
        self.w1.getView().removeItem(self.peak_text)
        self.peak_feature.setData([], [], pxMode=False)
        if self.parent.args.v >= 1: print "Done clearPeakMessage"

    def drawLabCoordinates(self):
        (cenX, cenY) = (-20, -20)  # no offset
        # Draw xy arrows
        symbolSize = 40
        cutoff = symbolSize / 2
        headLen = 30
        tailLen = 30 - cutoff
        xArrow = pg.ArrowItem(angle=180,
                              tipAngle=30,
                              baseAngle=20,
                              headLen=headLen,
                              tailLen=tailLen,
                              tailWidth=8,
                              pen=None,
                              brush='b',
                              pxMode=False)
        xArrow.setPos(2 * headLen + cenX, 0 + cenY)
        self.w1.getView().addItem(xArrow)
        yArrow = pg.ArrowItem(angle=-90,
                              tipAngle=30,
                              baseAngle=20,
                              headLen=headLen,
                              tailLen=tailLen,
                              tailWidth=8,
                              pen=None,
                              brush='r',
                              pxMode=False)
        yArrow.setPos(0 + cenX, 2 * headLen + cenY)
        self.w1.getView().addItem(yArrow)

        # Lab coordinates: Add z-direction
        self.z_direction.setData([0+cenX], [0+cenY], symbol='o', \
                                 size=symbolSize, brush='w', \
                                 pen={'color': 'k', 'width': 4}, pxMode=False)
        self.z_direction1.setData([0+cenX], [0+cenY], symbol='o', \
                                 size=symbolSize/6, brush='k', \
                                 pen={'color': 'k', 'width': 4}, pxMode=False)
        # Lab coordinates: Add xyz text
        self.x_text = pg.TextItem(
            html=
            '<div style="text-align: center"><span style="color: #0000FF; font-size: 16pt;">x</span></div>',
            anchor=(0, 0))
        self.w1.getView().addItem(self.x_text)
        self.x_text.setPos(2 * headLen + cenX, 0 + cenY)
        self.y_text = pg.TextItem(
            html=
            '<div style="text-align: center"><span style="color: #FF0000; font-size: 16pt;">y</span></div>',
            anchor=(1, 1))
        self.w1.getView().addItem(self.y_text)
        self.y_text.setPos(0 + cenX, 2 * headLen + cenY)
        self.z_text = pg.TextItem(
            html=
            '<div style="text-align: center"><span style="color: #FFFFFF; font-size: 16pt;">z</span></div>',
            anchor=(1, 0))
        self.w1.getView().addItem(self.z_text)
        self.z_text.setPos(-headLen + cenX, 0 + cenY)

        # Label xy axes
        self.x_axis = self.w1.getView().getAxis('bottom')
        self.x_axis.setLabel('X-axis (pixels)')
        self.y_axis = self.w1.getView().getAxis('left')
        self.y_axis.setLabel('Y-axis (pixels)')

    def updateImage(self, calib=None):
        if self.parent.hasExperimentName and self.parent.hasRunNumber and self.parent.hasDetInfo:
            if calib is None:
                self.parent.calib, self.parent.data = self.getDetImage(
                    self.parent.eventNumber)
            else:
                _, self.parent.data = self.getDetImage(self.parent.eventNumber,
                                                       calib=calib)

            if self.parent.firstUpdate:
                if self.parent.exp.logscaleOn:
                    self.w1.setImage(
                        np.log10(abs(self.parent.data) + self.parent.eps))
                    self.parent.firstUpdate = False
                else:
                    self.minPercentile = np.percentile(
                        self.parent.data, self.displayMinPercentile)
                    if self.minPercentile < 0: self.minPercentile = 0
                    self.maxPercentile = np.percentile(
                        self.parent.data, self.displayMaxPercentile)
                    self.w1.setImage(self.parent.data,
                                     levels=(self.minPercentile,
                                             self.maxPercentile))
                    self.parent.firstUpdate = False
            else:
                if self.parent.exp.logscaleOn:
                    self.w1.setImage(
                        np.log10(abs(self.parent.data) + self.parent.eps),
                        autoRange=False,
                        autoLevels=False,
                        autoHistogramRange=False)
                else:
                    if self.minPercentile == 0 and self.maxPercentile == 0:
                        self.minPercentile = np.percentile(
                            self.parent.data, self.displayMinPercentile)
                        if self.minPercentile < 0: self.minPercentile = 0
                        self.maxPercentile = np.percentile(
                            self.parent.data, self.displayMaxPercentile)
                        self.w1.setImage(self.parent.data,
                                         levels=(self.minPercentile,
                                                 self.maxPercentile))
                    else:
                        self.w1.setImage(self.parent.data,
                                         autoRange=False,
                                         autoLevels=False,
                                         autoHistogramRange=False)

            try:
                fname = "/reg/d/psdm/cxi/cxitut13/res/psocake/log/" + \
                        self.parent.exp.username + "_" + self.parent.experimentName + "_" \
                        + str(self.parent.runNumber) + "_" + self.parent.detInfo + ".txt"
                with open(fname, "a") as myfile:
                    date = datetime.datetime.today().strftime(
                        '%Y-%m-%d-%H-%M-%S')
                    myStr = date + ": " + str(self.parent.eventNumber) + '\n'
                    myfile.write(myStr)
            except:
                pass

        # Load peak parameters if exists
        if 'sfx' in self.parent.args.mode and self.parent.pk.userUpdate is None:
            self.parent.pk.updateParam()

        if self.parent.args.v >= 1: print "Done updateImage"

    def getCalib(self, evtNumber):
        if self.parent.exp.run is not None:
            self.parent.evt = self.parent.exp.getEvt(evtNumber)
            if self.parent.exp.applyCommonMode:  # play with different common mode
                if self.parent.exp.commonMode[0] == 5:  # Algorithm 5
                    calib = self.parent.det.calib(
                        self.parent.evt,
                        cmpars=(self.parent.exp.commonMode[0],
                                self.parent.exp.commonMode[1]))
                else:  # Algorithms 1 to 4
                    print "### Overriding common mode: ", self.parent.exp.commonMode
                    calib = self.parent.det.calib(
                        self.parent.evt,
                        cmpars=(self.parent.exp.commonMode[0],
                                self.parent.exp.commonMode[1],
                                self.parent.exp.commonMode[2],
                                self.parent.exp.commonMode[3]))
            else:
                calib = self.parent.det.calib(self.parent.evt)
            return calib
        else:
            return None

    def getCommonModeCorrected(self, evtNumber):
        if self.parent.exp.run is not None:
            try:
                self.parent.evt = self.parent.exp.getEvt(evtNumber)
                pedestalCorrected = self.parent.det.raw(
                    self.parent.evt) - self.parent.det.pedestals(
                        self.parent.evt)
                if self.parent.exp.applyCommonMode:  # play with different common mode
                    if self.parent.exp.commonMode[0] == 5:  # Algorithm 5
                        commonMode = self.parent.det.common_mode_correction(
                            self.parent.evt,
                            pedestalCorrected,
                            cmpars=(self.parent.exp.commonMode[0],
                                    self.parent.exp.commonMode[1]))
                        commonModeCorrected = pedestalCorrected - commonMode
                    else:  # Algorithms 1 to 4
                        print "### Overriding common mode: ", self.parent.exp.commonMode
                        commonMode = self.parent.det.common_mode_correction(
                            self.parent.evt,
                            pedestalCorrected,
                            cmpars=(self.parent.exp.commonMode[0],
                                    self.parent.exp.commonMode[1],
                                    self.parent.exp.commonMode[2],
                                    self.parent.exp.commonMode[3]))
                        commonModeCorrected = pedestalCorrected - commonMode
                else:
                    commonMode = self.parent.det.common_mode_correction(
                        self.parent.evt, pedestalCorrected)
                    commonModeCorrected = pedestalCorrected + commonMode  # WHAT! You need to ADD common mode?!!
                return commonModeCorrected
            except:
                return None
        else:
            return None

    def getCommonMode(self, evtNumber):
        if self.parent.exp.run is not None:
            self.parent.evt = self.parent.exp.getEvt(evtNumber)
            pedestalCorrected = self.parent.det.raw(
                self.parent.evt) - self.parent.det.pedestals(self.parent.evt)
            if self.parent.exp.applyCommonMode:  # play with different common mode
                print "### Overriding common mode: ", self.parent.exp.commonMode
                if self.parent.exp.commonMode[0] == 5:  # Algorithm 5
                    cm = self.parent.det.common_mode_correction(
                        self.parent.evt,
                        pedestalCorrected,
                        cmpars=(self.parent.exp.commonMode[0],
                                self.parent.exp.commonMode[1]))
                else:  # Algorithms 1 to 4
                    cm = self.parent.det.common_mode_correction(
                        self.parent.evt,
                        pedestalCorrected,
                        cmpars=(self.parent.exp.commonMode[0],
                                self.parent.exp.commonMode[1],
                                self.parent.exp.commonMode[2],
                                self.parent.exp.commonMode[3]))
            else:
                cm = self.parent.det.common_mode_correction(
                    self.parent.evt, pedestalCorrected)
            return cm
        else:
            return None

    def getAssembledImage(self, arg, calib):
        if arg == 'lcls':
            _calib = calib.copy()  # this is important
            tic = time.time()
            if self.parent.exp.applyFriedel:  # Apply Friedel symmetry
                print "Apply Friedel symmetry"
                centre = self.parent.det.point_indexes(self.parent.evt,
                                                       pxy_um=(0, 0))
                self.fs = FriedelSym(self.parent.exp.detGuaranteedData.shape,
                                     centre)
                data = self.parent.det.image(self.parent.evt, _calib)
                if self.parent.mk.combinedMask is not None:
                    data = self.fs.applyFriedel(
                        data,
                        mask=self.parent.det.image(
                            self.parent.evt, self.parent.mk.combinedMask),
                        mode='same')
                else:
                    data = self.fs.applyFriedel(data, mask=None, mode='same')
            else:
                data = self.parent.det.image(self.parent.evt, _calib)
            if data is None: data = _calib
            toc = time.time()
            if self.parent.args.v >= 1: print "time assemble: ", toc - tic
            return data

    def setupRadialBackground(self):
        self.parent.geom.findPsanaGeometry()
        if self.parent.geom.calibFile is not None:
            if self.parent.args.v >= 1:
                print "calibFile: ", self.parent.geom.calibPath + '/' + self.parent.geom.calibFile
            self.geo = self.parent.det.geometry(
                self.parent.runNumber
            )  #self.geo = GeometryAccess(self.parent.geom.calibPath+'/'+self.parent.geom.calibFile)
            self.xarr, self.yarr, self.zarr = self.geo.get_pixel_coords()
            self.iX, self.iY = self.geo.get_pixel_coord_indexes()
            self.mask = self.geo.get_pixel_mask(
                mbits=0377
            )  # mask for 2x1 edges, two central columns, and unbound pixels with their neighbours
            self.rb = RadialBkgd(self.xarr,
                                 self.yarr,
                                 mask=self.mask,
                                 radedges=None,
                                 nradbins=100,
                                 phiedges=(0, 360),
                                 nphibins=1)
            if self.parent.args.v >= 1: print "Done setupRadialBackground"
        else:
            self.rb = None

    def updatePolarizationFactor(self):
        if self.rb is not None:
            self.pf = polarization_factor(self.rb.pixel_rad(),
                                          self.rb.pixel_phi(),
                                          self.parent.detectorDistance *
                                          1e6)  # convert to um
            if self.parent.args.v >= 1: print "Done updatePolarizationFactor"

    def updateDetectorCentre(self, arg):
        if arg == 'lcls':
            self.parent.cx, self.parent.cy = self.parent.det.point_indexes(
                self.parent.evt, pxy_um=(0, 0))
            if self.parent.cx is None:
                data = self.parent.det.image(self.parent.evt,
                                             self.parent.exp.detGuaranteed)
                self.parent.cx, self.parent.cy = self.getCentre(data.shape)
            if self.parent.args.v >= 1:
                print "cx, cy: ", self.parent.cx, self.parent.cy

    def getDetImage(self, evtNumber, calib=None):
        if calib is None:
            if self.parent.exp.image_property == self.parent.exp.disp_medianCorrection:  # median subtraction
                calib = self.getCalib(evtNumber)
                if calib is None:
                    calib = np.zeros_like(self.parent.exp.detGuaranteed,
                                          dtype='float32')
                calib -= median_filter_ndarr(calib,
                                             self.parent.exp.medianFilterRank)
            elif self.parent.exp.image_property == self.parent.exp.disp_radialCorrection:  # radial subtraction + polarization corrected
                calib = self.getCalib(evtNumber)
                if calib is None:
                    calib = np.zeros_like(self.parent.exp.detGuaranteed,
                                          dtype='float32')
                self.pf.shape = calib.shape  # FIXME: shape is 1d
                calib = self.rb.subtract_bkgd(calib * self.pf)
                calib.shape = self.parent.calib.shape  # FIXME: shape is 1d
            elif self.parent.exp.image_property == self.parent.exp.disp_adu:  # gain and hybrid gain corrected
                calib = self.getCalib(evtNumber)
                if calib is None:
                    calib = np.zeros_like(self.parent.exp.detGuaranteed,
                                          dtype='float32')
            elif self.parent.exp.image_property == self.parent.exp.disp_commonModeCorrected:  # common mode corrected
                calib = self.getCommonModeCorrected(evtNumber)
                if calib is None:
                    calib = np.zeros_like(self.parent.exp.detGuaranteed,
                                          dtype='float32')
            elif self.parent.exp.image_property == self.parent.exp.disp_pedestalCorrected:  # pedestal corrected
                calib = self.parent.det.raw(self.parent.evt).astype('float32')
                if calib is None:
                    calib = np.zeros_like(self.parent.exp.detGuaranteed,
                                          dtype='float32')
                else:
                    calib -= self.parent.det.pedestals(self.parent.evt)
            elif self.parent.exp.image_property == self.parent.exp.disp_raw:  # raw
                calib = self.parent.det.raw(self.parent.evt)
                if calib is None:
                    calib = np.zeros_like(self.parent.exp.detGuaranteed,
                                          dtype='float32')
                self.parent.firstUpdate = True
            elif self.parent.exp.image_property == self.parent.exp.disp_photons:  # photon counts
                calib = self.parent.det.photons(
                    self.parent.evt,
                    mask=self.parent.mk.userMask,
                    adu_per_photon=self.parent.exp.aduPerPhoton)
                if calib is None:
                    calib = np.zeros_like(self.parent.exp.detGuaranteed,
                                          dtype='int32')
                self.parent.firstUpdate = True
            elif self.parent.exp.image_property == self.parent.exp.disp_pedestal:  # pedestal
                calib = self.parent.det.pedestals(self.parent.evt)
                self.parent.firstUpdate = True
            elif self.parent.exp.image_property == self.parent.exp.disp_status:  # status
                calib = self.parent.det.status(self.parent.evt)
                self.parent.firstUpdate = True
            elif self.parent.exp.image_property == self.parent.exp.disp_rms:  # rms
                calib = self.parent.det.rms(self.parent.evt)
                self.parent.firstUpdate = True
            elif self.parent.exp.image_property == self.parent.exp.disp_commonMode:  # common mode
                calib = self.getCommonMode(evtNumber)
                self.parent.firstUpdate = True
            elif self.parent.exp.image_property == self.parent.exp.disp_gain:  # gain
                calib = self.parent.det.gain(self.parent.evt)
                self.parent.firstUpdate = True
            elif self.parent.exp.image_property == self.parent.exp.disp_gainMask:  # gain_mask
                calib = self.parent.det.gain_mask(self.parent.evt)
                self.parent.firstUpdate = True
            elif self.parent.exp.image_property == self.parent.exp.disp_coordx:  # coords_x
                calib = self.parent.det.coords_x(self.parent.evt)
                self.parent.firstUpdate = True
            elif self.parent.exp.image_property == self.parent.exp.disp_coordy:  # coords_y
                calib = self.parent.det.coords_y(self.parent.evt)
                self.parent.firstUpdate = True

            shape = self.parent.det.shape(self.parent.evt)
            if len(shape) == 3:
                if self.parent.exp.image_property == self.parent.exp.disp_quad:  # quad ind
                    calib = np.zeros(shape)
                    for i in range(shape[0]):
                        # TODO: handle detectors properly
                        if shape[0] == 32:  # cspad
                            calib[i, :, :] = int(i) % 8
                        elif shape[0] == 2:  # cspad2x2
                            calib[i, :, :] = int(i) % 2
                        elif shape[0] == 4:  # pnccd
                            calib[i, :, :] = int(i) % 4
                    self.parent.firstUpdate = True
                elif self.parent.exp.image_property == self.parent.exp.disp_seg:  # seg ind
                    calib = np.zeros(shape)
                    if shape[0] == 32:  # cspad
                        for i in range(32):
                            calib[i, :, :] = int(i) / 8
                    elif shape[0] == 2:  # cspad2x2
                        for i in range(2):
                            calib[i, :, :] = int(i)
                    elif shape[0] == 4:  # pnccd
                        for i in range(4):
                            calib[i, :, :] = int(i)
                    self.parent.firstUpdate = True
                elif self.parent.exp.image_property == self.parent.exp.disp_row:  # row ind
                    calib = np.zeros(shape)
                    if shape[0] == 32:  # cspad
                        for i in range(185):
                            calib[:, i, :] = i
                    elif shape[0] == 2:  # cspad2x2
                        for i in range(185):
                            calib[:, i, :] = i
                    elif shape[0] == 4:  # pnccd
                        for i in range(512):
                            calib[:, i, :] = i
                    self.parent.firstUpdate = True
                elif self.parent.exp.image_property == self.parent.exp.disp_col:  # col ind
                    calib = np.zeros(shape)
                    if shape[0] == 32:  # cspad
                        for i in range(388):
                            calib[:, :, i] = i
                    elif shape[0] == 2:  # cspad2x2
                        for i in range(388):
                            calib[:, :, i] = i
                    elif shape[0] == 4:  # pnccd
                        for i in range(512):
                            calib[:, :, i] = i
                    self.parent.firstUpdate = True

        # Update photon energy
        self.parent.exp.updatePhotonEnergy('lcls')

        # Update clen
        self.parent.geom.updateClen('lcls')

        # Write a temporary geom file
        self.parent.geom.deployCrystfelGeometry('lcls')
        self.parent.geom.writeCrystfelGeom('lcls')  # Hack to override coffset

        # Get assembled image
        if calib is not None:
            data = self.getAssembledImage('lcls', calib)
        else:
            calib = np.zeros_like(self.parent.exp.detGuaranteed,
                                  dtype='float32')
            data = self.getAssembledImage('lcls', calib)

        # Update detector centre
        self.updateDetectorCentre('lcls')

        # Update ROI histogram
        if self.parent.roi.roiCurrent == 'rect':
            self.parent.roi.updateRoi(self.parent.roi.roi)
        elif self.parent.roi.roiCurrent == 'poly':
            self.parent.roi.updateRoi(self.parent.roi.roiPoly)
        elif self.parent.roi.roiCurrent == 'circ':
            self.parent.roi.updateRoi(self.parent.roi.roiCircle)

        return calib, data

    def getCentre(self, shape):
        cx = shape[1] / 2
        cy = shape[0] / 2
        return cx, cy
Example #4
0
class PeakFinder:
    def __init__(self,
                 exp,
                 run,
                 detname,
                 evt,
                 detector,
                 algorithm,
                 hitParam_alg_npix_min,
                 hitParam_alg_npix_max,
                 hitParam_alg_amax_thr,
                 hitParam_alg_atot_thr,
                 hitParam_alg_son_min,
                 streakMask_on,
                 streakMask_sigma,
                 streakMask_width,
                 userMask_path,
                 psanaMask_on,
                 psanaMask_calib,
                 psanaMask_status,
                 psanaMask_edges,
                 psanaMask_central,
                 psanaMask_unbond,
                 psanaMask_unbondnrs,
                 generousMask=0,
                 medianFilterOn=0,
                 medianRank=5,
                 radialFilterOn=0,
                 distance=0.0,
                 windows=None,
                 **kwargs):
        self.exp = exp
        self.run = run
        self.detname = detname
        self.det = detector
        self.algorithm = algorithm
        self.maxRes = 0

        self.npix_min = hitParam_alg_npix_min
        self.npix_max = hitParam_alg_npix_max
        self.amax_thr = hitParam_alg_amax_thr
        self.atot_thr = hitParam_alg_atot_thr
        self.son_min = hitParam_alg_son_min

        self.streakMask_on = str2bool(streakMask_on)
        self.streakMask_sigma = streakMask_sigma
        self.streakMask_width = streakMask_width
        self.userMask_path = userMask_path
        self.psanaMask_on = str2bool(psanaMask_on)
        self.psanaMask_calib = str2bool(psanaMask_calib)
        self.psanaMask_status = str2bool(psanaMask_status)
        self.psanaMask_edges = str2bool(psanaMask_edges)
        self.psanaMask_central = str2bool(psanaMask_central)
        self.psanaMask_unbond = str2bool(psanaMask_unbond)
        self.psanaMask_unbondnrs = str2bool(psanaMask_unbondnrs)
        self.generousMaskOn = generousMask

        self.medianFilterOn = medianFilterOn
        self.medianRank = medianRank
        self.radialFilterOn = radialFilterOn
        self.distance = distance

        self.windows = windows

        self.userMask = None
        self.psanaMask = None
        self.streakMask = None
        self.userPsanaMask = None
        self.combinedMask = None
        self.generousMask = None

        # Make user mask
        if self.userMask_path is not None:
            self.userMask = np.load(self.userMask_path)

        if facility == 'LCLS':
            # Make psana mask
            if self.psanaMask_on:
                self.psanaMask = detector.mask(
                    evt,
                    calib=self.psanaMask_calib,
                    status=self.psanaMask_status,
                    edges=self.psanaMask_edges,
                    central=self.psanaMask_central,
                    unbond=self.psanaMask_unbond,
                    unbondnbrs=self.psanaMask_unbondnrs)
                if self.generousMaskOn:
                    self.psanaMask = self.generousBadPixel(self.psanaMask)
            # Combine userMask and psanaMask
            self.userPsanaMask = np.ones_like(self.det.calib(evt),
                                              dtype=np.int16)
            if self.userMask is not None:
                self.userPsanaMask *= self.userMask
            if self.psanaMask is not None:
                self.userPsanaMask *= self.psanaMask
        elif facility == 'PAL':
            self.userPsanaMask = self.userMask

        # Powder of hits and misses
        self.powderHits = None
        self.powderMisses = None

        # set algorithm specific parameters
        if algorithm == 1:
            self.hitParam_alg1_thr_low = kwargs["alg1_thr_low"]
            self.hitParam_alg1_thr_high = kwargs["alg1_thr_high"]
            self.hitParam_alg1_rank = int(kwargs["alg1_rank"])
            self.hitParam_alg1_radius = int(kwargs["alg1_radius"])
            self.hitParam_alg1_dr = kwargs["alg1_dr"]
        elif algorithm == 2:
            self.hitParam_alg1_thr_low = kwargs["alg1_thr_low"]
            self.hitParam_alg1_thr_high = kwargs["alg1_thr_high"]
            self.hitParam_alg1_rank = int(kwargs["alg1_rank"])
            self.hitParam_alg1_radius = int(kwargs["alg1_radius"])
            self.hitParam_alg1_dr = kwargs["alg1_dr"]
        elif algorithm == 3:
            self.hitParam_alg3_rank = kwargs["alg3_rank"]
            self.hitParam_alg3_r0 = int(kwargs["alg3_r0"])
            self.hitParam_alg3_dr = kwargs["alg3_dr"]
        elif algorithm == 4:
            self.hitParam_alg4_thr_low = kwargs["alg4_thr_low"]
            self.hitParam_alg4_thr_high = kwargs["alg4_thr_high"]
            self.hitParam_alg4_rank = int(kwargs["alg4_rank"])
            self.hitParam_alg4_r0 = int(kwargs["alg4_r0"])
            self.hitParam_alg4_dr = kwargs["alg4_dr"]

        if facility == 'LCLS':
            self.access = kwargs["access"]
            if self.algorithm == 1:
                self.alg = PyAlgos(mask=None, pbits=0)
                self.peakRadius = int(self.hitParam_alg1_radius)
                self.alg.set_peak_selection_pars(npix_min=self.npix_min, npix_max=self.npix_max, \
                                                 amax_thr=self.amax_thr, atot_thr=self.atot_thr, \
                                                 son_min=self.son_min)
                #self.alg = myskbeam.DropletA(self.peakRadius, self.peakRadius+self.hitParam_alg1_dr) #PyAlgos(windows=self.windows, mask=None, pbits=0)
            elif self.algorithm == 2:
                # set peak-selector parameters:
                self.alg = PyAlgos(mask=None, pbits=0)
                self.peakRadius = int(self.hitParam_alg1_radius)
                self.alg.set_peak_selection_pars(npix_min=self.npix_min, npix_max=self.npix_max, \
                                                 amax_thr=self.amax_thr, atot_thr=self.atot_thr, \
                                                 son_min=self.son_min)
        elif facility == 'PAL':
            self.peakRadius = int(self.hitParam_alg1_radius)
            self.alg = myskbeam.DropletA(self.peakRadius,
                                         self.hitParam_alg1_dr)

        if facility == 'LCLS':
            self.StreakMask = myskbeam.StreakMask(self.det,
                                                  evt,
                                                  width=self.streakMask_width,
                                                  sigma=self.streakMask_sigma)
            self.cx, self.cy = self.det.point_indexes(evt, pxy_um=(0, 0))
            self.iX = np.array(self.det.indexes_x(evt), dtype=np.int64)
            self.iY = np.array(self.det.indexes_y(evt), dtype=np.int64)
            if len(self.iX.shape) == 2:
                self.iX = np.expand_dims(self.iX, axis=0)
                self.iY = np.expand_dims(self.iY, axis=0)
            # Initialize radial background subtraction
            self.setupExperiment()
            if self.radialFilterOn:
                self.setupRadialBackground()
                self.updatePolarizationFactor()
        elif facility == 'PAL':
            self.geom = kwargs["geom"]
            with open(self.geom, 'r') as f:
                lines = f.readlines()
            for i, line in enumerate(lines):
                if 'p0/max_ss' in line:
                    dim0 = int(line.split('=')[-1]) + 1
                elif 'p0/max_fs' in line:
                    dim1 = int(line.split('=')[-1]) + 1
                elif 'p0/corner_x' in line:
                    self.cy = -1 * float(line.split('=')[-1])
                elif 'p0/corner_y' in line:
                    self.cx = float(line.split('=')[-1])
            self.iy = np.tile(np.arange(dim0), [dim1, 1])
            self.ix = np.transpose(self.iy)
            self.iX = np.array(self.ix, dtype=np.int64)
            self.iY = np.array(self.iy, dtype=np.int64)

    def generousBadPixel(self, unassemMask, n=10):
        generousBadPixelMask = unassemMask
        (numAsic, numFs, numSs) = unassemMask.shape
        for i in range(numAsic):
            for a in range(numSs):
                numBadPixels = len(np.where(unassemMask[i, :, a] == 0)[0])
                if numBadPixels >= n:
                    generousBadPixelMask[i, :, a] = 0
        return generousBadPixelMask

    def setupExperiment(self):
        access = 'exp=' + str(self.exp) + ':run=' + str(self.run) + ':idx'
        if 'ffb' in self.access.lower():
            access += ':dir=/reg/d/ffb/' + self.exp[:3] + '/' + self.exp + '/xtc'
        self.ds = psana.DataSource(access)
        self.run = self.ds.runs().next()
        self.times = self.run.times()
        self.eventTotal = len(self.times)
        self.env = self.ds.env()
        self.evt = self.run.event(self.times[0])
        self.det = psana.Detector(str(self.detname), self.env)
        self.det.do_reshape_2d_to_3d(flag=True)

    def setupRadialBackground(self):
        self.geo = self.det.geometry(
            self.run
        )  # self.geo = GeometryAccess(self.parent.geom.calibPath+'/'+self.parent.geom.calibFile)
        self.xarr, self.yarr, self.zarr = self.geo.get_pixel_coords()
        self.ix = self.det.indexes_x(self.evt)
        self.iy = self.det.indexes_y(self.evt)
        if self.ix is None:
            self.iy = np.tile(np.arange(self.userMask.shape[1]),
                              [self.userMask.shape[2], 1])
            self.ix = np.transpose(self.iy)
        self.iX = np.array(self.ix, dtype=np.int64)
        self.iY = np.array(self.iy, dtype=np.int64)
        if len(self.iX.shape) == 2:
            self.iX = np.expand_dims(self.iX, axis=0)
            self.iY = np.expand_dims(self.iY, axis=0)
        self.mask = self.geo.get_pixel_mask(
            mbits=0377
        )  # mask for 2x1 edges, two central columns, and unbound pixels with their neighbours
        self.rb = RadialBkgd(self.xarr,
                             self.yarr,
                             mask=self.mask,
                             radedges=None,
                             nradbins=100,
                             phiedges=(0, 360),
                             nphibins=1)

    def updatePolarizationFactor(self):
        self.pf = polarization_factor(self.rb.pixel_rad(), self.rb.pixel_phi(),
                                      self.distance * 1e6)  # convert to um

    def findPeaks(self, calib, evt, thr_high=None, thr_low=None):

        if facility == 'LCLS':
            if self.streakMask_on:  # make new streak mask
                self.streakMask = self.StreakMask.getStreakMaskCalib(evt)

            # Apply background correction
            if self.medianFilterOn:
                calib -= median_filter_ndarr(calib, self.medianRank)

            if self.radialFilterOn:
                self.pf.shape = calib.shape  # FIXME: shape is 1d
                calib = self.rb.subtract_bkgd(calib * self.pf)
                calib.shape = self.userPsanaMask.shape  # FIXME: shape is 1d

            if self.streakMask is not None:
                self.combinedMask = self.userPsanaMask * self.streakMask
            else:
                self.combinedMask = self.userPsanaMask

            # set new mask
            #self.alg.set_mask(self.combinedMask) # This doesn't work reliably
        elif facility == 'PAL':
            self.combinedMask = self.userMask

        # set algorithm specific parameters
        if self.algorithm == 1:
            if facility == 'LCLS':
                #print "param: ", self.npix_min, self.npix_max, self.atot_thr, self.son_min, thr_low, thr_high, np.sum(self.combinedMask)
                # v1 - aka Droplet Finder - two-threshold peak-finding algorithm in restricted region
                #                           around pixel with maximal intensity.
                if thr_high is None:  # use gui input
                    self.peakRadius = int(self.hitParam_alg1_radius)
                    self.peaks = self.alg.peak_finder_v4r3(
                        calib,
                        thr_low=self.hitParam_alg1_thr_low,
                        thr_high=self.hitParam_alg1_thr_high,
                        rank=self.hitParam_alg1_rank,
                        r0=self.hitParam_alg1_radius,
                        dr=self.hitParam_alg1_dr,
                        mask=self.combinedMask.astype(np.uint16))
#                    self.peaks = self.alg.peak_finder_v4r2(calib,
#                                                           thr_low=self.hitParam_alg1_thr_low,
#                                                           thr_high=self.hitParam_alg1_thr_high,
#                                                           rank=self.hitParam_alg1_rank,
#                                                           r0=self.hitParam_alg1_radius,
#                                                           dr=self.hitParam_alg1_dr)
                else:
                    self.peaks = self.alg.findPeaks(calib,
                                                    npix_min=self.npix_min,
                                                    npix_max=self.npix_max,
                                                    atot_thr=self.atot_thr,
                                                    son_min=self.son_min,
                                                    thr_low=thr_low,
                                                    thr_high=thr_high,
                                                    mask=self.combinedMask)


#                    self.peaks = self.alg.peak_finder_v4r2(calib,
#                                                           thr_low=thr_low,
#                                                           thr_high=thr_high,
#                                                           rank=self.hitParam_alg1_rank,
#                                                           r0=self.hitParam_alg1_radius,
#                                                           dr=self.hitParam_alg1_dr)
            elif facility == 'PAL':
                self.peakRadius = int(self.hitParam_alg1_radius)
                _calib = np.zeros((1, calib.shape[0], calib.shape[1]))
                _calib[0, :, :] = calib
                if self.combinedMask is None:
                    _mask = None
                else:
                    _mask = self.combinedMask.astype(np.uint16)

                self.peaks = self.alg.findPeaks(
                    _calib,
                    npix_min=self.npix_min,
                    npix_max=self.npix_max,
                    son_min=self.son_min,
                    thr_low=self.hitParam_alg1_thr_low,
                    thr_high=self.hitParam_alg1_thr_high,
                    atot_thr=self.atot_thr,
                    r0=self.peakRadius,
                    dr=int(self.hitParam_alg1_dr),
                    mask=_mask)
        elif self.algorithm == 2:
            if facility == 'LCLS':
                #print "param: ", self.npix_min, self.npix_max, self.atot_thr, self.son_min, thr_low, thr_high, np.sum(self.combinedMask)
                # v1 - aka Droplet Finder - two-threshold peak-finding algorithm in restricted region
                #                           around pixel with maximal intensity.
                self.peakRadius = int(self.hitParam_alg1_radius)
                self.peaks = self.alg.peak_finder_v3r3(
                    calib,
                    rank=int(self.hitParam_alg1_rank),
                    r0=self.peakRadius,
                    dr=self.hitParam_alg1_dr,
                    nsigm=self.son_min,
                    mask=self.combinedMask.astype(np.uint16))
        elif self.algorithm == 3:
            self.peaks = self.alg.peak_finder_v3(calib,
                                                 rank=self.hitParam_alg3_rank,
                                                 r0=self.hitParam_alg3_r0,
                                                 dr=self.hitParam_alg3_dr)
        elif self.algorithm == 4:
            # v4 - aka iDroplet Finder - two-threshold peak-finding algorithm in restricted region
            #                            around pixel with maximal intensity.
            self.peaks = self.alg.peak_finder_v4(calib, thr_low=self.hitParam_alg4_thr_low, thr_high=self.hitParam_alg4_thr_high, \
                                   rank=self.hitParam_alg4_rank, r0=self.hitParam_alg4_r0, dr=self.hitParam_alg4_dr)
        self.numPeaksFound = self.peaks.shape[0]

        if self.numPeaksFound > 0:
            if facility == 'LCLS':
                cenX = self.iX[np.array(self.peaks[:, 0], dtype=np.int64),
                               np.array(self.peaks[:, 1], dtype=np.int64),
                               np.array(self.peaks[:,
                                                   2], dtype=np.int64)] + 0.5
                cenY = self.iY[np.array(self.peaks[:, 0], dtype=np.int64),
                               np.array(self.peaks[:, 1], dtype=np.int64),
                               np.array(self.peaks[:,
                                                   2], dtype=np.int64)] + 0.5
            elif facility == 'PAL':
                cenX = self.iX[np.array(self.peaks[:, 1], dtype=np.int64),
                               np.array(self.peaks[:,
                                                   2], dtype=np.int64)] + 0.5
                cenY = self.iY[np.array(self.peaks[:, 1], dtype=np.int64),
                               np.array(self.peaks[:,
                                                   2], dtype=np.int64)] + 0.5
            self.maxRes = getMaxRes(cenX, cenY, self.cx, self.cy)
        else:
            self.maxRes = 0

        if self.numPeaksFound >= 15:
            if self.powderHits is None:
                self.powderHits = calib
            else:
                self.powderHits = np.maximum(self.powderHits, calib)
        else:
            if self.powderMisses is None:
                self.powderMisses = calib
            else:
                self.powderMisses = np.maximum(self.powderMisses, calib)

        if self.powderHits is None: self.powderHits = np.zeros_like(calib)
        if self.powderMisses is None: self.powderMisses = np.zeros_like(calib)
Example #5
0
class PeakFinder:
    def __init__(self,
                 exp,
                 run,
                 detname,
                 evt,
                 detector,
                 algorithm,
                 hitParam_alg_npix_min,
                 hitParam_alg_npix_max,
                 hitParam_alg_amax_thr,
                 hitParam_alg_atot_thr,
                 hitParam_alg_son_min,
                 streakMask_on,
                 streakMask_sigma,
                 streakMask_width,
                 userMask_path,
                 psanaMask_on,
                 psanaMask_calib,
                 psanaMask_status,
                 psanaMask_edges,
                 psanaMask_central,
                 psanaMask_unbond,
                 psanaMask_unbondnrs,
                 medianFilterOn=0,
                 medianRank=5,
                 radialFilterOn=0,
                 distance=0.0,
                 windows=None,
                 **kwargs):
        self.exp = exp
        self.run = run
        self.detname = detname
        self.det = detector
        self.algorithm = algorithm
        self.maxRes = 0

        self.npix_min = hitParam_alg_npix_min
        self.npix_max = hitParam_alg_npix_max
        self.amax_thr = hitParam_alg_amax_thr
        self.atot_thr = hitParam_alg_atot_thr
        self.son_min = hitParam_alg_son_min

        self.streakMask_on = str2bool(streakMask_on)
        self.streakMask_sigma = streakMask_sigma
        self.streakMask_width = streakMask_width
        self.userMask_path = userMask_path
        self.psanaMask_on = str2bool(psanaMask_on)
        self.psanaMask_calib = str2bool(psanaMask_calib)
        self.psanaMask_status = str2bool(psanaMask_status)
        self.psanaMask_edges = str2bool(psanaMask_edges)
        self.psanaMask_central = str2bool(psanaMask_central)
        self.psanaMask_unbond = str2bool(psanaMask_unbond)
        self.psanaMask_unbondnrs = str2bool(psanaMask_unbondnrs)

        self.medianFilterOn = medianFilterOn
        self.medianRank = medianRank
        self.radialFilterOn = radialFilterOn
        self.distance = distance

        self.windows = windows

        self.userMask = None
        self.psanaMask = None
        self.streakMask = None
        self.userPsanaMask = None
        self.combinedMask = None

        # Make user mask
        if self.userMask_path is not None:
            self.userMask = np.load(self.userMask_path)

        if facility == 'LCLS':
            # Make psana mask
            self.psanaMask = detector.mask(run,
                                           calib=self.psanaMask_calib,
                                           status=self.psanaMask_status,
                                           edges=self.psanaMask_edges,
                                           central=self.psanaMask_central,
                                           unbond=self.psanaMask_unbond,
                                           unbondnbrs=self.psanaMask_unbondnrs)
            # Combine userMask and psanaMask
            self.userPsanaMask = np.ones_like(self.psanaMask, dtype=np.int16)
            if self.userMask is not None:
                self.userPsanaMask *= self.userMask
            if self.psanaMask_on:
                self.userPsanaMask *= self.psanaMask

        # Powder of hits and misses
        self.powderHits = None
        self.powderMisses = None

        # set algorithm specific parameters
        if algorithm == 1:
            self.hitParam_alg1_thr_low = kwargs["alg1_thr_low"]
            self.hitParam_alg1_thr_high = kwargs["alg1_thr_high"]
            self.hitParam_alg1_rank = int(kwargs["alg1_rank"])
            self.hitParam_alg1_radius = int(kwargs["alg1_radius"])
            self.hitParam_alg1_dr = kwargs["alg1_dr"]
        elif algorithm >= 2:
            self.hitParam_alg1_thr_low = kwargs["alg1_thr_low"]
            self.hitParam_alg1_thr_high = kwargs["alg1_thr_high"]
            self.hitParam_alg1_rank = int(kwargs["alg1_rank"])
            self.hitParam_alg1_radius = int(kwargs["alg1_radius"])
            self.hitParam_alg1_dr = kwargs["alg1_dr"]

        if facility == 'LCLS':
            self.access = kwargs["access"]
            if self.algorithm == 1:
                self.alg = PyAlgos(mask=None, pbits=0)
                self.peakRadius = int(self.hitParam_alg1_radius)
                self.alg.set_peak_selection_pars(npix_min=self.npix_min, npix_max=self.npix_max, \
                                                 amax_thr=self.amax_thr, atot_thr=self.atot_thr, \
                                                 son_min=self.son_min)
            elif self.algorithm >= 2:
                self.alg = PyAlgos(mask=None, pbits=0)
                self.peakRadius = int(self.hitParam_alg1_radius)
                self.alg.set_peak_selection_pars(npix_min=self.npix_min, npix_max=self.npix_max, \
                                                 amax_thr=self.amax_thr, atot_thr=self.atot_thr, \
                                                 son_min=self.son_min)

        if facility == 'LCLS':
            self.StreakMask = myskbeam.StreakMask(self.det,
                                                  evt,
                                                  width=self.streakMask_width,
                                                  sigma=self.streakMask_sigma)
            #self.cx, self.cy = self.det.point_indexes(evt, pxy_um=(0, 0))
            try:
                self.cy, self.cx = self.det.point_indexes(
                    evt,
                    pxy_um=(0, 0),
                    pix_scale_size_um=None,
                    xy0_off_pix=None,
                    cframe=gu.CFRAME_PSANA,
                    fract=True)
            except AttributeError:
                self.cx, self.cy = self.det.point_indexes(evt, pxy_um=(0, 0))
            self.iX = np.array(self.det.indexes_x(evt), dtype=np.int64)
            self.iY = np.array(self.det.indexes_y(evt), dtype=np.int64)
            if len(self.iX.shape) == 2:
                self.iX = np.expand_dims(self.iX, axis=0)
                self.iY = np.expand_dims(self.iY, axis=0)
            # Initialize radial background subtraction
            self.setupExperiment()
            if self.radialFilterOn:
                self.setupRadialBackground()
                self.updatePolarizationFactor()

    def setupExperiment(self):
        access = 'exp=' + str(self.exp) + ':run=' + str(self.run) + ':idx'
        if 'ffb' in self.access.lower():
            access += ':dir=/reg/d/ffb/' + self.exp[:3] + '/' + self.exp + '/xtc'
        self.ds = psana.DataSource(access)
        self.run = next(self.ds.runs())
        self.times = self.run.times()
        self.eventTotal = len(self.times)
        self.env = self.ds.env()
        self.evt = self.run.event(self.times[0])
        self.det = psana.Detector(str(self.detname), self.env)
        self.det.do_reshape_2d_to_3d(flag=True)

    def setupRadialBackground(self):
        self.geo = self.det.geometry(
            self.run
        )  # self.geo = GeometryAccess(self.parent.geom.calibPath+'/'+self.parent.geom.calibFile)
        self.xarr, self.yarr, self.zarr = self.geo.get_pixel_coords()
        self.ix = self.det.indexes_x(self.evt)
        self.iy = self.det.indexes_y(self.evt)
        if self.ix is None:
            self.iy = np.tile(np.arange(self.userMask.shape[1]),
                              [self.userMask.shape[2], 1])
            self.ix = np.transpose(self.iy)
        self.iX = np.array(self.ix, dtype=np.int64)
        self.iY = np.array(self.iy, dtype=np.int64)
        if len(self.iX.shape) == 2:
            self.iX = np.expand_dims(self.iX, axis=0)
            self.iY = np.expand_dims(self.iY, axis=0)
        self.mask = self.geo.get_pixel_mask(
            mbits=0o0377
        )  # mask for 2x1 edges, two central columns, and unbound pixels with their neighbours
        self.rb = RadialBkgd(self.xarr,
                             self.yarr,
                             mask=self.mask,
                             radedges=None,
                             nradbins=100,
                             phiedges=(0, 360),
                             nphibins=1)

    def updatePolarizationFactor(self):
        # FIXME: handle vertical/horizontal polarization properly
        self.pf = polarization_factor(self.rb.pixel_rad(),
                                      self.rb.pixel_phi() + 90,
                                      self.distance * 1e6)  # convert to um

    def findPeaks(self, calib, evt, minPeaks=15, thr_high=None, thr_low=None):
        #t0 = time.time()
        if facility == 'LCLS':
            if self.streakMask_on:  # make new streak mask
                self.streakMask = self.StreakMask.getStreakMaskCalib(evt)

            # Apply background correction
            if self.medianFilterOn:
                calib -= median_filter_ndarr(calib, self.medianRank)

            if self.radialFilterOn:
                self.pf.shape = calib.shape  # FIXME: shape is 1d
                calib = self.rb.subtract_bkgd(calib * self.pf)
                calib.shape = self.userPsanaMask.shape  # FIXME: shape is 1d

            self.calib = calib  # save background subtracted calib as an attribute

            if self.streakMask is not None:
                self.combinedMask = self.userPsanaMask * self.streakMask
            else:
                self.combinedMask = self.userPsanaMask
        #t1 = time.time()
        # set algorithm specific parameters
        if self.algorithm == 1:
            if facility == 'LCLS':
                # v1 - aka Droplet Finder - two-threshold peak-finding algorithm in restricted region
                #                           around pixel with maximal intensity.
                if thr_high is None:  # use gui input
                    self.peakRadius = int(self.hitParam_alg1_radius)
                    self.peaks = self.alg.peak_finder_v4r3(
                        calib,
                        thr_low=self.hitParam_alg1_thr_low,
                        thr_high=self.hitParam_alg1_thr_high,
                        rank=self.hitParam_alg1_rank,
                        r0=self.hitParam_alg1_radius,
                        dr=self.hitParam_alg1_dr,
                        mask=self.combinedMask.astype(np.uint16))
                else:
                    self.peaks = self.alg.findPeaks(calib,
                                                    npix_min=self.npix_min,
                                                    npix_max=self.npix_max,
                                                    atot_thr=self.atot_thr,
                                                    son_min=self.son_min,
                                                    thr_low=thr_low,
                                                    thr_high=thr_high,
                                                    mask=self.combinedMask)
        elif self.algorithm == 2:
            if facility == 'LCLS':
                # Adaptive peak finder v3r3
                self.peakRadius = int(self.hitParam_alg1_radius)
                self.peaks = self.alg.peak_finder_v3r3(
                    calib,
                    rank=int(self.hitParam_alg1_rank),
                    r0=self.peakRadius,
                    dr=self.hitParam_alg1_dr,
                    nsigm=self.son_min,
                    mask=self.combinedMask.astype(np.uint16))
        elif self.algorithm == 3:
            if facility == 'LCLS':
                # perform binning here
                binr = 2
                binc = 2
                downCalib = sm.block_reduce(calib,
                                            block_size=(1, binr, binc),
                                            func=np.sum)
                downWeight = sm.block_reduce(self.combinedMask,
                                             block_size=(1, binr, binc),
                                             func=np.sum)
                warr = np.zeros_like(downCalib, dtype='float32')
                ind = np.where(downWeight > 0)
                warr[ind] = downCalib[ind] / downWeight[ind]
                upCalib = utils.upsample(warr, calib.shape, binr, binc)
                self.peakRadius = int(self.hitParam_alg1_radius)
                self.peaks = self.alg.peak_finder_v3r3(
                    upCalib,
                    rank=int(self.hitParam_alg1_rank),
                    r0=self.peakRadius,
                    dr=self.hitParam_alg1_dr,
                    nsigm=self.son_min,
                    mask=self.combinedMask.astype(np.uint16))
        #t2 = time.time()
        self.numPeaksFound = self.peaks.shape[0]

        if self.numPeaksFound >= minPeaks:
            if facility == 'LCLS':
                cenX = self.iX[np.array(self.peaks[:, 0], dtype=np.int64),
                               np.array(self.peaks[:, 1], dtype=np.int64),
                               np.array(self.peaks[:,
                                                   2], dtype=np.int64)] + 0.5
                cenY = self.iY[np.array(self.peaks[:, 0], dtype=np.int64),
                               np.array(self.peaks[:, 1], dtype=np.int64),
                               np.array(self.peaks[:,
                                                   2], dtype=np.int64)] + 0.5
            self.maxRes = getMaxRes(cenX, cenY, self.cx, self.cy)
        else:
            self.maxRes = 0
        #t3 = time.time()
        if self.numPeaksFound >= minPeaks:
            if self.powderHits is None:
                self.powderHits = calib
            else:
                self.powderHits = np.maximum(self.powderHits, calib)
        else:
            if self.powderMisses is None:
                self.powderMisses = calib
            else:
                self.powderMisses = np.maximum(self.powderMisses, calib)

        if self.powderHits is None: self.powderHits = np.zeros_like(calib)
        if self.powderMisses is None: self.powderMisses = np.zeros_like(calib)
Example #6
0
class psanaWhisperer():
    def __init__(self,
                 experimentName,
                 runNumber,
                 detInfo,
                 clen='',
                 aduPerPhoton=1,
                 localCalib=False):
        self.experimentName = experimentName
        self.runNumber = runNumber
        self.detInfo = detInfo
        self.clenStr = clen
        self.aduPerPhoton = aduPerPhoton
        self.localCalib = localCalib

    def setupExperiment(self):
        self.ds = psana.DataSource('exp=' + str(self.experimentName) +
                                   ':run=' + str(self.runNumber) + ':idx')
        self.run = self.ds.runs().next()
        self.times = self.run.times()
        self.eventTotal = len(self.times)
        self.env = self.ds.env()
        self.evt = self.run.event(self.times[0])
        self.det = psana.Detector(str(self.detInfo), self.env)
        self.det.do_reshape_2d_to_3d(flag=True)
        self.getDetInfoList()
        self.detAlias = self.getDetectorAlias(str(self.detInfo))
        self.updateClen()  # Get epics variable, clen

    def updateClen(self):
        if 'cspad' in self.detInfo.lower() and 'cxi' in self.experimentName:
            self.epics = self.ds.env().epicsStore()
            self.clen = self.epics.value(self.clenStr)
        elif 'rayonix' in self.detInfo.lower(
        ) and 'mfx' in self.experimentName:
            self.epics = self.ds.env().epicsStore()
            self.clen = self.epics.value(self.clenStr)
        elif 'rayonix' in self.detInfo.lower(
        ) and 'xpp' in self.experimentName:
            self.epics = self.ds.env().epicsStore()
            self.clen = self.epics.value(self.clenStr)

    def getDetectorAlias(self, srcOrAlias):
        for i in self.detInfoList:
            src, alias, _ = i
            if srcOrAlias.lower() == src.lower() or srcOrAlias.lower(
            ) == alias.lower():
                return alias

    def getDetInfoList(self):
        myAreaDetectors = []
        self.detnames = psana.DetNames()
        for k in self.detnames:
            try:
                if Detector.PyDetector.dettype(str(
                        k[0]), self.env) == Detector.AreaDetector.AreaDetector:
                    myAreaDetectors.append(k)
            except ValueError:
                continue
        self.detInfoList = list(set(myAreaDetectors))

    def getEvent(self, number):
        self.evt = self.run.event(self.times[number])

    def getImg(self, number):
        self.getEvent(number)
        img = self.det.image(self.evt, self.det.calib(self.evt))
        return img

    def getImg(self):
        if self.evt is not None:
            img = self.det.image(self.evt, self.det.calib(self.evt))
            return img
        return None

    def getCheetahImg(self, calib=None):
        """Converts seg, row, col assuming (32,185,388)
           to cheetah 2-d table row and col (8*185, 4*388)
        """
        if 'cspad2x2' in self.detInfo.lower():
            print "Not implemented yet: cspad2x2"
        elif 'cspad' in self.detInfo.lower():
            if calib is None: calib = self.det.calib(self.evt)  # (32,185,388)
            img = np.zeros((8 * 185, 4 * 388))
            counter = 0
            for quad in range(4):
                for seg in range(8):
                    img[seg * 185:(seg + 1) * 185,
                        quad * 388:(quad + 1) * 388] = calib[counter, :, :]
                    counter += 1
        elif 'rayonix' in self.detInfo.lower():
            if calib is None:
                img = np.squeeze(self.det.calib(self.evt))  # (1920,1920)
            else:
                img = np.squeeze(calib)
        return img

    def getCleanAssembledImg(self, backgroundEvent):
        """Returns psana assembled image
        """
        backgroundEvt = self.run.event(self.times[backgroundEvent])
        backgroundCalib = self.det.calib(backgroundEvt)
        calib = self.det.calib(self.evt)
        cleanCalib = calib - backgroundCalib
        img = self.det.image(self.evt, cleanCalib)
        return img

    def getAssembledImg(self):
        """Returns psana assembled image
        """
        img = self.det.image(self.evt)
        return img

    def getCalibImg(self):
        """Returns psana assembled image
        """
        img = self.det.calib(self.evt)
        return img

    def getCleanAssembledPhotons(self, backgroundEvent):
        """Returns psana assembled image in photon counts
        """
        backgroundEvt = self.run.event(self.times[backgroundEvent])
        backgroundCalib = self.det.calib(backgroundEvt)
        calib = self.det.calib(self.evt)
        cleanCalib = calib - backgroundCalib
        img = self.det.photons(self.evt,
                               nda_calib=cleanCalib,
                               adu_per_photon=self.aduPerPhoton)
        phot = self.det.image(self.evt, img)
        return phot

    def getAssembledPhotons(self):
        """Returns psana assembled image in photon counts
        """
        img = self.det.photons(self.evt, adu_per_photon=self.aduPerPhoton)
        phot = self.det.image(self.evt, img)
        return phot

    def getPsanaEvent(self, cheetahFilename):
        # Gets psana event given cheetahFilename, e.g. LCLS_2015_Jul26_r0014_035035_e820.h5
        hrsMinSec = cheetahFilename.split('_')[-2]
        fid = int(cheetahFilename.split('_')[-1].split('.')[0], 16)
        for t in self.times:
            if t.fiducial() == fid:
                localtime = time.strftime('%H:%M:%S',
                                          time.localtime(t.seconds()))
                localtime = localtime.replace(':', '')
                if localtime[0:3] == hrsMinSec[0:3]:
                    self.evt = self.run.event(t)
                else:
                    self.evt = None

    def getStartTime(self):
        self.evt = self.run.event(self.times[0])
        evtId = self.evt.get(psana.EventId)
        sec = evtId.time()[0]
        nsec = evtId.time()[1]
        fid = evtId.fiducials()
        return time.strftime('%FT%H:%M:%S-0800',
                             time.localtime(sec))  # Hard-coded pacific time

    #####################################################################
    # TODO: Functions below are not being used yet
    #####################################################################
    def findPsanaGeometry(self):
        try:
            self.source = psana.Detector.PyDetector.map_alias_to_source(
                self.detInfo, self.ds.env())  # 'DetInfo(CxiDs2.0:Cspad.0)'
            self.calibSource = self.source.split('(')[-1].split(')')[
                0]  # 'CxiDs2.0:Cspad.0'
            self.detectorType = gu.det_type_from_source(self.source)  # 1
            self.calibGroup = gu.dic_det_type_to_calib_group[
                self.detectorType]  # 'CsPad::CalibV1'
            self.detectorName = gu.dic_det_type_to_name[
                self.detectorType].upper()  # 'CSPAD'
            if self.localCalib:
                self.calibPath = "./calib/" + self.calibGroup + "/" + self.calibSource + "/geometry"
            else:
                self.calibPath = "/reg/d/psdm/" + self.parent.experimentName[0:3] + \
                                 "/" + self.parent.experimentName + "/calib/" + \
                                 self.calibGroup + "/" + self.calibSource + "/geometry"

            # Determine which calib file to use
            geometryFiles = os.listdir(self.calibPath)
            self.calibFile = None
            minDiff = -1e6
            for fname in geometryFiles:
                if fname.endswith('.data'):
                    endValid = False
                    startNum = int(fname.split('-')[0])
                    endNum = fname.split('-')[-1].split('.data')[0]
                    diff = startNum - self.parent.runNumber
                    # Make sure it's end number is valid too
                    if 'end' in endNum:
                        endValid = True
                    else:
                        try:
                            if self.parent.runNumber <= int(endNum):
                                endValid = True
                        except:
                            continue
                    if diff <= 0 and diff > minDiff and endValid is True:
                        minDiff = diff
                        self.calibFile = fname
        except:
            if self.parent.args.v >= 1: print "Couldn't find psana geometry"
            self.calibFile = None

    def setupRadialBackground(self):
        self.findPsanaGeometry()
        if self.calibFile is not None:
            self.geo = GeometryAccess(self.calibPath + '/' + self.calibFile)
            self.xarr, self.yarr, self.zarr = self.geo.get_pixel_coords()
            self.iX, self.iY = self.geo.get_pixel_coord_indexes()
            self.mask = self.geo.get_pixel_mask(
                mbits=0377
            )  # mask for 2x1 edges, two central columns, and unbound pixels with their neighbours
            self.rb = RadialBkgd(self.xarr,
                                 self.yarr,
                                 mask=self.mask,
                                 radedges=None,
                                 nradbins=100,
                                 phiedges=(0, 360),
                                 nphibins=1)
        else:
            self.rb = None

    def updatePolarizationFactor(self, detectorDistance_in_m):
        if self.rb is not None:
            self.pf = polarization_factor(self.rb.pixel_rad(),
                                          self.rb.pixel_phi(),
                                          detectorDistance_in_m *
                                          1e6)  # convert to um

    def getCalib(self, evtNumber):
        if self.run is not None:
            self.evt = self.getEvent(evtNumber)
            if self.applyCommonMode:  # play with different common mode
                if self.commonMode[0] == 5:  # Algorithm 5
                    calib = self.det.calib(self.evt,
                                           cmpars=(self.commonMode[0],
                                                   self.commonMode[1]))
                else:  # Algorithms 1 to 4
                    print "### Overriding common mode: ", self.commonMode
                    calib = self.det.calib(
                        self.evt,
                        cmpars=(self.commonMode[0], self.commonMode[1],
                                self.commonMode[2], self.commonMode[3]))
            else:
                calib = self.det.calib(self.evt)
            return calib
        else:
            return None

    def getPreprocessedImage(self, evtNumber, image_property):
        disp_medianCorrection = 19
        disp_radialCorrection = 18
        disp_gainMask = 17
        disp_coordy = 16
        disp_coordx = 15
        disp_col = 14
        disp_row = 13
        disp_seg = 12
        disp_quad = 11
        disp_gain = 10
        disp_commonMode = 9
        disp_rms = 8
        disp_status = 7
        disp_pedestal = 6
        disp_photons = 5
        disp_raw = 4
        disp_pedestalCorrected = 3
        disp_commonModeCorrected = 2
        disp_adu = 1

        if image_property == disp_medianCorrection:  # median subtraction
            print "Sorry, this feature isn't available yet"
        elif image_property == disp_radialCorrection:  # radial subtraction + polarization corrected
            self.getEvent(evtNumber)
            calib = self.getCalib(evtNumber)
            if calib:
                self.pf.shape = self.parent.calib.shape
                calib = self.rb.subtract_bkgd(calib * self.pf)
        elif image_property == disp_adu:  # gain and hybrid gain corrected
            calib = self.getCalib(evtNumber)
        elif image_property == disp_commonModeCorrected:  # common mode corrected
            calib = self.getCommonModeCorrected(evtNumber)
        elif image_property == disp_pedestalCorrected:  # pedestal corrected
            calib = self.det.raw(self.evt).astype('float32')
            if calib: calib -= self.det.pedestals(self.evt)
        elif image_property == disp_raw:  # raw
            calib = self.det.raw(self.evt)
        elif image_property == disp_photons:  # photon counts
            calib = self.det.photons(
                self.evt,
                mask=self.parent.mk.userMask,
                adu_per_photon=self.parent.exp.aduPerPhoton)
            if calib is None:
                calib = np.zeros_like(self.parent.exp.detGuaranteed,
                                      dtype='int32')
        elif image_property == disp_pedestal:  # pedestal
            calib = self.parent.det.pedestals(self.parent.evt)
        elif image_property == disp_status:  # status
            calib = self.parent.det.status(self.parent.evt)
        elif image_property == disp_rms:  # rms
            calib = self.parent.det.rms(self.parent.evt)
        elif image_property == disp_commonMode:  # common mode
            calib = self.getCommonMode(evtNumber)
        elif image_property == disp_gain:  # gain
            calib = self.parent.det.gain(self.parent.evt)
        elif image_property == disp_gainMask:  # gain_mask
            calib = self.parent.det.gain_mask(self.parent.evt)
        elif image_property == disp_coordx:  # coords_x
            calib = self.parent.det.coords_x(self.parent.evt)
        elif image_property == disp_coordy:  # coords_y
            calib = self.parent.det.coords_y(self.parent.evt)

        shape = self.parent.det.shape(self.parent.evt)
        if len(shape) == 3:
            if image_property == disp_quad:  # quad ind
                calib = np.zeros(shape)
                for i in range(shape[0]):
                    # FIXME: handle detectors properly
                    if shape[0] == 32:  # cspad
                        calib[i, :, :] = int(i) % 8
                    elif shape[0] == 2:  # cspad2x2
                        calib[i, :, :] = int(i) % 2
                    elif shape[0] == 4:  # pnccd
                        calib[i, :, :] = int(i) % 4
            elif image_property == disp_seg:  # seg ind
                calib = np.zeros(shape)
                if shape[0] == 32:  # cspad
                    for i in range(32):
                        calib[i, :, :] = int(i) / 8
                elif shape[0] == 2:  # cspad2x2
                    for i in range(2):
                        calib[i, :, :] = int(i)
                elif shape[0] == 4:  # pnccd
                    for i in range(4):
                        calib[i, :, :] = int(i)
            elif image_property == disp_row:  # row ind
                calib = np.zeros(shape)
                if shape[0] == 32:  # cspad
                    for i in range(185):
                        calib[:, i, :] = i
                elif shape[0] == 2:  # cspad2x2
                    for i in range(185):
                        calib[:, i, :] = i
                elif shape[0] == 4:  # pnccd
                    for i in range(512):
                        calib[:, i, :] = i
            elif image_property == disp_col:  # col ind
                calib = np.zeros(shape)
                if shape[0] == 32:  # cspad
                    for i in range(388):
                        calib[:, :, i] = i
                elif shape[0] == 2:  # cspad2x2
                    for i in range(388):
                        calib[:, :, i] = i
                elif shape[0] == 4:  # pnccd
                    for i in range(512):
                        calib[:, :, i] = i
Example #7
0
class ImageViewer(object):
    def __init__(self, parent=None):
        self.parent = parent

        self.maxPercentile = 0
        self.minPercentile = 0
        self.displayMaxPercentile = 99.8
        self.displayMinPercentile = 1.0

        self.rb = None
        pg.setConfigOptions(imageAxisOrder="row-major")
        ## Dock 2: Image Panel
        self.dock = Dock("Image Panel", size=(500, 400))
        self.win = pg.ImageView(view=pg.PlotItem())
        self.win.getView().invertY(True)
        self.img_feature = pg.ImageItem()
        # Set color map white -> black
        #colors = [
        #    (255, 255, 255),
        #    (0, 0, 0)
        #]
        #self.cmap = pg.ColorMap(pos=np.linspace(0.0, 1.0, len(colors)), color=colors)
        #self.win.setColorMap(self.cmap)

        self.win.getView().addItem(self.img_feature)
        self.ring_feature = pg.ScatterPlotItem()
        self.centre_feature = pg.ScatterPlotItem()
        self.peak_feature = pg.ScatterPlotItem()
        self.indexedPeak_feature = pg.ScatterPlotItem()
        self.filePeak_feature = pg.ScatterPlotItem()
        self.z_direction = pg.ScatterPlotItem()
        self.z_direction1 = pg.ScatterPlotItem()
        self.win.getView().addItem(self.ring_feature)
        self.win.getView().addItem(self.centre_feature)
        self.win.getView().addItem(self.peak_feature)
        self.win.getView().addItem(self.indexedPeak_feature)
        self.win.getView().addItem(self.filePeak_feature)
        self.win.getView().addItem(self.z_direction)
        self.win.getView().addItem(self.z_direction1)
        self.abc_text = pg.TextItem(html='',
                                    anchor=(0, 0))  # unit cell display
        self.win.getView().addItem(self.abc_text)
        self.peak_text = pg.TextItem(html='', anchor=(0, 0))  # peak display
        self.win.getView().addItem(self.peak_text)
        self.dock.addWidget(self.win)
        self.drawLabCoordinates()

    def clearPeakMessage(self):
        self.win.getView().removeItem(self.peak_text)
        self.peak_feature.setData([], [], pxMode=False)
        if self.parent.args.v >= 1: print("Done clearPeakMessage")

    def clearIndexingMessage(self):
        self.win.getView().removeItem(self.abc_text)
        self.indexedPeak_feature.setData([], [], pxMode=False)
        if self.parent.args.v >= 1: print("Done clearIndexingMessage")

    def updateIndexingMessage(self, abc_text):
        self.win.getView().addItem(abc_text)

    def drawLabCoordinates(self):
        (cenX, cenY) = (-20, -20)  # no offset
        # Draw xy arrows
        symbolSize = 40
        cutoff = symbolSize / 2
        headLen = -30
        tailLen = -30 + cutoff
        xArrow = pg.ArrowItem(angle=180,
                              tipAngle=30,
                              baseAngle=20,
                              headLen=headLen,
                              tailLen=tailLen,
                              tailWidth=8,
                              pen=None,
                              brush='b',
                              pxMode=False)
        xArrow.setPos(2 * headLen + cenY, 0 + cenX)
        self.win.getView().addItem(xArrow)
        yArrow = pg.ArrowItem(angle=-90,
                              tipAngle=30,
                              baseAngle=20,
                              headLen=headLen,
                              tailLen=tailLen,
                              tailWidth=8,
                              pen=None,
                              brush='r',
                              pxMode=False)
        yArrow.setPos(0 + cenY, 2 * headLen + cenX)
        self.win.getView().addItem(yArrow)

        # Lab coordinates: Add z-direction
        self.z_direction.setData([0+cenY], [0+cenX], symbol='o', \
                                 size=symbolSize, brush='w', \
                                 pen={'color': 'k', 'width': 4}, pxMode=False)
        self.z_direction1.setData([0+cenY], [0+cenX], symbol='x', \
                                 size=symbolSize, brush='k', \
                                 pen={'color': 'k', 'width': 4}, pxMode=False)
        # Lab coordinates: Add xyz text
        self.x_text = pg.TextItem(
            html=
            '<div style="text-align: left"><span style="color: #0000FF; font-size: 16pt;">x</span></div>',
            anchor=(0, 0))
        self.win.getView().addItem(self.x_text)
        self.x_text.setPos(2 * headLen + cenY, 0 + cenX)
        self.y_text = pg.TextItem(
            html=
            '<div style="text-align: left"><span style="color: #FF0000; font-size: 16pt;">y</span></div>',
            anchor=(1, 1))
        self.win.getView().addItem(self.y_text)
        self.y_text.setPos(0 + cenY, 2 * headLen + cenX)
        self.z_text = pg.TextItem(
            html=
            '<div style="text-align: left"><span style="color: #000000; font-size: 16pt;">z</span></div>',
            anchor=(1, 0))
        self.win.getView().addItem(self.z_text)
        self.z_text.setPos(-headLen + cenY, 0 + cenX)

        # Label xy axes
        self.x_axis = self.win.getView().getAxis('bottom')
        self.x_axis.setLabel('X-axis (pixels)')
        self.y_axis = self.win.getView().getAxis('left')
        self.y_axis.setLabel('Y-axis (pixels)')

    def updateImage(self, calib=None):
        if self.parent.hasExperimentName and self.parent.hasRunNumber and self.parent.hasDetInfo:
            if calib is None:
                self.parent.calib, self.parent.data = self.getDetImage(
                    self.parent.eventNumber)
            else:
                _, self.parent.data = self.getDetImage(self.parent.eventNumber,
                                                       calib=calib)

            if self.parent.firstUpdate:
                if self.parent.exp.logscaleOn:
                    self.win.setImage(
                        np.log10(abs(self.parent.data) + self.parent.eps))
                    self.win.view.setRange(
                        xRange=[0, self.parent.data.shape[0]],
                        yRange=[0, self.parent.data.shape[1]],
                        padding=0)
                    self.parent.firstUpdate = False
                else:
                    self.minPercentile = np.percentile(
                        self.parent.data, self.displayMinPercentile)
                    if self.minPercentile < 0: self.minPercentile = 0
                    self.maxPercentile = np.percentile(
                        self.parent.data, self.displayMaxPercentile)
                    self.win.setImage(self.parent.data,
                                      levels=(self.minPercentile,
                                              self.maxPercentile))
                    # properly resize the image to fit on screen
                    self.win.view.setRange(
                        xRange=[0, self.parent.data.shape[0]],
                        yRange=[0, self.parent.data.shape[1]],
                        padding=0)
                    self.parent.firstUpdate = False
            else:
                if self.parent.exp.logscaleOn:
                    self.win.setImage(
                        np.log10(abs(self.parent.data) + self.parent.eps),
                        autoRange=False,
                        autoLevels=False,
                        autoHistogramRange=False)
                else:
                    if self.minPercentile == 0 and self.maxPercentile == 0:
                        self.minPercentile = np.percentile(
                            self.parent.data, self.displayMinPercentile)
                        if self.minPercentile < 0: self.minPercentile = 0
                        self.maxPercentile = np.percentile(
                            self.parent.data, self.displayMaxPercentile)
                        self.win.setImage(self.parent.data,
                                          levels=(self.minPercentile,
                                                  self.maxPercentile))
                    else:
                        self.win.setImage(self.parent.data,
                                          autoRange=False,
                                          autoLevels=False,
                                          autoHistogramRange=False)

        # Load peak parameters if exists
        if 'sfx' in self.parent.args.mode and self.parent.pk.userUpdate is None:
            self.parent.pk.updateParam()
        else:
            self.parent.mk.displayMask()

        if 'label' in self.parent.args.mode:
            self.parent.labeling.updateText()

        if self.parent.args.v >= 1: print("Done updateImage")

    def getCalib(self, evtNumber):
        if self.parent.exp.run is not None:
            self.parent.evt = self.parent.exp.getEvt(evtNumber)
            if self.parent.exp.applyCommonMode:  # play with different common mode
                if self.parent.exp.commonMode[0] == 5:  # Algorithm 5
                    calib = self.parent.det.calib(
                        self.parent.evt,
                        cmpars=(self.parent.exp.commonMode[0],
                                self.parent.exp.commonMode[1]))
                else:  # Algorithms 1 to 4
                    print("### Overriding common mode: ",
                          self.parent.exp.commonMode)
                    calib = self.parent.det.calib(
                        self.parent.evt,
                        cmpars=(self.parent.exp.commonMode[0],
                                self.parent.exp.commonMode[1],
                                self.parent.exp.commonMode[2],
                                self.parent.exp.commonMode[3]))
            else:
                if not self.parent.inputImages:
                    calib = self.parent.det.calib(self.parent.evt)
                else:
                    f = h5py.File(self.parent.inputImages)
                    ind = np.where(f['eventNumber'][()] == evtNumber)[0][0]
                    if len(f['/data/data'].shape) == 3:
                        calib = ipct(self.parent.detInfo,
                                     f['data/data'][ind, :, :])
                    else:
                        calib = f['data/data'][ind, :, :, :]
                    f.close()
            return calib
        else:
            return None

    def getCommonModeCorrected(self, evtNumber):
        if self.parent.exp.run is not None:
            try:
                self.parent.evt = self.parent.exp.getEvt(evtNumber)
                pedestalCorrected = self.parent.det.raw(
                    self.parent.evt) - self.parent.det.pedestals(
                        self.parent.evt)
                if self.parent.exp.applyCommonMode:  # play with different common mode
                    if self.parent.exp.commonMode[0] == 5:  # Algorithm 5
                        commonMode = self.parent.det.common_mode_correction(
                            self.parent.evt,
                            pedestalCorrected,
                            cmpars=(self.parent.exp.commonMode[0],
                                    self.parent.exp.commonMode[1]))
                        commonModeCorrected = pedestalCorrected - commonMode
                    else:  # Algorithms 1 to 4
                        print("### Overriding common mode: ",
                              self.parent.exp.commonMode)
                        commonMode = self.parent.det.common_mode_correction(
                            self.parent.evt,
                            pedestalCorrected,
                            cmpars=(self.parent.exp.commonMode[0],
                                    self.parent.exp.commonMode[1],
                                    self.parent.exp.commonMode[2],
                                    self.parent.exp.commonMode[3]))
                        commonModeCorrected = pedestalCorrected - commonMode
                else:
                    commonMode = self.parent.det.common_mode_correction(
                        self.parent.evt, pedestalCorrected)
                    commonModeCorrected = pedestalCorrected + commonMode  # WHAT! You need to ADD common mode?!!
                return commonModeCorrected
            except:
                return None
        else:
            return None

    def getCommonMode(self, evtNumber):
        if self.parent.exp.run is not None:
            self.parent.evt = self.parent.exp.getEvt(evtNumber)
            pedestalCorrected = self.parent.det.raw(
                self.parent.evt) - self.parent.det.pedestals(self.parent.evt)
            if self.parent.exp.applyCommonMode:  # play with different common mode
                print("### Overriding common mode: ",
                      self.parent.exp.commonMode)
                if self.parent.exp.commonMode[0] == 5:  # Algorithm 5
                    cm = self.parent.det.common_mode_correction(
                        self.parent.evt,
                        pedestalCorrected,
                        cmpars=(self.parent.exp.commonMode[0],
                                self.parent.exp.commonMode[1]))
                else:  # Algorithms 1 to 4
                    cm = self.parent.det.common_mode_correction(
                        self.parent.evt,
                        pedestalCorrected,
                        cmpars=(self.parent.exp.commonMode[0],
                                self.parent.exp.commonMode[1],
                                self.parent.exp.commonMode[2],
                                self.parent.exp.commonMode[3]))
            else:
                cm = self.parent.det.common_mode_correction(
                    self.parent.evt, pedestalCorrected)
            return cm
        else:
            return None

    def getAssembledImage(self, arg, calib):
        _calib = calib.copy()  # this is important
        tic = time.time()
        if self.parent.exp.applyFriedel:  # Apply Friedel symmetry
            print("Apply Friedel symmetry")
            try:
                centre = self.parent.det.point_indexes(self.parent.evt,
                                                       pxy_um=(0, 0),
                                                       pix_scale_size_um=None,
                                                       xy0_off_pix=None,
                                                       cframe=gu.CFRAME_PSANA,
                                                       fract=True)
            except AttributeError:
                centre = self.parent.det.point_indexes(self.parent.evt)
            self.fs = FriedelSym(self.parent.exp.detGuaranteedData.shape,
                                 centre)
            data = self.parent.det.image(self.parent.evt, _calib)
            if self.parent.mk.combinedMask is not None:
                data = self.fs.applyFriedel(data,
                                            mask=self.parent.det.image(
                                                self.parent.evt,
                                                self.parent.mk.combinedMask),
                                            mode='same')
            else:
                data = self.fs.applyFriedel(data, mask=None, mode='same')
        else:
            data = self.parent.det.image(self.parent.evt, _calib)
        if data is None: data = _calib
        toc = time.time()
        if self.parent.args.v >= 1: print("time assemble: ", toc - tic)
        return data

    def setupRadialBackground(self):
        self.parent.geom.findPsanaGeometry()
        if self.parent.geom.calibFile is not None:
            if self.parent.args.v >= 1:
                print(
                    "calibFile: ", self.parent.geom.calibPath + '/' +
                    self.parent.geom.calibFile)
            self.geo = self.parent.det.geometry(
                self.parent.runNumber
            )  #self.geo = GeometryAccess(self.parent.geom.calibPath+'/'+self.parent.geom.calibFile)
            self.xarr, self.yarr, self.zarr = self.geo.get_pixel_coords()
            self.iX, self.iY = self.geo.get_pixel_coord_indexes()
            self.mask = self.geo.get_pixel_mask(mbits=0o0377)
            # mask for 2x1 edges, two central columns, and unbound pixels with their neighbours
            self.rb = RadialBkgd(self.xarr,
                                 self.yarr,
                                 mask=self.mask,
                                 radedges=None,
                                 nradbins=100,
                                 phiedges=(0, 360),
                                 nphibins=1)
            if self.parent.args.v >= 1: print("Done setupRadialBackground")
        else:
            self.rb = None

    def updatePolarizationFactor(
            self):  # FIXME: change to vertical polarization after July 2020
        if self.rb is not None:
            self.pf = polarization_factor(self.rb.pixel_rad(),
                                          self.rb.pixel_phi() + 90,
                                          self.parent.detectorDistance *
                                          1e6)  # convert to um
            if self.parent.args.v >= 1: print("Done updatePolarizationFactor")

    def updateDetectorCentre(self):
        try:
            self.parent.cy, self.parent.cx = self.parent.det.point_indexes(
                self.parent.evt,
                pxy_um=(0, 0),
                pix_scale_size_um=None,
                xy0_off_pix=None,
                cframe=gu.CFRAME_PSANA,
                fract=True)
        except AttributeError:
            self.parent.cy, self.parent.cx = self.parent.det.point_indexes(
                self.parent.evt, pxy_um=(0, 0))
        if self.parent.cx is None:
            print("#######################################")
            print(
                "WARNING: Unable to get detector center position. Check detector geometry is deployed."
            )
            print("#######################################")
            data = self.parent.det.image(self.parent.evt,
                                         self.parent.exp.detGuaranteed)
            self.parent.cx, self.parent.cy = self.getCentre(data.shape)
        if self.parent.args.v >= 1:
            print("cx, cy: ", self.parent.cx, self.parent.cy)

    def getDetImage(self, evtNumber, calib=None):
        if calib is None:
            if self.parent.exp.image_property == self.parent.exp.disp_medianCorrection:  # median subtraction
                calib = self.getCalib(evtNumber)
                if calib is None:
                    calib = np.zeros_like(self.parent.exp.detGuaranteed,
                                          dtype='float32')
                calib -= median_filter_ndarr(calib,
                                             self.parent.exp.medianFilterRank)
            elif self.parent.exp.image_property == self.parent.exp.disp_radialCorrection:  # radial subtraction + polarization corrected
                calib = self.getCalib(evtNumber)
                if calib is None:
                    calib = np.zeros_like(self.parent.exp.detGuaranteed,
                                          dtype='float32')
                self.pf.shape = calib.shape  # FIXME: shape is 1d
                calib = self.rb.subtract_bkgd(calib * self.pf)
                calib.shape = self.parent.calib.shape  # FIXME: shape is 1d
            elif self.parent.exp.image_property == self.parent.exp.disp_adu:  # gain and hybrid gain corrected
                calib = self.getCalib(evtNumber)
                if calib is None:
                    calib = np.zeros_like(self.parent.exp.detGuaranteed,
                                          dtype='float32')
            elif self.parent.exp.image_property == self.parent.exp.disp_commonModeCorrected:  # common mode corrected
                calib = self.getCommonModeCorrected(evtNumber)
                if calib is None:
                    calib = np.zeros_like(self.parent.exp.detGuaranteed,
                                          dtype='float32')
            elif self.parent.exp.image_property == self.parent.exp.disp_pedestalCorrected:  # pedestal corrected
                calib = self.parent.det.raw(self.parent.evt).astype('float32')
                if calib is None:
                    calib = np.zeros_like(self.parent.exp.detGuaranteed,
                                          dtype='float32')
                else:
                    calib -= self.parent.det.pedestals(self.parent.evt)
            elif self.parent.exp.image_property == self.parent.exp.disp_raw:  # raw
                calib = self.parent.det.raw(self.parent.evt)
                if calib is None:
                    calib = np.zeros_like(self.parent.exp.detGuaranteed,
                                          dtype='float32')
                self.parent.firstUpdate = True
            elif self.parent.exp.image_property == self.parent.exp.disp_photons:  # photon counts
                calib = self.parent.det.photons(
                    self.parent.evt,
                    mask=self.parent.mk.userMask,
                    adu_per_photon=self.parent.exp.aduPerPhoton)
                if calib is None:
                    calib = np.zeros_like(self.parent.exp.detGuaranteed,
                                          dtype='int32')
                self.parent.firstUpdate = True
            elif self.parent.exp.image_property == self.parent.exp.disp_pedestal:  # pedestal
                calib = self.parent.det.pedestals(self.parent.evt)
                self.parent.firstUpdate = True
            elif self.parent.exp.image_property == self.parent.exp.disp_status:  # status
                calib = self.parent.det.status(self.parent.evt)
                self.parent.firstUpdate = True
            elif self.parent.exp.image_property == self.parent.exp.disp_rms:  # rms
                calib = self.parent.det.rms(self.parent.evt)
                self.parent.firstUpdate = True
            elif self.parent.exp.image_property == self.parent.exp.disp_commonMode:  # common mode
                calib = self.getCommonMode(evtNumber)
                self.parent.firstUpdate = True
            elif self.parent.exp.image_property == self.parent.exp.disp_gain:  # gain
                calib = self.parent.det.gain(self.parent.evt)
                self.parent.firstUpdate = True
            elif self.parent.exp.image_property == self.parent.exp.disp_gainMask:  # gain_mask
                calib = self.parent.det.gain_mask(self.parent.evt)
                self.parent.firstUpdate = True
            elif self.parent.exp.image_property == self.parent.exp.disp_coordx:  # coords_x
                try:
                    calib = self.parent.det.coords_x(self.parent.evt,
                                                     cframe=1)  # lab coords
                except:
                    calib = self.parent.det.coords_x(
                        self.parent.evt)  # matrix coords
                self.parent.firstUpdate = True
            elif self.parent.exp.image_property == self.parent.exp.disp_coordy:  # coords_y
                try:
                    calib = self.parent.det.coords_y(self.parent.evt,
                                                     cframe=1)  # lab coords
                except:
                    calib = self.parent.det.coords_y(
                        self.parent.evt)  # matrix coords
                self.parent.firstUpdate = True

            shape = self.parent.det.shape(self.parent.evt)
            if len(shape) == 3:
                if self.parent.exp.image_property == self.parent.exp.disp_seg:  # seg ind
                    calib = np.zeros(shape)
                    for i in range(shape[0]):
                        calib[i, :, :] = i
                    self.parent.firstUpdate = True
                elif self.parent.exp.image_property == self.parent.exp.disp_row:  # row ind
                    calib = np.zeros(shape)
                    for i in range(shape[1]):
                        calib[:, i, :] = i
                    self.parent.firstUpdate = True
                elif self.parent.exp.image_property == self.parent.exp.disp_col:  # col ind
                    calib = np.zeros(shape)
                    for i in range(shape[2]):
                        calib[:, :, i] = i
                    self.parent.firstUpdate = True

        # Update photon energy
        self.parent.exp.updatePhotonEnergy(self.parent.facility)

        # Update clen
        self.parent.geom.updateClen(self.parent.facility)

        # Write a temporary geom file
        #self.parent.geom.deployCrystfelGeometry(self.parent.facility)
        #self.parent.geom.writeCrystfelGeom(self.parent.facility) # Hack to override coffset

        # Get assembled image
        if calib is not None:
            data = self.getAssembledImage(self.parent.facility, calib)
        else:
            calib = np.zeros_like(self.parent.exp.detGuaranteed,
                                  dtype='float32')
            data = self.getAssembledImage(self.parent.facility, calib)

        # Update ROI histogram
        if self.parent.roi.roiCurrent == 'rect':
            self.parent.roi.updateRoi(self.parent.roi.roi)
        elif self.parent.roi.roiCurrent == 'poly':
            self.parent.roi.updateRoi(self.parent.roi.roiPoly)
        elif self.parent.roi.roiCurrent == 'circ':
            self.parent.roi.updateRoi(self.parent.roi.roiCircle)

        return calib, data

    def getCentre(self, shape):
        cx = shape[1] / 2
        cy = shape[0] / 2
        return cx, cy
Example #8
0
class psanaWhisperer():
    def __init__(self, experimentName, runNumber, detInfo, clen='', aduPerPhoton=1, localCalib=False):
        self.experimentName = experimentName
        self.runNumber = runNumber
        self.detInfo = detInfo
        self.clenStr = clen
        self.aduPerPhoton = aduPerPhoton
        self.localCalib = localCalib

    def setupExperiment(self):
        self.ds = psana.DataSource('exp=' + str(self.experimentName) + ':run=' + str(self.runNumber) + ':idx')
        self.run = self.ds.runs().next()
        self.times = self.run.times()
        self.eventTotal = len(self.times)
        self.env = self.ds.env()
        self.evt = self.run.event(self.times[0])
        self.det = psana.Detector(str(self.detInfo), self.env)
        self.det.do_reshape_2d_to_3d(flag=True)
        self.getDetInfoList()
        self.detAlias = self.getDetectorAlias(str(self.detInfo))
        self.updateClen() # Get epics variable, clen

    def updateClen(self):
        if 'cspad' in self.detInfo.lower() and 'cxi' in self.experimentName:
            self.epics = self.ds.env().epicsStore()
            self.clen = self.epics.value(self.clenStr)
        elif 'rayonix' in self.detInfo.lower() and 'mfx' in self.experimentName:
            self.epics = self.ds.env().epicsStore()
            self.clen = self.epics.value(self.clenStr)
        elif 'rayonix' in self.detInfo.lower() and 'xpp' in self.experimentName:
            self.epics = self.ds.env().epicsStore()
            self.clen = self.epics.value(self.clenStr)

    def getDetectorAlias(self, srcOrAlias):
        for i in self.detInfoList:
            src, alias, _ = i
            if srcOrAlias.lower() == src.lower() or srcOrAlias.lower() == alias.lower():
                return alias

    def getDetInfoList(self):
        myAreaDetectors = []
        self.detnames = psana.DetNames()
        for k in self.detnames:
            try:
                if Detector.PyDetector.dettype(str(k[0]), self.env) == Detector.AreaDetector.AreaDetector:
                    myAreaDetectors.append(k)
            except ValueError:
                continue
        self.detInfoList = list(set(myAreaDetectors))

    def getEvent(self, number):
        self.evt = self.run.event(self.times[number])

    def getImg(self, number):
        self.getEvent(number)
        img = self.det.image(self.evt, self.det.calib(self.evt))
        return img

    def getImg(self):
        if self.evt is not None:
            img = self.det.image(self.evt, self.det.calib(self.evt))
            return img
        return None

    def getCheetahImg(self, calib=None):
        """Converts seg, row, col assuming (32,185,388)
           to cheetah 2-d table row and col (8*185, 4*388)
        """
        if 'cspad2x2' in self.detInfo.lower():
            print "Not implemented yet: cspad2x2"
        elif 'cspad' in self.detInfo.lower():
            if calib is None: calib = self.det.calib(self.evt) # (32,185,388)
            img = np.zeros((8 * 185, 4 * 388))
            counter = 0
            for quad in range(4):
                for seg in range(8):
                    img[seg * 185:(seg + 1) * 185, quad * 388:(quad + 1) * 388] = calib[counter, :, :]
                    counter += 1
        elif 'rayonix' in self.detInfo.lower():
            if calib is None:
                img = np.squeeze(self.det.calib(self.evt))  # (1920,1920)
            else:
                img = np.squeeze(calib)
        return img

    def getCleanAssembledImg(self, backgroundEvent):
        """Returns psana assembled image
        """
        backgroundEvt = self.run.event(self.times[backgroundEvent])
        backgroundCalib = self.det.calib(backgroundEvt)
        calib = self.det.calib(self.evt)
        cleanCalib = calib - backgroundCalib
        img = self.det.image(self.evt, cleanCalib)
        return img

    def getAssembledImg(self):
        """Returns psana assembled image
        """
        img = self.det.image(self.evt)
        return img

    def getCalibImg(self):
        """Returns psana assembled image
        """
        img = self.det.calib(self.evt)
        return img

    def getCleanAssembledPhotons(self, backgroundEvent):
        """Returns psana assembled image in photon counts
        """
        backgroundEvt = self.run.event(self.times[backgroundEvent])
        backgroundCalib = self.det.calib(backgroundEvt)
        calib = self.det.calib(self.evt)
        cleanCalib = calib - backgroundCalib
        img = self.det.photons(self.evt, nda_calib=cleanCalib, adu_per_photon=self.aduPerPhoton)
        phot = self.det.image(self.evt, img)
        return phot

    def getAssembledPhotons(self):
        """Returns psana assembled image in photon counts
        """
        img = self.det.photons(self.evt, adu_per_photon=self.aduPerPhoton)
        phot = self.det.image(self.evt, img)
        return phot

    def getPsanaEvent(self, cheetahFilename):
        # Gets psana event given cheetahFilename, e.g. LCLS_2015_Jul26_r0014_035035_e820.h5
        hrsMinSec = cheetahFilename.split('_')[-2]
        fid = int(cheetahFilename.split('_')[-1].split('.')[0], 16)
        for t in self.times:
            if t.fiducial() == fid:
                localtime = time.strftime('%H:%M:%S', time.localtime(t.seconds()))
                localtime = localtime.replace(':', '')
                if localtime[0:3] == hrsMinSec[0:3]:
                    self.evt = self.run.event(t)
                else:
                    self.evt = None

    def getStartTime(self):
        self.evt = self.run.event(self.times[0])
        evtId = self.evt.get(psana.EventId)
        sec = evtId.time()[0]
        nsec = evtId.time()[1]
        fid = evtId.fiducials()
        return time.strftime('%FT%H:%M:%S-0800', time.localtime(sec))  # Hard-coded pacific time

    #####################################################################
    # TODO: Functions below are not being used yet
    #####################################################################
    def findPsanaGeometry(self):
        try:
            self.source = psana.Detector.PyDetector.map_alias_to_source(self.detInfo,
                                                                  self.ds.env())  # 'DetInfo(CxiDs2.0:Cspad.0)'
            self.calibSource = self.source.split('(')[-1].split(')')[0]  # 'CxiDs2.0:Cspad.0'
            self.detectorType = gu.det_type_from_source(self.source)  # 1
            self.calibGroup = gu.dic_det_type_to_calib_group[self.detectorType]  # 'CsPad::CalibV1'
            self.detectorName = gu.dic_det_type_to_name[self.detectorType].upper()  # 'CSPAD'
            if self.localCalib:
                self.calibPath = "./calib/" + self.calibGroup + "/" + self.calibSource + "/geometry"
            else:
                self.calibPath = "/reg/d/psdm/" + self.parent.experimentName[0:3] + \
                                 "/" + self.parent.experimentName + "/calib/" + \
                                 self.calibGroup + "/" + self.calibSource + "/geometry"

            # Determine which calib file to use
            geometryFiles = os.listdir(self.calibPath)
            self.calibFile = None
            minDiff = -1e6
            for fname in geometryFiles:
                if fname.endswith('.data'):
                    endValid = False
                    startNum = int(fname.split('-')[0])
                    endNum = fname.split('-')[-1].split('.data')[0]
                    diff = startNum - self.parent.runNumber
                    # Make sure it's end number is valid too
                    if 'end' in endNum:
                        endValid = True
                    else:
                        try:
                            if self.parent.runNumber <= int(endNum):
                                endValid = True
                        except:
                            continue
                    if diff <= 0 and diff > minDiff and endValid is True:
                        minDiff = diff
                        self.calibFile = fname
        except:
            if self.parent.args.v >= 1: print "Couldn't find psana geometry"
            self.calibFile = None

    def setupRadialBackground(self):
        self.findPsanaGeometry()
        if self.calibFile is not None:
            self.geo = GeometryAccess(self.calibPath+'/'+self.calibFile)
            self.xarr, self.yarr, self.zarr = self.geo.get_pixel_coords()
            self.iX, self.iY = self.geo.get_pixel_coord_indexes()
            self.mask = self.geo.get_pixel_mask(mbits=0377)  # mask for 2x1 edges, two central columns, and unbound pixels with their neighbours
            self.rb = RadialBkgd(self.xarr, self.yarr, mask=self.mask, radedges=None, nradbins=100, phiedges=(0, 360), nphibins=1)
        else:
            self.rb = None

    def updatePolarizationFactor(self, detectorDistance_in_m):
        if self.rb is not None:
            self.pf = polarization_factor(self.rb.pixel_rad(), self.rb.pixel_phi(), detectorDistance_in_m*1e6) # convert to um

    def getCalib(self, evtNumber):
        if self.run is not None:
            self.evt = self.getEvent(evtNumber)
            if self.applyCommonMode: # play with different common mode
                if self.commonMode[0] == 5: # Algorithm 5
                    calib = self.det.calib(self.evt,cmpars=(self.commonMode[0], self.commonMode[1]))
                else: # Algorithms 1 to 4
                    print "### Overriding common mode: ", self.commonMode
                    calib = self.det.calib(self.evt,cmpars=(self.commonMode[0], self.commonMode[1],
                                                          self.commonMode[2], self.commonMode[3]))
            else:
                calib = self.det.calib(self.evt)
            return calib
        else:
            return None

    def getPreprocessedImage(self, evtNumber, image_property):
        disp_medianCorrection = 19
        disp_radialCorrection = 18
        disp_gainMask = 17
        disp_coordy= 16
        disp_coordx= 15
        disp_col= 14
        disp_row= 13
        disp_seg= 12
        disp_quad= 11
        disp_gain= 10
        disp_commonMode= 9
        disp_rms= 8
        disp_status= 7
        disp_pedestal= 6
        disp_photons= 5
        disp_raw= 4
        disp_pedestalCorrected= 3
        disp_commonModeCorrected= 2
        disp_adu= 1

        if image_property == disp_medianCorrection:  # median subtraction
            print "Sorry, this feature isn't available yet"
        elif image_property == disp_radialCorrection:  # radial subtraction + polarization corrected
            self.getEvent(evtNumber)
            calib = self.getCalib(evtNumber)
            if calib:
                self.pf.shape = self.parent.calib.shape
                calib = self.rb.subtract_bkgd(calib * self.pf)
        elif image_property == disp_adu:  # gain and hybrid gain corrected
            calib = self.getCalib(evtNumber)
        elif image_property == disp_commonModeCorrected:  # common mode corrected
            calib = self.getCommonModeCorrected(evtNumber)
        elif image_property == disp_pedestalCorrected:  # pedestal corrected
            calib = self.det.raw(self.evt).astype('float32')
            if calib: calib -= self.det.pedestals(self.evt)
        elif image_property == disp_raw:  # raw
            calib = self.det.raw(self.evt)
        elif image_property == disp_photons:  # photon counts
            calib = self.det.photons(self.evt, mask=self.parent.mk.userMask,
                                            adu_per_photon=self.parent.exp.aduPerPhoton)
            if calib is None:
                calib = np.zeros_like(self.parent.exp.detGuaranteed, dtype='int32')
        elif image_property == disp_pedestal:  # pedestal
            calib = self.parent.det.pedestals(self.parent.evt)
        elif image_property == disp_status:  # status
            calib = self.parent.det.status(self.parent.evt)
        elif image_property == disp_rms:  # rms
            calib = self.parent.det.rms(self.parent.evt)
        elif image_property == disp_commonMode:  # common mode
            calib = self.getCommonMode(evtNumber)
        elif image_property == disp_gain:  # gain
            calib = self.parent.det.gain(self.parent.evt)
        elif image_property == disp_gainMask:  # gain_mask
            calib = self.parent.det.gain_mask(self.parent.evt)
        elif image_property == disp_coordx:  # coords_x
            calib = self.parent.det.coords_x(self.parent.evt)
        elif image_property == disp_coordy:  # coords_y
            calib = self.parent.det.coords_y(self.parent.evt)

        shape = self.parent.det.shape(self.parent.evt)
        if len(shape) == 3:
            if image_property == disp_quad:  # quad ind
                calib = np.zeros(shape)
                for i in range(shape[0]):
                    # FIXME: handle detectors properly
                    if shape[0] == 32:  # cspad
                        calib[i, :, :] = int(i) % 8
                    elif shape[0] == 2:  # cspad2x2
                        calib[i, :, :] = int(i) % 2
                    elif shape[0] == 4:  # pnccd
                        calib[i, :, :] = int(i) % 4
            elif image_property == disp_seg:  # seg ind
                calib = np.zeros(shape)
                if shape[0] == 32:  # cspad
                    for i in range(32):
                        calib[i, :, :] = int(i) / 8
                elif shape[0] == 2:  # cspad2x2
                    for i in range(2):
                        calib[i, :, :] = int(i)
                elif shape[0] == 4:  # pnccd
                    for i in range(4):
                        calib[i, :, :] = int(i)
            elif image_property == disp_row:  # row ind
                calib = np.zeros(shape)
                if shape[0] == 32:  # cspad
                    for i in range(185):
                        calib[:, i, :] = i
                elif shape[0] == 2:  # cspad2x2
                    for i in range(185):
                        calib[:, i, :] = i
                elif shape[0] == 4:  # pnccd
                    for i in range(512):
                        calib[:, i, :] = i
            elif image_property == disp_col:  # col ind
                calib = np.zeros(shape)
                if shape[0] == 32:  # cspad
                    for i in range(388):
                        calib[:, :, i] = i
                elif shape[0] == 2:  # cspad2x2
                    for i in range(388):
                        calib[:, :, i] = i
                elif shape[0] == 4:  # pnccd
                    for i in range(512):
                        calib[:, :, i] = i
Example #9
0
class PeakFinder:
    def __init__(self,exp,run,detname,evt,detector,algorithm,hitParam_alg_npix_min,hitParam_alg_npix_max,
                 hitParam_alg_amax_thr,hitParam_alg_atot_thr,hitParam_alg_son_min,
                 streakMask_on,streakMask_sigma,streakMask_width,userMask_path,psanaMask_on,psanaMask_calib,
                 psanaMask_status,psanaMask_edges,psanaMask_central,psanaMask_unbond,psanaMask_unbondnrs,
                 medianFilterOn=0, medianRank=5, radialFilterOn=0, distance=0.0, windows=None, **kwargs):
        self.exp = exp
        self.run = run
        self.detname = detname
        self.det = detector
        self.algorithm = algorithm
        self.maxRes = 0

        self.npix_min=hitParam_alg_npix_min
        self.npix_max=hitParam_alg_npix_max
        self.amax_thr=hitParam_alg_amax_thr
        self.atot_thr=hitParam_alg_atot_thr
        self.son_min=hitParam_alg_son_min

        self.streakMask_on = str2bool(streakMask_on)
        self.streakMask_sigma = streakMask_sigma
        self.streakMask_width = streakMask_width
        self.userMask_path = userMask_path
        self.psanaMask_on = str2bool(psanaMask_on)
        self.psanaMask_calib = str2bool(psanaMask_calib)
        self.psanaMask_status = str2bool(psanaMask_status)
        self.psanaMask_edges = str2bool(psanaMask_edges)
        self.psanaMask_central = str2bool(psanaMask_central)
        self.psanaMask_unbond = str2bool(psanaMask_unbond)
        self.psanaMask_unbondnrs = str2bool(psanaMask_unbondnrs)

        self.medianFilterOn = medianFilterOn
        self.medianRank = medianRank
        self.radialFilterOn = radialFilterOn
        self.distance = distance

        self.windows = windows

        self.userMask = None
        self.psanaMask = None
        self.streakMask = None
        self.userPsanaMask = None
        self.combinedMask = None

        # Make user mask
        if self.userMask_path is not None:
            self.userMask = np.load(self.userMask_path)

        # Make psana mask
        if self.psanaMask_on:
            self.psanaMask = detector.mask(evt, calib=self.psanaMask_calib, status=self.psanaMask_status,
                                           edges=self.psanaMask_edges, central=self.psanaMask_central,
                                           unbond=self.psanaMask_unbond, unbondnbrs=self.psanaMask_unbondnrs)

        # Combine userMask and psanaMask
        self.userPsanaMask = np.ones_like(self.det.calib(evt))
        if self.userMask is not None:
            self.userPsanaMask *= self.userMask
        if self.psanaMask is not None:
            self.userPsanaMask *= self.psanaMask

        # Powder of hits and misses
        self.powderHits = np.zeros_like(self.userPsanaMask)
        self.powderMisses = np.zeros_like(self.userPsanaMask)

        self.alg = PyAlgos(windows=self.windows, mask=self.userPsanaMask, pbits=0)
        # set peak-selector parameters:
        self.alg.set_peak_selection_pars(npix_min=self.npix_min, npix_max=self.npix_max, \
                                        amax_thr=self.amax_thr, atot_thr=self.atot_thr, \
                                        son_min=self.son_min)
        # set algorithm specific parameters
        if algorithm == 1:
            self.hitParam_alg1_thr_low = kwargs["alg1_thr_low"]
            self.hitParam_alg1_thr_high = kwargs["alg1_thr_high"]
            self.hitParam_alg1_rank = int(kwargs["alg1_rank"])
            self.hitParam_alg1_radius = int(kwargs["alg1_radius"])
            self.hitParam_alg1_dr = kwargs["alg1_dr"]
        elif algorithm == 3:
            self.hitParam_alg3_rank = kwargs["alg3_rank"]
            self.hitParam_alg3_r0 = int(kwargs["alg3_r0"])
            self.hitParam_alg3_dr = kwargs["alg3_dr"]
        elif algorithm == 4:
            self.hitParam_alg4_thr_low = kwargs["alg4_thr_low"]
            self.hitParam_alg4_thr_high = kwargs["alg4_thr_high"]
            self.hitParam_alg4_rank = int(kwargs["alg4_rank"])
            self.hitParam_alg4_r0 = int(kwargs["alg4_r0"])
            self.hitParam_alg4_dr = kwargs["alg4_dr"]

        self.maxNumPeaks = 2048
        self.StreakMask = myskbeam.StreakMask(self.det, evt, width=self.streakMask_width, sigma=self.streakMask_sigma)
        self.cx, self.cy = self.det.point_indexes(evt, pxy_um=(0, 0))
        self.iX = np.array(self.det.indexes_x(evt), dtype=np.int64)
        self.iY = np.array(self.det.indexes_y(evt), dtype=np.int64)
        if len(self.iX.shape) == 2:
            self.iX = np.expand_dims(self.iX, axis=0)
            self.iY = np.expand_dims(self.iY, axis=0)

        # Initialize radial background subtraction
        self.setupExperiment()
        if self.radialFilterOn:
            self.setupRadialBackground()
            self.updatePolarizationFactor()

    def setupExperiment(self):
        self.ds = psana.DataSource('exp=' + str(self.exp) + ':run=' + str(self.run) + ':idx')
        self.run = self.ds.runs().next()
        self.times = self.run.times()
        self.eventTotal = len(self.times)
        self.env = self.ds.env()
        self.evt = self.run.event(self.times[0])
        self.det = psana.Detector(str(self.detname), self.env)
        self.det.do_reshape_2d_to_3d(flag=True)

    def setupRadialBackground(self):
        self.geo = self.det.geometry(self.run)  # self.geo = GeometryAccess(self.parent.geom.calibPath+'/'+self.parent.geom.calibFile)
        self.xarr, self.yarr, self.zarr = self.geo.get_pixel_coords()
        self.ix = self.det.indexes_x(self.evt)
        self.iy = self.det.indexes_y(self.evt)
        if self.ix is None:
            self.iy = np.tile(np.arange(self.userMask.shape[1]), [self.userMask.shape[2], 1])
            self.ix = np.transpose(self.iy)
        self.iX = np.array(self.ix, dtype=np.int64)
        self.iY = np.array(self.iy, dtype=np.int64)
        if len(self.iX.shape) == 2:
            self.iX = np.expand_dims(self.iX, axis=0)
            self.iY = np.expand_dims(self.iY, axis=0)
        self.mask = self.geo.get_pixel_mask( mbits=0377)  # mask for 2x1 edges, two central columns, and unbound pixels with their neighbours
        self.rb = RadialBkgd(self.xarr, self.yarr, mask=self.mask, radedges=None, nradbins=100,
                             phiedges=(0, 360), nphibins=1)

    def updatePolarizationFactor(self):
        self.pf = polarization_factor(self.rb.pixel_rad(), self.rb.pixel_phi(), self.distance * 1e6)  # convert to um

    def findPeaks(self, calib, evt):

        if self.streakMask_on: # make new streak mask
            self.streakMask = self.StreakMask.getStreakMaskCalib(evt)

        # Apply background correction
        if self.medianFilterOn:
            calib -= median_filter_ndarr(calib, self.medianRank)

        if self.radialFilterOn:
            self.pf.shape = calib.shape  # FIXME: shape is 1d
            calib = self.rb.subtract_bkgd(calib * self.pf)
            calib.shape = self.userPsanaMask.shape  # FIXME: shape is 1d

        if self.streakMask is not None:
            self.combinedMask = self.userPsanaMask * self.streakMask
        else:
            self.combinedMask = self.userPsanaMask
        # set new mask
        #self.alg = PyAlgos(windows=self.windows, mask=self.combinedMask, pbits=0)
        # set peak-selector parameters:
        #self.alg.set_peak_selection_pars(npix_min=self.npix_min, npix_max=self.npix_max, \
        #                                amax_thr=self.amax_thr, atot_thr=self.atot_thr, \
        #                                son_min=self.son_min)
        self.alg.set_mask(self.combinedMask) # This doesn't work reliably
        # set algorithm specific parameters
        if self.algorithm == 1:
            # v1 - aka Droplet Finder - two-threshold peak-finding algorithm in restricted region
            #                           around pixel with maximal intensity.
            self.peaks = self.alg.peak_finder_v4r2(calib,
                                                   thr_low=self.hitParam_alg1_thr_low,
                                                   thr_high=self.hitParam_alg1_thr_high,
                                                   rank=self.hitParam_alg1_rank,
                                                   r0=self.hitParam_alg1_radius,
                                                   dr=self.hitParam_alg1_dr)
        elif self.algorithm == 3:
            self.peaks = self.alg.peak_finder_v3(calib, rank=self.hitParam_alg3_rank, r0=self.hitParam_alg3_r0, dr=self.hitParam_alg3_dr)
        elif self.algorithm == 4:
            # v4 - aka iDroplet Finder - two-threshold peak-finding algorithm in restricted region
            #                            around pixel with maximal intensity.
            self.peaks = self.alg.peak_finder_v4(calib, thr_low=self.hitParam_alg4_thr_low, thr_high=self.hitParam_alg4_thr_high, \
                                   rank=self.hitParam_alg4_rank, r0=self.hitParam_alg4_r0, dr=self.hitParam_alg4_dr)
        self.numPeaksFound = self.peaks.shape[0]

        if self.numPeaksFound > 0:
            cenX = self.iX[np.array(self.peaks[:, 0], dtype=np.int64), np.array(self.peaks[:, 1], dtype=np.int64), np.array(
                self.peaks[:, 2], dtype=np.int64)] + 0.5
            cenY = self.iY[np.array(self.peaks[:, 0], dtype=np.int64), np.array(self.peaks[:, 1], dtype=np.int64), np.array(
                self.peaks[:, 2], dtype=np.int64)] + 0.5
            self.maxRes = getMaxRes(cenX, cenY, self.cx, self.cy)
        else:
            self.maxRes = 0

        if self.numPeaksFound >= 15:
            self.powderHits = np.maximum(self.powderHits, calib)
        else:
            self.powderMisses = np.maximum(self.powderMisses, calib)