Пример #1
0
def RegisterCT2MRI():
    text = "Runs registration of CT imaging (moving) and T1-sequence (fixed) in order to get them into same space. " \
           "The default option (see cfg-file) constitutes three steps: a) Rigid, b) Affine registration and c) " \
           "Symmetric image Normalisation (SyN). For details see 'SyNRA'-option at " \
           "https://github.com/ANTsX/ANTsPy/blob/master/ants/registration/interface.py. Non-default means, that the " \
           "command-line for running ANTsRegistration can be modified according to the file: " \
           "cmdline_ANTsRegistration.txt in the .utils directory. Please make sure to include all terms within *...* " \
           "into the text-file as they will be replaced."
    return Output.split_lines(text)
Пример #2
0
def RegisterMRI2template():
    text = "Runs registration of MR-imaging (moving) to template sequences (fixed) as defined in the config file in " \
           "order to get them into same space. The default option constitutes three steps: a) Rigid, " \
           "b) Affine registration and c) Symmetric image Normalisation (SyN), although all options available in ANTsPy" \
           "are possible (for details see https://github.com/ANTsX/ANTsPy/blob/master/ants/registration/interface.py. " \
           "Non-default means, that the command-line for running ANTsRegistration can be modified according to " \
           "the file: cmdline_ANTsRegistration.txt in the .utils directory. Please make sure to include all terms " \
           "within *...* into the text-file as they will be replaced."

    return Output.split_lines(text)
Пример #3
0
    def wrapper_multiprocessing(self, fileIDs, subjects, modality):
        """To avoid redundancy between CT and MR  registration to common space, this part is wrapped up here """

        working_dir = self.cfg['folders']['nifti']
        prefix = '{}2template'.format(modality)

        # Start multiprocessing framework
        start_multi = time.time()
        status = mp.Queue()
        processes = [
            mp.Process(target=self.ANTsCoregisterMultiprocessing,
                       args=(filename_fixed, filename_moving, no_subj,
                             os.path.join(working_dir, no_subj),
                             'registration', prefix, status))
            for filename_fixed, filename_moving, no_subj in fileIDs
        ]

        for p in processes:
            p.start()

        while any([p.is_alive() for p in processes]):
            while not status.empty():
                filename_fixed, filename_moving, no_subj = status.get()
                print("\tRegistering {} (f) to {} (m), in ANTsPy\n".format(
                    filename_fixed,
                    os.path.split(filename_moving)[1], no_subj))
            time.sleep(0.1)

        for p in processes:
            p.join()

        # Functions creating/updating pipeline log, which documents all steps along with settings
        for subjID in subjects:
            files_processed = [(os.path.split(file_moving)[1],
                                os.path.split(file_fixed)[1])
                               for file_fixed, file_moving, subj_no in fileIDs
                               if subj_no == subjID]
            log_text = "{} successfully registered (@{}) to \n{}, \n\n Mean Duration per subject: {:.2f} " \
                       "secs".format(files_processed[0][0], time.strftime("%Y%m%d-%H%M%S"), files_processed[0][1],
                                     (time.time() - start_multi) / len(subjects))
            Output.logging_routine(text=Output.split_lines(log_text),
                                   cfg=self.cfg,
                                   subject=str(subjID),
                                   module='{}-Registration'.format(modality),
                                   opt=self.cfg['preprocess']['registration'],
                                   project="")

        print(
            '\nIn total, a list of {} subject(s) was processed; {} registration took {:.2f}secs. '
            'overall'.format(len(subjects), modality,
                             time.time() - start_multi))
