Ejemplo n.º 1
0
    def save(
        self,
        path: str,
        save_custom: bool = False,
        image_data_format: ImageDataFormat = None,
        num_workers: int = 0,
    ):
        """Saves scan data to disk with option for custom saving.

        Custom saving may be useful to reduce redundant saving and/or save data in standard
        compatible formats (e.g. medical images - nifti/dicom), which are not feasible with
        python serialization libraries, like pickle.

        When ``save_custom=True``, this method overloads standard pickling with customizable
        saving by first saving data in customizable way (e.g. MedicalVolume -> Nifti file),
        and then pickling the reference to the saved object (e.g. Nifti filepath).

        Currently certain custom saving of objects such as ``pydicom.FileDataset`` and
        :cls:`Tissue` objects are not supported.

        To load the data, do the following:

        >>> filepath = scan.save("/path/to/directory", save_custom=True)
        >>> scan_loaded = type(scan).load(io_utils.load_pik(filepath))

        Args:
            path (str): Directory where data is stored.
            data_format (ImageDataFormat, optional): Format to save data.
                Defaults to ``preferences.image_data_format``.
            save_custom (bool, optional): If ``True``, saves data in custom way specified
                by :meth:`save_custom_data` in format specified by ``data_format``. For
                example, for default classes this will save :cls:`MedicalVolume` data
                to nifti/dicom files as specified by ``image_data_format``.
            image_data_format (ImageDataFormat, optional): The data format to save
                :cls:`MedicalVolume` data. Only used if save_custom is ``True``.
            num_workers (int, bool): Number of workers for saving custom data.
                Only used if save_custom is ``True``.

        Returns:
            str: The path to the pickled file.
        """
        if image_data_format is None:
            image_data_format = preferences.image_data_format

        save_dirpath = path  # self._save_dir(path)
        os.makedirs(save_dirpath, exist_ok=True)
        filepath = os.path.join(save_dirpath, "%s.data" % self.NAME)

        metadata: Dict = {}
        for attr in self.__serializable_variables__():
            metadata[attr] = self.__getattribute__(attr)

        if save_custom:
            metadata = self._save(metadata,
                                  save_dirpath,
                                  image_data_format=image_data_format,
                                  num_workers=num_workers)

        io_utils.save_pik(filepath, metadata)
        return filepath
Ejemplo n.º 2
0
    def save_data(self, base_save_dirpath: str, data_format: ImageDataFormat = preferences.image_data_format):
        """Save data to disk.

        Data will be saved in the directory '`base_save_dirpath`/scan.NAME_data/'
            (e.g. '`base_save_dirpath`/dess_data/').

        Serializes variables specified in by self.__serializable_variables__().

        Override this method to save additional information such as volumes, subvolumes, quantitative maps, etc.
            In override, Call this function (super().save_data(base_save_dirpath)) before adding code to override this
            method.

        Args:
            base_save_dirpath (str): Directory path where all data is stored.
            data_format (ImageDataFormat): Format to save data.
        """

        # Write data as ref.
        save_dirpath = self.__save_dir__(base_save_dirpath)
        filepath = os.path.join(save_dirpath, '%s.data' % self.NAME)

        metadata = dict()
        for variable_name in self.__serializable_variables__():
            metadata[variable_name] = self.__getattribute__(variable_name)

        io_utils.save_pik(filepath, metadata)
Ejemplo n.º 3
0
    def test_pik(self):
        filepath = os.path.join(IO_UTILS_DATA, "sample.pik")
        datas = {
            "type": np.random.rand(10, 45, 2),
            "type2": np.random.rand(13, 95, 4)
        }

        io_utils.save_pik(filepath, datas)
        datas2 = io_utils.load_pik(filepath)

        for data in datas:
            assert (datas[data] == datas2[data]).all()
