예제 #1
0
def sample2DNifti1():
    nifti = readNifti(test_3DNifti1Path)
    newData = getNiftiData(nifti)
    # max positive value of 2 byte, signed short used in Nifti header for
    # storing dimension information
    newData = (newData.flatten()[:10000]).reshape((100, 100))
    return nib.Nifti1Image(newData, nifti.affine)
예제 #2
0
def test_nifti():
    with tempfile.TemporaryDirectory() as tmpDir:
        niftiFilename = os.path.join(tmpDir, 'nifti1.nii')
        imgHandler.convertDicomFileToNifti(dicomFile, niftiFilename)
        niftiImg1 = imgHandler.readNifti(niftiFilename)

        dcmImg = imgHandler.readDicomFromFile(dicomFile)
        niftiImgFromDcm = imgHandler.convertDicomImgToNifti(dcmImg)
        assert niftiImg1.header == niftiImgFromDcm.header
        assert np.array_equal(np.array(niftiImg1.dataobj),
                              np.array(niftiImgFromDcm.dataobj))
예제 #3
0
def sampleNifti2():
    return readNifti(test_4DNifti2Path)
예제 #4
0
def sample4DNifti1():
    return readNifti(test_4DNifti1Path)
예제 #5
0
def sample3DNifti2():
    return readNifti(test_3DNifti2Path)
예제 #6
0
def sample3DNifti1():
    return readNifti(test_3DNifti1Path)
