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
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)
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()
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)
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)