Пример #4
0
def LabelFilenameDCM2NII():
    text = "Please enter here the prefix/file information that should be included when saving NIFTI files. " \
           "Characters such as '<', '>', ':', '/' ... MUST be avoided (default is %p_%s). " \
           "From documentation:\n\t %a : antenna (coil) number inserted. For example, the output filename" \
           " 'myName%a' would generate 'myName1', 'myName2', each for each coil. Note that most scans combine data " \
           "from all coils and in these cases this option is ignored. For example, most scans which combine " \
           "data from all coils would simply be called 'myName'\n\t%d :" \
           "series description (0008,103E) inserted. For example, an echo-planar image " \
           "converted with 'myName%d' would yield 'myNameEPI' \n\t%e : echo number " \
           "inserted. For example, a sequence with two echo times converted with the output" \
           "filename 'myName%e' will yield 'myName1' and 'myName2'. Note that most MRI" \
           " sequences only use a single echo time, and in these cases you would only get " \
           "'myName1'.\n\t%f : input folder name inserted. For example, the output " \
           "filename'myName%f' combined with an input folder '/usr/Subj22' will result in " \
           "the output file named'myNameSubj22.nii' \n\t%i : patient ID " \
           "(DICOM tag 0010,0020) inserted. For example, the output filename 'myName%i' " \
           " would convert an image where the patient ID is named 'ID123' to be " \
           " 'myNameID123.nii' \n\t%m : manufacturer name For example, the output filename" \
           " 'myName%m' would convert an image from a GE scanner to 'myNameGE.nii', while " \
           " an image from  Philips would be 'myNamePh.nii', whereas Siemens would be " \
           " 'myNameSi.nii', otherwise the manufacturer is not available ('myNameNA.nii')." \
           " (requires dcm2nii versions from 2015 or later). \n\t%n : subject name (DICOM" \
           " tag 0010,0010) inserted. For example, the output filename 'myName%n' would " \
           " convert an image from John Doe to 'myNameJohnDoe.nii'. This option works best" \
           " if your participant names use only English letters, for other European " \
           " languages you may find it makes some basic conversions ('Müller' will become " \
           " 'Muller'). For non-European languages you will find this option unsatisfactory" \
           ". Perhaps future versions can support DICOM tag 0008,0005. \n\t %p: protocol" \
           " name (DICOM tag 0018,1030) inserted. For example, the output filename" \
           " 'myName%p' would convert image where protocol is named T1 to be 'myNameT1.nii'" \
           " \n\t%q: sequence name (DICOM tag 0018,1020) inserted.For example," \
           " the output filename 'myName%q' would convert a Spin Echo sequence to be " \
           "'myNameSE.nii' (new feature, in versions from 30Aug2015).\n\t%s : series (DICOM " \
           "tag 0020,0011) inserted. For example, the output filename 'myName%s' would " \
           "convert the second series to be 'myName2.nii'. If you want to zero-pad the " \
           "series number, insert the number of digits desired (0..9). For example applying " \
           "the filter 'm%s' when converting 11 series will create files that will cause" \
           " problems for a simple alphabetical sort, e.g. 'm1.nii,m11.nii,m2.nii...m9.nii'." \
           " In contrast specifying 'm%3s' will help sorting (e.g. 'm001.nii,m002.nii" \
           "...m011.nii').\n\t%t : session date and time inserted (DICOM tags 0008,0021 and " \
           "0008,0030). For example, the output filename 'myName%t' would convert an image " \
           "where the session began at 1:23pm on 13 Jan 2014 as 'myName20140113132322.nii' " \
           "\n\t%z : Sequence Name (0018,0024) inserted, so a T1 scan converted with " \
           "'myName%z' might yield 'myNameT1'."

    return Output.split_lines(text)
Пример #5
0
def renameFolders():
    text = 'Displays a small GUI which enables to change the prefix for all folders. This new prefix is saved in ' \
           'the configuration file'
    return Output.split_lines(text)
Пример #6
0
def ProbabilisticMask():
    text = 'Defines whether or not use probablisitic mask. With the use of ANTs for registration and segmentation, ' \
           ' a probabilistic mask is created via ANTsPyNet routines. if set to "yes", the 95th percentile is used, ' \
           ' otherwise data is subtracted from the edges with a sphere analog to the procedure in Lead-DBS'

    return Output.split_lines(text)