예제 #7
0
def doRuns(cfg, dataInterface, subjInterface, webInterface):
    """
    This function is called by 'main()' below. Here, we use the 'dataInterface'
    to read in dicoms (presumably from the scanner, but here it's from a folder
    with previously collected dicom files), doing some sort of analysis in the
    cloud, and then sending the info to the web browser.

    INPUT:
        [1] cfg (configuration file with important variables)
        [2] dataInterface (this will allow a script from the cloud to access files
               from the stimulus computer, which receives dicom files directly
               from the Siemens console computer)
        [3] subjInterface - this allows sending feedback (e.g. classification results)
                to a subjectService running on the presentation computer to provide
                feedback to the subject (and optionally get their response).
    OUTPUT:
        None.
    """

    # variables we'll use throughout
    scanNum = cfg.scanNum[0]
    runNum = cfg.runNum[0]

    # obtain the path for the directory where the subject's dicoms live
    cfg.dicomDir = cfg.imgDir
    print("Location of the subject's dicoms: %s\n" % cfg.dicomDir)

    # Initialize a watch for the entire dicom folder using the function 'initWatch'
    # in dataInterface. (Later we will use watchFile() to look for a specific dicom)
    #   INPUT:
    #       [1] cfg.dicomDir (where the subject's dicom files live)
    #       [2] cfg.dicomNamePattern (the naming pattern of dicom files)
    #       [3] cfg.minExpectedDicomSize (a check on size to make sure we don't
    #               accidentally grab a dicom before it's fully acquired)
    dataInterface.initWatch(cfg.dicomDir, cfg.dicomNamePattern,
                            cfg.minExpectedDicomSize)

    #We will use the function plotDataPoint in webInterface whenever we
    #  want to send values to the web browser so that they can be plotted in the
    #  --Data Plots-- tab.
    #However at the start of a run we will want to clear the plot, and we can use
    #clearRunPlot(runId), or clearAllPlots() also in the webInterface object.
    print(
        "\n\nClearing any pre-existing plot for this run using 'clearRunPlot(runNum)'"
    )
    webInterface.clearRunPlot(runNum)
    print(
        ''
        '###################################################################################'
    )

    # declare the total number of TRs
    num_trainingData = cfg.numTrainingTRs
    num_total_TRs = cfg.numSynthetic

    for this_TR in np.arange(num_total_TRs):
        # declare variables that are needed to use 'readRetryDicomFromDataInterface'
        timeout_file = 5  # small number because of demo, can increase for real-time

        # use 'getDicomFileName' from 'imageHandling.py' to obtain the filename
        #   of the dicom data you want to get... which is useful considering how
        #   complicated these filenames can be!
        #   INPUT:
        #       [1] cfg (config parameters)
        #       [2] scanNum (scan number)
        #       [3] fileNum (TR number, which will reference the correct file)
        #   OUTPUT:
        #       [1] fullFileName (the filename of the dicom that should be grabbed)
        fileName = getDicomFileName(cfg, scanNum, this_TR)

        # Use 'readRetryDicomFromDataInterface' in 'imageHandling.py' to wait for dicom
        #    files to be written by the scanner (uses 'watchFile' internally) and then
        #    reading the dicom file once it is available.
        #INPUT:
        #    [1] dataInterface (allows a cloud script to access files from the
        #        control room computer)
        #    [2] filename (the dicom file we're watching for and want to load)
        #    [3] timeout (time spent waiting for a file before timing out)
        #OUTPUT:
        #    [1] dicomData (with class 'pydicom.dataset.FileDataset')
        dicomData = readRetryDicomFromDataInterface(dataInterface, fileName,
                                                    timeout_file)

        # We can use the 'convertDicomFileToNifti' function with dicomData as
        #   input to get the data in NifTi format
        base, ext = os.path.splitext(fileName)
        assert ext == '.dcm'
        niftiFilename = base + '.nii'
        convertDicomFileToNifti(fileName, niftiFilename)
        niftiObject = readNifti(niftiFilename)

        # declare various things if it's the first TR
        if this_TR == 0:
            # load the labels and mask
            labels = np.load(os.path.join(cfg.imgDir, 'labels.npy'))
            print(os.path.join(cfg.imgDir, 'labels.npy'))
            ROI_nib = nib.load(os.path.join(currPath, 'ROI_mask.nii.gz'))
            ROI_mask = np.array(ROI_nib.dataobj)
            mask_nib = nib.Nifti1Image(ROI_mask.T, affine=niftiObject.affine)
            # declare the number of TRs we will shift the data to account for the hemodynamic lag
            num_shiftTRs = 3
            # shift the labels to account for hemodynamic lag
            shifted_labels = np.concatenate(
                [np.full((num_shiftTRs, 1), np.nan), labels])
            # set up a matrix that will hold all of the preprocessed data
            preprocessed_data = np.full((num_total_TRs, int(ROI_mask.sum())),
                                        np.nan)

        # preprocess the training data by applying the mask
        preprocessed_data[this_TR, :] = np.ravel(
            apply_mask(niftiObject, mask_nib).reshape(int(ROI_mask.sum()), 1))

        ## Now we divide into one of three possible steps

        # STEP 1: collect the training data
        if this_TR < num_trainingData:
            print('Collected training data for TR %s' % this_TR)
        # STEP 2: train the SVM model
        elif this_TR == num_trainingData:
            print(
                ''
                '###################################################################################'
            )
            print(
                'Done collecting training data! \nStart training the classifier.'
            )

            # snapshot of time to keep track of how long it takes to train the classifier
            start_time = time.time()

            scaler = StandardScaler()
            X_train = preprocessed_data[num_shiftTRs:num_trainingData]
            y_train = shifted_labels[num_shiftTRs:num_trainingData].reshape(
                -1, )
            # we don't want to include rest data
            X_train_noRest = X_train[y_train != 0]
            y_train_noRest = y_train[y_train != 0]
            # and we want to zscore the bold data
            X_train_noRest_zscored = scaler.fit_transform(X_train_noRest)
            clf = svm.SVC(kernel='linear', C=0.01, class_weight='balanced')
            clf.fit(X_train_noRest_zscored, y_train_noRest)

            # print out the amount of time it took to train the classifier
            print('Classifier done training! Time it took: %.2f s' %
                  (time.time() - start_time))
            print(
                ''
                '###################################################################################'
            )
        elif this_TR > num_trainingData:
            # apply the classifier to new data to obtain prediction IF not a rest trial
            if shifted_labels[this_TR] != 0:
                prediction = clf.predict(
                    scaler.transform(preprocessed_data[this_TR, :].reshape(
                        1, -1)))
                print(
                    f'Plotting classifier prediction for TR {this_TR}: {prediction}'
                )
                webInterface.plotDataPoint(runNum, int(this_TR),
                                           float(prediction))

                # To send feedback for the subject at the presentation computer use
                #   the subjInterface as shown below. For this demo there is no
                #   presentation computer so we won't actually it.
                # subjInterface.setResult(runNum, int(this_TR), float(prediction))
            else:
                print(f'Skipping classification because it is a rest trial')

    X_test = preprocessed_data[num_trainingData + 1:]
    y_test = shifted_labels[num_trainingData + 1:num_total_TRs].reshape(-1, )
    # we don't want to include the rest data
    X_test_noRest = X_test[y_test != 0]
    y_test_noRest = y_test[y_test != 0]
    # and we want to zscore the bold data
    X_test_noRest_zscored = scaler.transform(X_test_noRest)
    accuracy_score = clf.score(X_test_noRest_zscored, y_test_noRest)
    print('Accuracy of classifier on new data: %s' % accuracy_score)
    # print(y_test_noRest)
    # print(clf.predict(X_test_noRest_zscored))

    print(
        ""
        "###################################################################################\n"
        "REAL-TIME EXPERIMENT COMPLETE!")

    return