Best Python code snippet using Airtest
gui_utils.py
Source:gui_utils.py  
1#!/usr/bin/env python2"""Functions covering the user interaction with the GUI."""3from __future__ import division, print_function4import os5import numpy as np6import matplotlib.pyplot as plt7import segmentator.config as cfg8from segmentator.utils import map_2D_hist_to_ima9from nibabel import save, Nifti1Image10from scipy.ndimage.morphology import binary_erosion11class responsiveObj:12    """Stuff to interact in the user interface."""13    def __init__(self, **kwargs):14        """Initialize variables used acros functions here."""15        if kwargs is not None:16            for key, value in kwargs.items():17                setattr(self, key, value)18        self.basename = self.nii.get_filename().split(os.extsep, 1)[0]19        self.press = None20        self.ctrlHeld = False21        self.labelNr = 022        self.imaSlcMskSwitch, self.volHistHighlightSwitch = 0, 023        self.TranspVal = 0.524        self.nrExports = 025        self.borderSwitch = 026        self.imaSlc = self.orig[:, :, self.sliceNr]  # selected slice27        self.cycleCount = 028        self.cycRotHistory = [[0, 0], [0, 0], [0, 0]]29        self.highlights = [[], []]  # to hold image to histogram circles30    def remapMsks(self, remap_slice=True):31        """Update volume histogram to image mapping.32        Parameters33        ----------34        remap_slice : bool35            Do histogram to image mapping. Used to map displayed slice mask.36        """37        if self.segmType == 'main':38            self.volHistMask = self.sectorObj.binaryMask()39            self.volHistMask = self.lassoArr(self.volHistMask, self.idxLasso)40            self.volHistMaskH.set_data(self.volHistMask)41        elif self.segmType == 'ncut':42            self.labelContours()43            self.volHistMaskH.set_data(self.volHistMask)44            self.volHistMaskH.set_extent((0, self.nrBins, self.nrBins, 0))45        # histogram to image mapping46        if remap_slice:47            temp_slice = self.invHistVolume[:, :, self.sliceNr]48            image_slice_shape = self.invHistVolume[:, :, self.sliceNr].shape49            if cfg.discard_zeros:50                zmask = temp_slice != 051                image_slice_mask = map_2D_hist_to_ima(temp_slice[zmask],52                                                      self.volHistMask)53                # reshape to image slice shape54                self.imaSlcMsk = np.zeros(image_slice_shape)55                self.imaSlcMsk[zmask] = image_slice_mask56            else:57                image_slice_mask = map_2D_hist_to_ima(temp_slice.flatten(),58                                                      self.volHistMask)59                # reshape to image slice shape60                self.imaSlcMsk = image_slice_mask.reshape(image_slice_shape)61            # for optional border visualization62            if self.borderSwitch == 1:63                self.imaSlcMsk = self.calcImaMaskBrd()64    def updatePanels(self, update_slice=True, update_rotation=False,65                     update_extent=False):66        """Update histogram and image panels."""67        if update_rotation:68            self.checkRotation()69        if update_extent:70            self.updateImaExtent()71        if update_slice:72            self.imaSlcH.set_data(self.imaSlc)73        self.imaSlcMskH.set_data(self.imaSlcMsk)74        self.figure.canvas.draw()75    def connect(self):76        """Make the object responsive."""77        self.cidpress = self.figure.canvas.mpl_connect(78            'button_press_event', self.on_press)79        self.cidrelease = self.figure.canvas.mpl_connect(80            'button_release_event', self.on_release)81        self.cidmotion = self.figure.canvas.mpl_connect(82            'motion_notify_event', self.on_motion)83        self.cidkeypress = self.figure.canvas.mpl_connect(84            'key_press_event', self.on_key_press)85        self.cidkeyrelease = self.figure.canvas.mpl_connect(86            'key_release_event', self.on_key_release)87    def on_key_press(self, event):88        """Determine what happens when a keyboard button is pressed."""89        if event.key == 'control':90            self.ctrlHeld = True91        elif event.key == '1':92            self.imaSlcMskIncr(-0.1)93        elif event.key == '2':94            self.imaSlcMskTransSwitch()95        elif event.key == '3':96            self.imaSlcMskIncr(0.1)97        elif event.key == '4':98            self.volHistHighlightTransSwitch()99        elif event.key == '5':100            self.borderSwitch = (self.borderSwitch + 1) % 2101            self.remapMsks()102            self.updatePanels(update_slice=False, update_rotation=True,103                              update_extent=True)104        if self.segmType == 'main':105            if event.key == 'up':106                self.sectorObj.scale_r(1.05)107                self.remapMsks()108                self.updatePanels(update_slice=False, update_rotation=True,109                                  update_extent=False)110            elif event.key == 'down':111                self.sectorObj.scale_r(0.95)112                self.remapMsks()113                self.updatePanels(update_slice=False, update_rotation=True,114                                  update_extent=False)115            elif event.key == 'right':116                self.sectorObj.rotate(-10.0)117                self.remapMsks()118                self.updatePanels(update_slice=False, update_rotation=True,119                                  update_extent=False)120            elif event.key == 'left':121                self.sectorObj.rotate(10.0)122                self.remapMsks()123                self.updatePanels(update_slice=True, update_rotation=True,124                                  update_extent=False)125            else:126                return127    def on_key_release(self, event):128        """Determine what happens if key is released."""129        if event.key == 'control':130            self.ctrlHeld = False131    def findVoxInHist(self, event):132        """Find voxel's location in histogram."""133        self.press = event.xdata, event.ydata134        pixel_x = int(np.floor(event.xdata))135        pixel_y = int(np.floor(event.ydata))136        aoi = self.invHistVolume[:, :, self.sliceNr]  # array of interest137        # Check rotation138        cyc_rot = self.cycRotHistory[self.cycleCount][1]139        if cyc_rot == 1:  # 90140            aoi = np.rot90(aoi, axes=(0, 1))141        elif cyc_rot == 2:  # 180142            aoi = aoi[::-1, ::-1]143        elif cyc_rot == 3:  # 270144            aoi = np.rot90(aoi, axes=(1, 0))145        # Switch x and y voxel to get linear index since not Cartesian!!!146        pixelLin = aoi[pixel_y, pixel_x]147        # ind2sub148        xpix = (pixelLin / self.nrBins)149        ypix = (pixelLin % self.nrBins)150        # Switch x and y for circle centre since back to Cartesian.151        circle_colors = [np.array([8, 48, 107, 255])/255,152                         np.array([33, 113, 181, 255])/255]153        self.highlights[0].append(plt.Circle((ypix, xpix), radius=1,154                                  edgecolor=None, color=circle_colors[0]))155        self.highlights[1].append(plt.Circle((ypix, xpix), radius=5,156                                  edgecolor=None, color=circle_colors[1]))157        self.axes.add_artist(self.highlights[0][-1])  # small circle158        self.axes.add_artist(self.highlights[1][-1])  # large circle159        self.figure.canvas.draw()160    def on_press(self, event):161        """Determine what happens if mouse button is clicked."""162        if self.segmType == 'main':163            if event.button == 1:  # left button164                if event.inaxes == self.axes:  # cursor in left plot (hist)165                    if self.ctrlHeld is False:  # ctrl no166                        contains = self.contains(event)167                        if not contains:168                            print('cursor outside circle mask')169                        if not contains:170                            return171                        # get sector centre x and y positions172                        x0 = self.sectorObj.cx173                        y0 = self.sectorObj.cy174                        # also get cursor x and y position and safe to press175                        self.press = x0, y0, event.xdata, event.ydata176                elif event.inaxes == self.axes2:  # cursor in right plot (brow)177                    self.findVoxInHist(event)178                else:179                    return180            elif event.button == 2:  # scroll button181                if event.inaxes != self.axes:  # outside axes182                    return183                # increase/decrease radius of the sector mask184                if self.ctrlHeld is False:  # ctrl no185                    self.sectorObj.scale_r(1.05)186                    self.remapMsks()187                    self.updatePanels(update_slice=False, update_rotation=True,188                                      update_extent=False)189                elif self.ctrlHeld is True:  # ctrl yes190                    self.sectorObj.rotate(10.0)191                    self.remapMsks()192                    self.updatePanels(update_slice=False, update_rotation=True,193                                      update_extent=False)194                else:195                    return196            elif event.button == 3:  # right button197                if event.inaxes != self.axes:198                    return199                # rotate the sector mask200                if self.ctrlHeld is False:  # ctrl no201                    self.sectorObj.scale_r(0.95)202                    self.remapMsks()203                    self.updatePanels(update_slice=False, update_rotation=True,204                                      update_extent=False)205                elif self.ctrlHeld is True:  # ctrl yes206                    self.sectorObj.rotate(-10.0)207                    self.remapMsks()208                    self.updatePanels(update_slice=False, update_rotation=True,209                                      update_extent=False)210                else:211                    return212        elif self.segmType == 'ncut':213            if event.button == 1:  # left mouse button214                if event.inaxes == self.axes:  # cursor in left plot (hist)215                    xbin = int(np.floor(event.xdata))216                    ybin = int(np.floor(event.ydata))217                    val = self.volHistMask[ybin][xbin]218                    # increment counterField for values in clicked subfield, at219                    # the first click the entire field constitutes the subfield220                    counter = int(self.counterField[ybin][xbin])221                    if counter+1 >= self.ima_ncut_labels.shape[2]:222                        print("already at maximum ncut dimension")223                        return224                    self.counterField[(225                        self.ima_ncut_labels[:, :, counter] ==226                        self.ima_ncut_labels[[ybin], [xbin], counter])] += 1227                    print("counter:" + str(counter+1))228                    # define arrays with old and new labels for later indexing229                    oLabels = self.ima_ncut_labels[:, :, counter]230                    nLabels = self.ima_ncut_labels[:, :, counter+1]231                    # replace old values with new values (in clicked subfield)232                    self.volHistMask[oLabels == val] = np.copy(233                        nLabels[oLabels == val])234                    self.remapMsks()235                    self.updatePanels(update_slice=False, update_rotation=True,236                                      update_extent=False)237                elif event.inaxes == self.axes2:  # cursor in right plot (brow)238                    self.findVoxInHist(event)239                else:240                    return241            elif event.button == 3:  # right mouse button242                if event.inaxes == self.axes:  # cursor in left plot (hist)243                    xbin = int(np.floor(event.xdata))244                    ybin = int(np.floor(event.ydata))245                    val = self.volHistMask[ybin][xbin]246                    # fetch the slider value to get label nr247                    self.volHistMask[self.volHistMask == val] = \248                        np.copy(self.labelNr)249                    self.remapMsks()250                    self.updatePanels(update_slice=False, update_rotation=True,251                                      update_extent=False)252    def on_motion(self, event):253        """Determine what happens if mouse button moves."""254        if self.segmType == 'main':255            # ... button is pressed256            if self.press is None:257                return258            # ... cursor is in left plot259            if event.inaxes != self.axes:260                return261            # get former sector centre x and y positions,262            # cursor x and y positions263            x0, y0, xpress, ypress = self.press264            # calculate difference betw cursor pos on click265            # and new pos dur motion266            # switch x0 & y0 cause volHistMask not Cart267            dy = event.xdata - xpress268            dx = event.ydata - ypress269            # update x and y position of sector,270            # based on past motion of cursor271            self.sectorObj.set_x(x0 + dx)272            self.sectorObj.set_y(y0 + dy)273            # update masks274            self.remapMsks()275            self.updatePanels(update_slice=False, update_rotation=True,276                              update_extent=False)277        else:278            return279    def on_release(self, event):280        """Determine what happens if mouse button is released."""281        self.press = None282        # Remove highlight circle283        if self.highlights[1]:284            self.highlights[1][-1].set_visible(False)285        self.figure.canvas.draw()286    def disconnect(self):287        """Make the object unresponsive."""288        self.figure.canvas.mpl_disconnect(self.cidpress)289        self.figure.canvas.mpl_disconnect(self.cidrelease)290        self.figure.canvas.mpl_disconnect(self.cidmotion)291    def updateColorBar(self, val):292        """Update slider for scaling log colorbar in 2D hist."""293        histVMax = np.power(10, self.sHistC.val)294        plt.clim(vmax=histVMax)295    def updateSliceNr(self):296        """Update slice number and the selected slice."""297        self.sliceNr = int(self.sSliceNr.val*self.orig.shape[2])298        self.imaSlc = self.orig[:, :, self.sliceNr]299    def updateImaBrowser(self, val):300        """Update image browse."""301        # scale slider value [0,1) to dimension index302        self.updateSliceNr()303        self.remapMsks()304        self.updatePanels(update_slice=True, update_rotation=True,305                          update_extent=True)306    def updateImaExtent(self):307        """Update both image and mask extent in image browser."""308        self.imaSlcH.set_extent((0, self.imaSlc.shape[1],309                                 self.imaSlc.shape[0], 0))310        self.imaSlcMskH.set_extent((0, self.imaSlc.shape[1],311                                    self.imaSlc.shape[0], 0))312    def cycleView(self, event):313        """Cycle through views."""314        self.cycleCount = (self.cycleCount + 1) % 3315        # transpose data316        self.orig = np.transpose(self.orig, (2, 0, 1))317        # transpose ima2volHistMap318        self.invHistVolume = np.transpose(self.invHistVolume, (2, 0, 1))319        # updates320        self.updateSliceNr()321        self.remapMsks()322        self.updatePanels(update_slice=True, update_rotation=True,323                          update_extent=True)324    def rotateIma90(self, axes=(0, 1)):325        """Rotate image slice 90 degrees."""326        self.imaSlc = np.rot90(self.imaSlc, axes=axes)327        self.imaSlcMsk = np.rot90(self.imaSlcMsk, axes=axes)328    def changeRotation(self, event):329        """Change rotation of image after clicking the button."""330        self.cycRotHistory[self.cycleCount][1] += 1331        self.cycRotHistory[self.cycleCount][1] %= 4332        self.rotateIma90()333        self.updatePanels(update_slice=True, update_rotation=False,334                          update_extent=True)335    def checkRotation(self):336        """Check rotation update if changed."""337        cyc_rot = self.cycRotHistory[self.cycleCount][1]338        if cyc_rot == 1:  # 90339            self.rotateIma90(axes=(0, 1))340        elif cyc_rot == 2:  # 180341            self.imaSlc = self.imaSlc[::-1, ::-1]342            self.imaSlcMsk = self.imaSlcMsk[::-1, ::-1]343        elif cyc_rot == 3:  # 270344            self.rotateIma90(axes=(1, 0))345    def exportNifti(self, event):346        """Export labels in the image browser as a nifti file."""347        print("  Exporting nifti file...")348        # put the permuted indices back to their original format349        cycBackPerm = (self.cycleCount, (self.cycleCount+1) % 3,350                       (self.cycleCount+2) % 3)351        # assing unique integers (for ncut labels)352        out_volHistMask = np.copy(self.volHistMask)353        labels = np.unique(self.volHistMask)354        intLabels = [i for i in range(labels.size)]355        for label, newLabel in zip(labels, intLabels):356            out_volHistMask[out_volHistMask == label] = intLabels[newLabel]357        # get 3D brain mask358        volume_image = np.transpose(self.invHistVolume, cycBackPerm)359        if cfg.discard_zeros:360            zmask = volume_image != 0361            temp_labeled_image = map_2D_hist_to_ima(volume_image[zmask],362                                                    out_volHistMask)363            out_nii = np.zeros(volume_image.shape)364            out_nii[zmask] = temp_labeled_image  # put back flat labels365        else:366            out_nii = map_2D_hist_to_ima(volume_image.flatten(),367                                         out_volHistMask)368            out_nii = out_nii.reshape(volume_image.shape)369        # save mask image as nii370        new_image = Nifti1Image(out_nii, header=self.nii.get_header(),371                                affine=self.nii.get_affine())372        # get new flex file name and check for overwriting373        labels_out = '{}_labels_{}.nii.gz'.format(374            self.basename, self.nrExports)375        while os.path.isfile(labels_out):376            self.nrExports += 1377            labels_out = '{}_labels_{}.nii.gz'.format(378                self.basename, self.nrExports)379        save(new_image, labels_out)380        print("    Saved as: {}".format(labels_out))381    def clearOverlays(self):382        """Clear overlaid items such as circle highlights."""383        if self.highlights[0]:384            {h.remove() for h in self.highlights[0]}385            {h.remove() for h in self.highlights[1]}386        self.highlights[0] = []387    def resetGlobal(self, event):388        """Reset stuff."""389        # reset highlights390        self.clearOverlays()391        # reset color bar392        self.sHistC.reset()393        # reset transparency394        self.TranspVal = 0.5395        if self.segmType == 'main':396            if self.lassoSwitchCount == 1:  # reset only lasso drawing397                self.idxLasso = np.zeros(self.nrBins*self.nrBins, dtype=bool)398            else:399                # reset theta sliders400                self.sThetaMin.reset()401                self.sThetaMax.reset()402                # reset values for mask403                self.sectorObj.set_x(cfg.init_centre[0])404                self.sectorObj.set_y(cfg.init_centre[1])405                self.sectorObj.set_r(cfg.init_radius)406                self.sectorObj.tmin, self.sectorObj.tmax = np.deg2rad(407                    cfg.init_theta)408        elif self.segmType == 'ncut':409            self.sLabelNr.reset()410            # reset ncut labels411            self.ima_ncut_labels = np.copy(self.orig_ncut_labels)412            # reset values for volHistMask413            self.volHistMask = self.ima_ncut_labels[:, :, 0].reshape(414                (self.nrBins, self.nrBins))415            # reset counter field416            self.counterField = np.zeros((self.nrBins, self.nrBins))417            # reset political borders418            self.pltMap = np.zeros((self.nrBins, self.nrBins))419            self.pltMapH.set_data(self.pltMap)420        self.updateSliceNr()421        self.remapMsks()422        self.updatePanels(update_slice=False, update_rotation=True,423                          update_extent=False)424    def updateThetaMin(self, val):425        """Update theta (min) in volume histogram mask."""426        if self.segmType == 'main':427            theta_val = self.sThetaMin.val  # get theta value from slider428            self.sectorObj.theta_min(theta_val)429            self.remapMsks()430            self.updatePanels(update_slice=False, update_rotation=True,431                              update_extent=False)432        else:433            return434    def updateThetaMax(self, val):435        """Update theta(max) in volume histogram mask."""436        if self.segmType == 'main':437            theta_val = self.sThetaMax.val  # get theta value from slider438            self.sectorObj.theta_max(theta_val)439            self.remapMsks()440            self.updatePanels(update_slice=False, update_rotation=True,441                              update_extent=False)442        else:443            return444    def exportNyp(self, event):445        """Export histogram counts as a numpy array."""446        print("  Exporting numpy file...")447        outFileName = '{}_identifier_pcMax{}_pcMin{}_sc{}'.format(448            self.basename, cfg.perc_max, cfg.perc_min, int(cfg.scale))449        if self.segmType == 'ncut':450            outFileName = outFileName.replace('identifier', 'volHistLabels')451            out_data = self.volHistMask452        elif self.segmType == 'main':453            outFileName = outFileName.replace('identifier', 'volHist')454            out_data = self.counts455        outFileName = outFileName.replace('.', 'pt')456        np.save(outFileName, out_data)457        print("    Saved as: {}{}".format(outFileName, '.npy'))458    def updateLabels(self, val):459        """Update labels in volume histogram with slider."""460        if self.segmType == 'ncut':461            self.labelNr = self.sLabelNr.val462        else:  # NOTE: might be used in the future463            return464    def imaSlcMskIncr(self, incr):465        """Update transparency of image mask by increment."""466        if (self.TranspVal + incr >= 0) & (self.TranspVal + incr <= 1):467            self.TranspVal += incr468        self.imaSlcMskH.set_alpha(self.TranspVal)469        self.figure.canvas.draw()470    def imaSlcMskTransSwitch(self):471        """Update transparency of image mask to toggle transparency."""472        self.imaSlcMskSwitch = (self.imaSlcMskSwitch+1) % 2473        if self.imaSlcMskSwitch == 1:  # set imaSlcMsk transp474            self.imaSlcMskH.set_alpha(0)475        else:  # set imaSlcMsk opaque476            self.imaSlcMskH.set_alpha(self.TranspVal)477        self.figure.canvas.draw()478    def volHistHighlightTransSwitch(self):479        """Update transparency of highlights to toggle transparency."""480        self.volHistHighlightSwitch = (self.volHistHighlightSwitch+1) % 2481        if self.volHistHighlightSwitch == 1 and self.highlights[0]:482            if self.highlights[0]:483                {h.set_visible(False) for h in self.highlights[0]}484        elif self.volHistHighlightSwitch == 0 and self.highlights[0]:485                {h.set_visible(True) for h in self.highlights[0]}486        self.figure.canvas.draw()487    def updateLabelsRadio(self, val):488        """Update labels with radio buttons."""489        labelScale = self.lMax / 6.  # nr of non-zero radio buttons490        self.labelNr = int(float(val) * labelScale)491    def labelContours(self):492        """Plot political borders used in ncut version."""493        grad = np.gradient(self.volHistMask)494        self.pltMap = np.greater(np.sqrt(np.power(grad[0], 2) +495                                         np.power(grad[1], 2)), 0)496        self.pltMapH.set_data(self.pltMap)497        self.pltMapH.set_extent((0, self.nrBins, self.nrBins, 0))498    def lassoArr(self, array, indices):499        """Update lasso volume histogram mask."""500        lin = np.arange(array.size)501        newArray = array.flatten()502        newArray[lin[indices]] = True503        return newArray.reshape(array.shape)504    def calcImaMaskBrd(self):505        """Calculate borders of image mask slice."""506        return self.imaSlcMsk - binary_erosion(self.imaSlcMsk)507class sector_mask:508    """A pacman-like shape with useful parameters.509    Disclaimer510    ----------511    This script is adapted from a stackoverflow  post by user ali_m:512    [1] http://stackoverflow.com/questions/18352973/mask-a-circular-sector-in-a-numpy-array513    """514    def __init__(self, shape, centre, radius, angle_range):515        """Initialize variables used acros functions here."""516        self.radius, self.shape = radius, shape517        self.x, self.y = np.ogrid[:shape[0], :shape[1]]518        self.cx, self.cy = centre519        self.tmin, self.tmax = np.deg2rad(angle_range)520        # ensure stop angle > start angle521        if self.tmax < self.tmin:522            self.tmax += 2 * np.pi523        # convert cartesian to polar coordinates524        self.r2 = (self.x - self.cx) * (self.x - self.cx) + (525            self.y-self.cy) * (self.y - self.cy)526        self.theta = np.arctan2(self.x - self.cx, self.y - self.cy) - self.tmin527        # wrap angles between 0 and 2*pi528        self.theta %= 2 * np.pi529    def set_polCrd(self):530        """Convert cartesian to polar coordinates."""531        self.r2 = (self.x-self.cx)*(self.x-self.cx) + (532            self.y-self.cy)*(self.y-self.cy)533        self.theta = np.arctan2(self.x-self.cx, self.y-self.cy) - self.tmin534        # wrap angles between 0 and 2*pi535        self.theta %= (2*np.pi)536    def set_x(self, x):537        """Set x axis value."""538        self.cx = x539        self.set_polCrd()  # update polar coordinates540    def set_y(self, y):541        """Set y axis value."""542        self.cy = y543        self.set_polCrd()  # update polar coordinates544    def set_r(self, radius):545        """Set radius of the circle."""546        self.radius = radius547    def scale_r(self, scale):548        """Scale (multiply) the radius."""549        self.radius = self.radius * scale550    def rotate(self, degree):551        """Rotate shape."""552        rad = np.deg2rad(degree)553        self.tmin += rad554        self.tmax += rad555        self.set_polCrd()  # update polar coordinates556    def theta_min(self, degree):557        """Angle to determine one the cut out piece in circular mask."""558        rad = np.deg2rad(degree)559        self.tmin = rad560        # ensure stop angle > start angle561        if self.tmax <= self.tmin:562            self.tmax += 2*np.pi563        # ensure stop angle- 2*np.pi NOT > start angle564        if self.tmax - 2*np.pi >= self.tmin:565            self.tmax -= 2*np.pi566        # update polar coordinates567        self.set_polCrd()568    def theta_max(self, degree):569        """Angle to determine one the cut out piece in circular mask."""570        rad = np.deg2rad(degree)571        self.tmax = rad572        # ensure stop angle > start angle573        if self.tmax <= self.tmin:574            self.tmax += 2*np.pi575        # ensure stop angle- 2*np.pi NOT > start angle576        if self.tmax - 2*np.pi >= self.tmin:577            self.tmax -= 2*np.pi578        # update polar coordinates579        self.set_polCrd()580    def binaryMask(self):581        """Return a boolean mask for a circular sector."""582        # circular mask583        self.circmask = self.r2 <= self.radius*self.radius584        # angular mask585        self.anglemask = self.theta <= (self.tmax-self.tmin)586        # return binary mask587        return self.circmask*self.anglemask588    def contains(self, event):589        """Check if a cursor pointer is inside the sector mask."""590        xbin = np.floor(event.xdata)591        ybin = np.floor(event.ydata)592        Mask = self.binaryMask()593        # the next line doesn't follow pep 8 (otherwise it fails)594        if Mask[ybin][xbin] is True:  # switch x and ybin, volHistMask not Cart595            return True596        else:597            return False598    def draw(self, ax, cmap='Reds', alpha=0.2, vmin=0.1, zorder=0,599             interpolation='nearest', origin='lower', extent=[0, 100, 0, 100]):600        """Draw sector mask."""601        BinMask = self.binaryMask()602        FigObj = ax.imshow(BinMask, cmap=cmap, alpha=alpha, vmin=vmin,603                           interpolation=interpolation, origin=origin,604                           extent=extent, zorder=zorder)...campaign.py
Source:campaign.py  
...126        if arcade.check_for_collision_with_list(self.player_sprite, self.window.cursor):127            self.window.cursor.change_state(state='no')128        else:129            self.window.cursor.change_state(state='idle')130        self.planet_8.update_rotation(delta_time)131        self.planet_7.update_rotation(delta_time)132        self.planet_6.update_rotation(delta_time)133        self.planet_5.update_rotation(delta_time)134        self.planet_4.update_rotation(delta_time)135        self.planet_3.update_rotation(delta_time)136        self.planet_2.update_rotation(delta_time)137        self.planet_1.update_rotation(delta_time)138    def on_draw(self):139        """ Use this function to draw everything to the screen. """140        # Move the angle of the sweep.141        self.angle += RADIANS_PER_FRAME142        # Calculate the end point of our radar sweep. Using math.143        x = self.sweep_length * math.sin(self.angle) + (self.window.width // 2)144        y = self.sweep_length * math.cos(self.angle) + (self.window.height // 2)145        # Start the render. This must happen before any drawing146        # commands. We do NOT need an stop render command.147        self.window.developer_tool.on_draw_start()148        arcade.start_render()149        # Draw the background texture150        arcade.draw_lrwh_rectangle_textured(0, 0,151                                            self.window.width, self.window.height,...sense_hat.py
Source:sense_hat.py  
...6    7    def __init__(self, settings):8        self.settings = settings9        self.hat = PiSenseHat()10        self.update_rotation(settings.get("rotation"))11        self.update_low_light(settings.get("low_light"))12    def get_sensor_values(self):13        return  {14            "humidity": self.hat.get_humidity(),15            "temperature": self.hat.get_temperature(),16            "pressure": self.hat.get_pressure()17        }18    19    def display(self, text, color = None, speed = None):20        if not color: color = [255, 255, 255]21        if not speed: speed = self.settings.get("display_speed")22        brightness = self.settings.get("brightness")23        color = [ int(subcolor * (brightness / 255)) for subcolor in color]24        self.display_bussy = True25        self.hat.show_message(text, text_colour=color, scroll_speed=speed)26        self.display_bussy = False27        self.update_rotation(self.settings.get("rotation"))28    def update_rotation(self, value):29        # Don't update the rotation while 'show_message' is active. It buffers the rotation and resets it to the bufferd value when done...30        # https://github.com/astro-pi/python-sense-hat/blob/9a37f0923ce8dbde69514c3b8d58d30de01c9ee7/sense_hat/sense_hat.py#L46631        if(not self.display_bussy):  32            self.hat.set_rotation(value, False)33    34    def update_low_light(self, value):...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