Пример #7
0
    def dcm2niix_multiprocessing(self, name_subj, no_subj, dcm2niix_bin,
                                 last_idx, total_subj, status):
        """function intended to provide multiprocessing approach to speed up extraction of DICOM data to nifti files"""

        modalities = ['CT', 'MRI']
        if self.logfile:
            log_filename = os.path.join(
                ROOTDIR, 'logs', 'log_DCM2NII_' + str(no_subj + last_idx) +
                time.strftime("%Y%m%d-%H%M%S"))
        else:
            log_filename = os.devnull

        subj_outdir = os.path.join(
            self.outdir,
            self.cfg['folders']['prefix'] + str(no_subj + last_idx))
        FileOperations.create_folder(subj_outdir)
        start_time_subject = time.time()
        keptfiles, deletedfiles = ([] for _ in range(2))

        for mod in modalities:
            status.put((name_subj, mod, no_subj, total_subj))
            input_folder_name = os.path.join(self.inputdir, name_subj + mod)
            # input_folder_files = [f.path for f in os.scandir(input_folder_name)
            #                       if (f.is_dir() and ('100' in f.path or 'DICOM' in f.path or '001' in f.path))]
            input_folder_files = []
            [
                input_folder_files.append(item)
                for item in os.listdir(input_folder_name)
                if (os.path.isdir(os.path.join(input_folder_name, item)) and (
                    '100' in item or 'DICOM' in item or '001' in item))
            ]

            orig_stdout = sys.stdout
            sys.stdout = open(log_filename, 'w')
            for folder in input_folder_files:
                subprocess.call(
                    [
                        dcm2niix_bin,
                        '-a',
                        'y',  # anonimisation of DICOM data
                        '-b',
                        self.cfg['preprocess']['dcm2nii']['BIDSsidecar'][0],
                        '-z',
                        self.cfg['preprocess']['dcm2nii']['OutputCompression']
                        [0],
                        '-f',
                        self.cfg['preprocess']['dcm2nii']['OutputFileStruct'],
                        '-o',
                        subj_outdir,
                        '-w',
                        str(self.cfg['preprocess']['dcm2nii']
                            ['NameConflicts']),
                        '-v',
                        str(self.cfg['preprocess']['dcm2nii']['Verbosity']),
                        '-x',
                        str(self.cfg['preprocess']['dcm2nii']['ReorientCrop']),
                        folder
                    ],
                    stdout=sys.stdout,
                    stderr=subprocess.STDOUT)

            sys.stdout.close()
            sys.stdout = orig_stdout

            files_kept, files_deleted = self.select_sequences(subj_outdir)
            keptfiles.extend(files_kept)
            deletedfiles.extend(files_deleted)

        # Functions creating/updating pipeline log, which document individually all steps along with settings
        log_text = "{} files successfully converted: {}, \n\nand {} deleted: {}.\nDuration: {:.2f} secs" \
            .format(len(set(keptfiles)),
                    '\n\t{}'.format('\n\t'.join(os.path.split(x)[1] for x in sorted(set(keptfiles)))),
                    len(set(deletedfiles)),
                    '\n\t{}'.format('\n\t'.join(os.path.split(x)[1] for x in sorted(set(deletedfiles)))),
                    time.time() - start_time_subject)
        Output.logging_routine(text=Output.split_lines(log_text),
                               cfg=self.cfg,
                               subject=self.cfg['folders']['prefix'] +
                               str(no_subj),
                               module='dcm2nii',
                               opt=self.cfg['preprocess']['dcm2nii'],
                               project="")
Пример #8
0
def runDCM2NII():
    text = 'Separate GUI to transform DICOM files using Chris Rordens routines ' \
           'see http://www.nitrc.org/projects/dcm2nii/'
    return Output.split_lines(text)
Пример #9
0
def LabelVerbosity():
    text = "According to the documentation this defines whether dcm2nii should be silent (0), with numerous" \
           " output (1) or logorrhoeic (2); default = 1"

    return Output.split_lines(text)
Пример #10
0
def LabelResampleImages():
    text = "Defines the spacing to which imaging will be resampled at. If set to '0' resampling is skipped"

    return Output.split_lines(text)
Пример #11
0
def N4BiasCorrection():
    text = "Reduces the Bias from the MRI using the N4Bias correction method as described in N.J. Tustison, ..., and " \
           "J.C. Gee. "'N4ITK: Improved N3 Bias Correction IEEE Transactions on Medical Imaging, ' \
           "29(6):1310-1320, June 2010."
    return Output.split_lines(text)
Пример #12
0
def BSplineDistance():
    text = "B-spline fitting parameters. With respect to the official documentation, only sizing of the mesh " \
           "elements can be used, whereas the other possible options are left as default. A float value of " \
           "the distance between the knots defining the B-Spline mesh can be chosen"

    return Output.split_lines(text)