Ejemplo n.º 4
0
    def __save_quant_data__(self, dirpath: str):
        """Save quantitative data and 2D visualizations of femoral cartilage.

        Check which quantitative values (T2, T1rho, etc) are defined for femoral cartilage and analyze these
            1. Save 2D total, superficial, and deep visualization maps.
            2. Save {'medial', 'lateral'}, {'anterior', 'central', 'posterior'}, {'deep', 'superficial'} data to excel
                file

        Args:
            dirpath (str): Directory path to tissue data.
        """
        q_names = []
        dfs = []

        for quant_val in QuantitativeValueType:
            if quant_val.name not in self.quant_vals.keys():
                continue

            q_names.append(quant_val.name)
            q_val = self.quant_vals[quant_val.name]
            dfs.append(q_val[1])

            q_name_dirpath = io_utils.mkdirs(
                os.path.join(dirpath, quant_val.name.lower()))
            for q_map_data in q_val[0]:
                filepath = os.path.join(q_name_dirpath, q_map_data['filename'])
                xlabel = 'Slice'
                ylabel = 'Angle (binned)'
                title = q_map_data['title']
                data_map = q_map_data['data']

                plt.clf()

                upper_bound = BOUNDS[quant_val]

                if preferences.visualization_use_vmax:
                    # Hard bounds - clipping
                    plt.imshow(data_map,
                               cmap='jet',
                               vmin=0.0,
                               vmax=BOUNDS[quant_val])
                else:
                    # Try to use a soft bounds
                    if np.sum(data_map <= upper_bound) == 0:
                        plt.imshow(data_map,
                                   cmap='jet',
                                   vmin=0.0,
                                   vmax=BOUNDS[quant_val])
                    else:
                        warnings.warn(
                            '%s: Pixel value exceeded upper bound (%0.1f). Using normalized scale.'
                            % (quant_val.name, upper_bound))
                        plt.imshow(data_map, cmap='jet')

                plt.xlabel(xlabel)
                plt.ylabel(ylabel)
                plt.title(title)
                clb = plt.colorbar()
                clb.ax.set_title('(ms)')

                plt.savefig(filepath)

                # Save data
                raw_data_filepath = os.path.join(
                    q_name_dirpath, 'raw_data',
                    q_map_data['raw_data_filename'])
                io_utils.save_pik(raw_data_filepath, data_map)

        if len(dfs) > 0:
            io_utils.save_tables(os.path.join(dirpath, 'data.xlsx'), dfs,
                                 q_names)
Ejemplo n.º 5
0
    def __save_quant_data__(self, dirpath):
        """Save quantitative data and 2D visualizations of patellar cartilage

        Check which quantitative values (T2, T1rho, etc) are defined for
        patellar cartilage and analyze these:

        1. Save 2D total, superficial, and deep visualization maps
        2. Save {'medial', 'lateral'}, {'anterior', 'posterior'},
            {'superior', 'inferior', 'total'} data to excel file

        :param dirpath: base filepath to save data
        """
        q_names = []
        dfs = []

        for quant_val in QuantitativeValueType:
            if quant_val.name not in self.quant_vals.keys():
                continue

            q_names.append(quant_val.name)
            q_val = self.quant_vals[quant_val.name]
            dfs.append(q_val[1])

            q_name_dirpath = io_utils.mkdirs(
                os.path.join(dirpath, quant_val.name.lower()))
            for q_map_data in q_val[0]:
                filepath = os.path.join(q_name_dirpath, q_map_data["filename"])
                xlabel = ""
                ylabel = ""
                title = q_map_data["title"]
                data_map = q_map_data["data"]

                axs_bounds = self.__get_axis_bounds__(data_map,
                                                      leave_buffer=True)

                plt.clf()

                upper_bound = BOUNDS[quant_val]
                if preferences.visualization_use_vmax:
                    # Hard bounds - clipping
                    plt.imshow(data_map,
                               cmap="jet",
                               vmin=0.0,
                               vmax=BOUNDS[quant_val])
                else:
                    # Try to use a soft bounds
                    if np.sum(data_map <= upper_bound) == 0:
                        plt.imshow(data_map,
                                   cmap="jet",
                                   vmin=0.0,
                                   vmax=BOUNDS[quant_val])
                    else:
                        warnings.warn(
                            "%s: Pixel value exceeded upper bound (%0.1f). Using normalized scale."
                            % (quant_val.name, upper_bound))
                        plt.imshow(data_map, cmap="jet")

                plt.xlabel(xlabel)
                plt.ylabel(ylabel)
                plt.title(title)
                plt.ylim(axs_bounds[0])
                plt.gca().invert_yaxis()
                plt.xlim(axs_bounds[1])
                # plt.axis('tight')
                clb = plt.colorbar()
                clb.ax.set_ylabel("(ms)")
                plt.savefig(filepath)

                # Save data
                raw_data_filepath = os.path.join(
                    q_name_dirpath, "raw_data",
                    q_map_data["raw_data_filename"])
                io_utils.save_pik(raw_data_filepath, data_map)

        if len(dfs) > 0:
            io_utils.save_tables(os.path.join(dirpath, "data.xlsx"), dfs,
                                 q_names)