def turnTo(self, turnToIdx, skipPreload=False):
        """
        Turn to the turnToIdx th scan, load scan and label
        """
        if turnToIdx == self._currScanIdx:
            return False
        if self._turninig:
            return

        self._turninig = True
        # 0. clear nodes from previous task and prepare states
        self.initPb("Preparing to load", "Load scan and label")
        self.setPb(0.1)

        if self.segmentation is not None:
            self.saveSegmentation()
        if self._usingInteractive:
            self.exitInteractiveMode()

        if len(self._scanPaths) == 0:
            slicer.util.errorDisplay(
                "No scan found, please load scans first.", autoCloseMsec=2000)
            self.closePb()
            self._turninig = False
            return

        logging.info(
            f"Turning to the {turnToIdx}th scan, path is {self._scanPaths[turnToIdx]}"
        )

        self.ui.dgPositiveControlPointPlacementWidget.setEnabled(False)
        self.ui.dgNegativeControlPointPlacementWidget.setEnabled(False)

        self.clearScene()  # remove segmentation node and control points
        self._currScanIdx = turnToIdx

        slicer.app.processEvents()
        # 1. load new scan & preprocess
        image_path = self._scanPaths[turnToIdx]
        self.setPb(0.2, f"Loading {osp.basename(image_path)}")
        self._currVolumeNode = self.getScan(image_path)
        self._currVolumeNode.SetName(osp.basename(image_path))
        self.manageCache(turnToIdx, skipPreload=skipPreload)

        # 2. load segmentation or create an empty one
        self.setPb(0.8, "Loading segmentation")
        dot_pos = image_path.find(".")
        self._currLabelPath = image_path[:dot_pos] + "_label" + image_path[
            dot_pos:]
        if osp.exists(self._currLabelPath):
            segmentNode = slicer.modules.segmentations.logic(
            ).LoadSegmentationFromFile(self._currLabelPath, False)
        else:
            segmentNode = slicer.mrmlScene.AddNewNodeByClass(
                "vtkMRMLSegmentationNode")

        segmentNode.SetName("EISegMed3DSegmentation")
        segmentNode.SetReferenceImageGeometryParameterFromVolumeNode(
            self._currVolumeNode)
        slicer.app.processEvents()
        slicer.app.processEvents()
        # update category info

        for segment in self.segments:
            if segment.GetNameAutoGenerated():
                segment.SetName(f"Segment_{segment.GetLabelValue()}")
        self._prevCatg = None
        self.catgFile2Segmentation()
        self.catgSegmentation2File()

        for idx, segment in enumerate(self.segments):
            # print(f"setting color for segment name: {segment.GetName()}, color: {colors[idx % len(colors)]}")
            segment.SetColor(colors[idx % len(colors)])
            segment.SetColor(colors[idx % len(colors)])
            segment.SetColor(colors[idx % len(colors)])

        def sync(*args):
            if not self._turninig:
                self.catgSegmentation2File()

        def setDirty(*args):
            if not self._turninig:
                self._dirty = True

        segmentNode.AddObserver(
            segmentNode.GetContentModifiedEvents().GetValue(5), sync)
        segmentNode.AddObserver(
            segmentNode.GetContentModifiedEvents().GetValue(4), sync)
        segmentNode.AddObserver(
            segmentNode.GetContentModifiedEvents().GetValue(1), setDirty)

        # add: 3, 5
        # edit: 5
        # remove: 1, 2, 4 (will be triggered when turn task)

        # 3. create category label from txt and segmentation
        self.setPb(0.8, "Syncing progress")
        self.saveProgress()
        self.updateProgressWidgets()

        # 4. set image
        self.setPb(0.9, "Preprocessing image for interactive segmentation")
        if not TEST:
            self.prepImage()

        # 5. set the editor as current result.
        self.setPb(0.95, "Wrapping up")
        self.ui.embeddedSegmentEditorWidget.setSegmentationNode(segmentNode)
        self.ui.embeddedSegmentEditorWidget.setMasterVolumeNode(
            self._currVolumeNode)

        self.ui.dgPositiveControlPointPlacementWidget.setEnabled(True)
        self.ui.dgNegativeControlPointPlacementWidget.setEnabled(True)

        # 6. change button state
        self.togglePrevNextBtn(self._currScanIdx)

        layoutManager = slicer.app.layoutManager()
        for sliceViewName in layoutManager.sliceViewNames():
            layoutManager.sliceWidget(sliceViewName).mrmlSliceNode(
            ).RotateToVolumePlane(self._currVolumeNode)
        slicer.util.resetSliceViews()

        self.closePb()
        self._turninig = False

        Turn to the turnToIdx th scan, load scan and label
        
EISeg/med3d/EISegMed3D/EISegMed3D.py