def runAnalysis(self):
        """ Compute all the features that are currently selected, for the nodule and/or for
        the surrounding spheres
        """
        # build list of features and feature classes based on what is checked by the user
        self.selectedMainFeaturesKeys = set()
        self.selectedFeatureKeys = set()
        self.analysisResults = dict()
        self.analysisResultsTiming = dict()
        self.__analyzedSpheres__ = set()

        for featureClass in self.featureWidgets:
            for widget in self.featureWidgets[featureClass]:
                if widget.checked:
                    self.selectedMainFeaturesKeys.add(featureClass)
                    self.selectedFeatureKeys.add(str(widget.text))

        # Preconditions
        if self.inputVolumeSelector.currentNode() is None:
            # TODO: disable the button until segmentation is done
            qt.QMessageBox.warning(slicer.util.mainWindow(), "Select a volume",
                                   "Please select and segment an input volume")
            return
        if self.logic.currentLabelmap is None:
            qt.QMessageBox.warning(slicer.util.mainWindow(), "Segment a labelmap",
                                   "Please select and segment a labelmap volume")
            return
        if len(self.selectedFeatureKeys) == 0:
            qt.QMessageBox.information(slicer.util.mainWindow(), "Select a feature",
                                       "Please select at least one feature from the menu to calculate")
            return
        if "Parenchymal Volume" in self.selectedMainFeaturesKeys and self.parenchymaLabelmapSelector.currentNode() is None:
            qt.QMessageBox.warning(slicer.util.mainWindow(), "Select a labelmap",
                                   "Please select a segmented emphysema labelmap in the Parenchymal Volume tab")
            return

        if self.otherRadiusCheckbox.checked and int(self.otherRadiusTextbox.text) > self.logic.MAX_TUMOR_RADIUS:
            qt.QMessageBox.warning(slicer.util.mainWindow(), "Invalid value",
                                   "The radius of the sphere must have a maximum value of {0}".format(
                                       self.logic.MAX_TUMOR_RADIUS))
            return

        try:
            # Analysis for the volume and the nodule:
            keyName = self.inputVolumeSelector.currentNode().GetName()
            start = time.time()
            if self.noduleCheckbox.checked:
                logic = FeatureExtractionLogic(self.logic.currentVolume, self.logic.currentVolumeArray,
                                               self.logic.currentLabelmapArray,
                                               self.selectedMainFeaturesKeys.difference(["Parenchymal Volume"]),
                                               self.selectedFeatureKeys.difference(
                                                   self.featureClasses["Parenchymal Volume"]))

                print("******** Nodule analysis results...")
                t1 = start

                t2 = time.time()

                self.analysisResults[keyName] = collections.OrderedDict()
                self.analysisResultsTiming[keyName] = collections.OrderedDict()
                logic.run(self.analysisResults[keyName], self.logic.printTiming, self.analysisResultsTiming[keyName])

                # Print analysis results
                print(self.analysisResults[keyName])

                if self.logic.printTiming:
                    print("Elapsed time for the nodule analysis (TOTAL={0} seconds:".format(t2 - t1))
                    print(self.analysisResultsTiming[keyName])

            # Check in any sphere has been selected for the analysis, because otherwise it's not necessary to calculate the distance map
            anySphereChecked = False
            for r in self.logic.spheresDict[self.workingMode]:
                if self.spheresButtonGroup.button(r*10).isChecked():
                    anySphereChecked = True
                    break
            if self.otherRadiusCheckbox.checked and self.otherRadiusTextbox.text != "":
                anySphereChecked = True

            # if self.r15Checkbox.checked or self.r20Checkbox.checked or self.r25Checkbox.checked \
            #         or (self.rOtherCheckbox.checked and self.otherRadiusTextbox.text != ""):
            if anySphereChecked:
                if "Parenchymal Volume" in self.selectedMainFeaturesKeys:
                    # If the parenchymal volume analysis is required, we need the numpy array represeting the whole
                    # emphysema segmentation labelmap
                    labelmapWholeVolumeArray = slicer.util.array(self.parenchymaLabelmapSelector.currentNode().GetName())
                else:
                    labelmapWholeVolumeArray = None

                # print("DEBUG: analyzing spheres...")
                t1 = time.time()
                self.logic.getCurrentDistanceMap()
                if self.logic.printTiming:
                    print("Time to get the current distance map: {0} seconds".format(time.time() - t1))
                for r in self.logic.spheresDict[self.workingMode]:
                    if self.spheresButtonGroup.button(r*10).isChecked():
                        self.runAnalysisSphere(r, labelmapWholeVolumeArray)
                        self.__analyzedSpheres__.add(r)
                # if self.r15Checkbox.checked:
                #     self.runAnalysisSphere(15, labelmapWholeVolumeArray)
                #     self.__analyzedSpheres__.add(15)
                # if self.r20Checkbox.checked:
                #     self.runAnalysisSphere(20, labelmapWholeVolumeArray)
                #     self.__analyzedSpheres__.add(20)
                # if self.r25Checkbox.checked:
                #     self.runAnalysisSphere(25, labelmapWholeVolumeArray)
                #     self.__analyzedSpheres__.add(25)
                if self.otherRadiusCheckbox.checked:
                    r = int(self.otherRadiusTextbox.text)
                    self.runAnalysisSphere(r, labelmapWholeVolumeArray)
                    self.__analyzedSpheres__.add(r)

            t = time.time() - start
            if self.logic.printTiming:
                print("********* TOTAL ANALYSIS TIME: {0} SECONDS".format(t))

            # Save the results in the report widget
            qt.QMessageBox.information(slicer.util.mainWindow(), "Process finished",
                                       "Analysis finished. Total time: {0} seconds. Click the \"Open\" button to see the results".format(t))

            self.refreshUI()
        except __HOLE__:
            qt.QMessageBox.warning(slicer.util.mainWindow(), "Process cancelled",
                                   "The process has been cancelled by the user")
        finally:
            self.saveReport(showConfirmation=False)
dataset/ETHPy150Open acil-bwh/SlicerCIP/Scripted/CIP_LesionModel/CIP_LesionModel.py/CIP_LesionModelWidget.runAnalysis