Пример #13
0
def displayFolderContent():
    text = 'Display the data available for the subj selected, to see what is present. Note: if more than one ' \
           'subject is selected an error will be dropped!'
    return Output.split_lines(text)
Пример #14
0
def LabelShrink():
    text = "Downsample level applied, specified as integer (factors <= 4 commonly used, see https://manpages.ubuntu.com/manpages/trusty/man1/N4BiasFieldCorrection.1.html)."

    return Output.split_lines(text)
Пример #15
0
def LabelPrefixBias():
    text = "The prefix for the N4Bias-corrected files. Be cautious here as changing this may result in some parts of the toolbox not working"

    return Output.split_lines(text)
Пример #16
0
def LabelReorientCrop():
    text = "This option sets whether reorientation according to header and cropping should be performed or not"

    return Output.split_lines(text)
Пример #17
0
def renameFoldersInput():
    text = "Please enter here the string that replaces the suffix (see left). \nIt may only contain characters, " \
           "numbers and the special characters: '_' and '.', but not at the end "
    return Output.split_lines(text)
Пример #18
0
def ResampleMethod():
    text = "Defines the method appled for resampling images: \n\t - (lin) - linear\n\t - (nn) - nearest neighbour\n\t - (gauss) - gaussian \n\t - (bspline) - B-spline interpolation"

    return Output.split_lines(text)
Пример #19
0
def subjectDetails():
    text = 'Displays the subject details and the names of the subjects corresponding to the prefix'
    return Output.split_lines(text)
Пример #20
0
def compareNIFTIfiles():
    text = "Opens a dialog in order to select NIFTI-files which can be displayed using the image viewer. This enables" \
           " to see whether there have been any problems whatsoever"
    return Output.split_lines(text)
Пример #21
0
def ANTsSettings():
    text = "Displays a separate window in which the options for the ANTsPy routines can be modified."
    return Output.split_lines(text)
Пример #22
0
def saveDirButton():
    text = "The folder is saved into a configuration file, which is read when GUI is loaded in order to " \
           "facilitate continuing with previous session (file located in main folder of Toolbox). Only available " \
           "for some parts of the code"
    return Output.split_lines(text)
Пример #23
0
def N4BiasConvergence():
    text = "Maximum number of iterations for each shrinkage factor and convergence tolerance"

    return Output.split_lines(text)
Пример #24
0
def LabelBIDS():
    text = "This option sets whether sidecar is stored or not (By default, data is always anonimised and BIDS " \
           "are always stored). "

    return Output.split_lines(text)
Пример #25
0
def ChangeWdirDICOM():
    text = (
        'Opens another dialog in which the DICOM directory may be changed. For actions to take place, press '
        '"reload files" button')
    return Output.split_lines(text)
Пример #26
0
def DiffPrefix():
    text = "Prefix for diffusion weighted imaging sequences (if available)."

    return Output.split_lines(text)
Пример #27
0
def run_dcm2niix():
    text = "Before running this script, please make sure that the prefrences are set properly. moreover it is " \
           "recommended to name DICOM folders xxxCT and xxxMRI or one of both. cDBS will specifically look for these " \
           "folders to convert DICOM data from."

    return Output.split_lines(text)
Пример #28
0
def PaCER_MetalThreshold():
    text = "The threshold used to scan for artifacts which may correspond to a lead within the mask of the brain. " \
           "In case none is found, this is lowered automatically"

    return Output.split_lines(text)
Пример #29
0
    def __init__(self, parent=None):
        super(QWidget, self).__init__(parent)

        # Load configuration files and general settings
        self.cfg = Configuration.load_config(ROOTDIR)
        if os.path.isdir(self.cfg['folders']['dicom']):
            self.dicomdir = self.cfg['folders']['dicom']
        else:
            self.dicomdir = FileOperations.set_wdir_in_config(self.cfg, foldername='dicom', init=True)

        self.cfg['folders']['dicom'] = self.dicomdir
        self.cfg['folders']['rootdir'] = ROOTDIR
        Configuration.save_config(ROOTDIR, self.cfg)

        # Create general layout
        self.tot_layout = QVBoxLayout(self)
        self.mid_layout = QHBoxLayout(self)

        # ============================    Create upper of  GUI, i.e. working directory   ============================
        self.folderboxDcm2nii = QGroupBox("Directory (DICOM-files)")
        self.HBoxUpperDcm2nii = QVBoxLayout(self.folderboxDcm2nii)
        self.label_dicomdir = QLabel('dicom DIR: {}'.format(self.dicomdir))
        self.HBoxUpperDcm2nii.addWidget(self.label_dicomdir)

        self.btn_dicomdir = QPushButton('Change working \ndirectory')
        self.btn_dicomdir.setFixedSize(150, 40)
        self.btn_dicomdir.clicked.connect(self.change_dicomdir)
        self.btn_savedir = QPushButton('Save directory \nto config file')
        self.btn_savedir.setFixedSize(150, 40)
        self.btn_savedir.setToolTip(Output.split_lines(setToolTips.saveDirButton()))
        self.btn_savedir.clicked.connect(self.save_cfg)

        hlay_upper = QHBoxLayout()
        hlay_upper.addWidget(self.btn_dicomdir)
        hlay_upper.addWidget(self.btn_savedir)
        hlay_upper.addStretch(1)
        self.HBoxUpperDcm2nii.addLayout(hlay_upper)

        # ====================    Create Content for Lists, i.e. input/output      ====================
        self.listboxInputDcm2nii = QGroupBox('Available subjects in working directory')
        self.listboxInput = QVBoxLayout(self.listboxInputDcm2nii)
        self.mInput = QListWidget()
        self.listboxInput.addWidget(self.mInput)

        self.mButtonToAvailable = QPushButton("<<")
        self.mBtnMoveToAvailable = QPushButton(">")
        self.mBtnMoveToSelected = QPushButton("<")
        self.mButtonToSelected = QPushButton(">>")
        self.mBtnUp = QPushButton("Up")
        self.mBtnDown = QPushButton("Down")

        self.listboxOutputDcm2nii = QGroupBox('Subjects to process')
        self.listboxOutput = QVBoxLayout(self.listboxOutputDcm2nii)
        self.mOutput = QListWidget()
        self.listboxOutput.addWidget(self.mOutput)

        # First column on the left side
        vlay = QVBoxLayout()
        vlay.addStretch()
        vlay.addWidget(self.mBtnMoveToAvailable)
        vlay.addWidget(self.mBtnMoveToSelected)
        vlay.addStretch()
        vlay.addWidget(self.mButtonToAvailable)
        vlay.addWidget(self.mButtonToSelected)
        vlay.addStretch()

        # Second column on the right side
        vlay2 = QVBoxLayout()
        vlay2.addStretch()
        vlay2.addWidget(self.mBtnUp)
        vlay2.addWidget(self.mBtnDown)
        vlay2.addStretch()

        # ====================    Lower part of GUI, i.e. Preferences/Start estimation      ====================
        self.btn_preferences = QPushButton("Preferences")
        self.btn_preferences.clicked.connect(self.settings_show)
        self.btn_run_dcm2niix = QPushButton("Run dcm2niix")
        self.btn_run_dcm2niix.setToolTip(setToolTips.run_dcm2niix())
        self.btn_run_dcm2niix.clicked.connect(self.start_converting)

        hlay_bottom = QHBoxLayout()
        hlay_bottom.addStretch(1)
        hlay_bottom.addWidget(self.btn_preferences)
        hlay_bottom.addWidget(self.btn_run_dcm2niix)
        hlay_bottom.addStretch()

        # ====================    Set all contents to general Layout     =======================
        self.mid_layout.addWidget(self.listboxInputDcm2nii)
        self.mid_layout.addLayout(vlay)
        self.mid_layout.addWidget(self.listboxOutputDcm2nii)
        self.mid_layout.addLayout(vlay2)

        self.tot_layout.addWidget(self.folderboxDcm2nii)
        self.tot_layout.addLayout(self.mid_layout)
        self.tot_layout.addLayout(hlay_bottom)

        try:
            self.mInput.clear()
            items = FileOperations.list_folders(inputdir=self.cfg['folders']['dicom'], prefix='', files2lookfor='')
            items = self.check_for_complete_input(list(items))
            self.add_available_subj(items)
        except FileExistsError:
            print('{} without any valid files/folders, continuing ...'.format(self.dicomdir))

        self.update_buttons_status()
        self.connections()
Пример #30
0
def PaCER_Lambda():
    text = "Not sure what it does!! Please double check"

    return Output.split_lines(text)