Beispiel #1
0
    def data(self, data):
        data = self._preprocess_data(data)
        if isinstance(data, dict):
            labeled_by = data.pop('labeled_by', 'rows')
            data_contiguous = data.pop('contiguous', None)
            if data_contiguous is not None:
                self.data = data_contiguous
                if len(data) == 0:
                    return

            if labeled_by not in ('rows', 'columns'):
                raise ValueError(
                    'when data provided as a dictionary of '
                    'matrices, the optional dictionary entry '
                    '`labeled_by` must be one of `columns` or `rows` '
                    '(default)')
            if not all(sparse_or_dense(m) for m in data.values()):
                raise TypeError('when data provided as a dictionary of '
                                'matrices, each value must be one of the '
                                'following matrix types: {}'
                                ''.format(CONRAD_MATRIX_TYPES))
            if labeled_by == 'columns':
                for mat in data.values():
                    rows = mat.shape[0]
                    break
                if not all([m.shape[0] == rows for m in data.values()]):
                    raise ValueError('all submatrices must have consistent '
                                     'number of rows when a dictionary of '
                                     'horizontally concatenable matrices is '
                                     'provided')
                columns = sum([m.shape[1] for m in data.values()])
            else:
                rows = sum([m.shape[0] for m in data.values()])
                for mat in data.values():
                    columns = mat.shape[1]
                    break
                if not all([m.shape[1] == columns for m in data.values()]):
                    raise ValueError('all submatrices must have consistent '
                                     'number of columns when a dictionary of '
                                     'vertically concatenable matrices is '
                                     'provided')

            self.__shape_check((rows, columns))
            self.__dim1, self.__dim2 = rows, columns
            if labeled_by == 'columns':
                self.__column_slices.update(data)
            else:
                self.__row_slices.update(data)
        else:
            if not sparse_or_dense(data):
                raise TypeError('when data provided as a singleton matrix, '
                                'it must be formatted as one of the following '
                                'matrix types {}'.format(CONRAD_MATRIX_TYPES))
            self.__shape_check(data.shape)
            self.__dim1, self.__dim2 = data.shape
            self.__data = data
Beispiel #2
0
	def frame0_to_1(self, in_):
		"""
		Allocating version of :meth`AbstractMapping.frame1_to_0`.

		If input array is a matrix, mapping operates on rows. If array
		is a vector, mapping operates on entries.

		Arguments:
			in_: Input array with :attr:`AbstractMapping.n_frame0` rows
				and ``k`` >= ``1`` columns.

		Returns:
			:class:`numpy.ndarray`: Array with
			:attr:`AbstractMapping.n_frame0` rows and same number of
			columns as input. Input entries are mapped one-to-one or
			many-to-one *into* output.
		"""
		if is_vector(in_):
			out_ = zeros(self.__n_frame0)
		elif sparse_or_dense(in_):
			dim1 = self.__n_frame0
			dim2 = in_.shape[1]
			out_ = zeros((dim1, dim2))

		return self.frame1_to_0_inplace(in_, out_)
Beispiel #3
0
	def frame0_to_1(self, in_):
		"""
		Map elements of array ``in_`` to a new array.

		If input array is a matrix, mapping operates on rows. If array
		is a vector, mapping operates on entries.

		A new empty vector or matrix

		Arguments:
			in_: Input array with :attr:`AbstractMapping.n_frame0` rows
				and ``k`` >= ``1`` columns.

		Returns:
			:class:`numpy.ndarray`: Array with
			:attr:`AbstractMapping.n_frame1` rows and ``k`` columns.
			Input entries are mapped one-to-one or one-to-many *into*
			output.
		"""
		if is_vector(in_):
			out_ = zeros(self.__n_frame1)
		elif sparse_or_dense(in_):
			dim1 = self.__n_frame1
			dim2 = in_.shape[1]
			out_ = zeros((dim1, dim2))

		return self.frame0_to_1_inplace(in_, out_)
Beispiel #4
0
 def to_unsafe_data(self, unsafe_file_entry):
     if isinstance(unsafe_file_entry, dict):
         unsafe_file_entry = UnsafeFileEntry(**unsafe_file_entry)
     if not isinstance(unsafe_file_entry, UnsafeFileEntry):
         raise TypeError('input should be of type (or parsable as) {}'
                         ''.format(UnsafeFileEntry))
     if not unsafe_file_entry.complete:
         raise ValueError(
             'no numpy file assigned to {}'.format(UnsafeFileEntry))
     typed_data = self.read_all(unsafe_file_entry.file)
     if isinstance(typed_data, np.ndarray):
         return typed_data
     if sparse_or_dense(typed_data):
         return typed_data
     if isinstance(typed_data, dict):
         sme = SparseMatrixEntry(**typed_data)
         if sme.complete:
             return self.to_sparse_matrix(sme)
         dme = DenseMatrixEntry(**typed_data)
         if dme.complete:
             return self.to_dense_matrix(dme)
         ve = VectorEntry(**typed_data)
         if ve.complete:
             return self.to_vector(ve)
     return typed_data
Beispiel #5
0
 def A_mean(self, A_mean=None):
     if A_mean is not None:
         if not isinstance(A_mean, np.ndarray):
             raise TypeError('if argument "A_mean" is provided, it must be '
                             'of type {}'.format(np.ndarray))
         elif not A_mean.size in A_mean.shape:
             raise ValueError(
                 'if argument "A_mean" is provided, it must be '
                 'a row or column vector. shape of argument: {}'
                 ''.format(A_mean.shape))
         else:
             if self.__A_full is not None:
                 if len(A_mean) != self.__A_full.shape[1]:
                     raise ValueError(
                         'field "A_full" already set; proposed '
                         'value for "A_mean" must have same '
                         'number of entries ({}) as columns in '
                         'A_full ({})'.format(len(A_mean),
                                              self.__A_full.shape[1]))
         self.__A_mean = vec(A_mean)
     elif self.__A_full is not None:
         if not sparse_or_dense(self.A_full):
             raise TypeError('cannot calculate structure.A_mean from'
                             'structure.A_full: A_full must be one of '
                             '({},{},{})'.format(np.ndarray, sp.csc_matrix,
                                                 sp.csr_matrix))
         else:
             if isinstance(self.A_full, np.ndarray):
                 self.__A_mean = np.dot(self.voxel_weights, self.A_full)
             else:
                 self.__A_mean = vec(self.voxel_weights * self.A_full)
             self.__A_mean /= float(self.weighted_size)
Beispiel #6
0
	def A_mean(self, A_mean=None):
		if A_mean is not None:
			if not isinstance(A_mean, ndarray):
				raise TypeError('if argument "A_mean" is provided, it '
								'must be of type {}'.format(ndarray))
			elif not A_mean.size in A_mean.shape:
				raise ValueError('if argument "A_mean" is provided, it must be'
								 ' a row or column vector. shape of argument: '
								 '{}'.format(A_mean.shape))
			else:
				if self.__A_full is not None:
					if len(A_mean) != self.__A_full.shape[1]:
						raise ValueError('field "A_full" already set; '
										 'proposed value for "A_mean" '
										 'must have same number of entries '
										 '({}) as columns in A_full ({})'
										 ''.format(len(A_mean),
										 self.__A_full.shape[1]))
				self.__A_mean = vec(A_mean)
		elif self.__A_full is not None:
			if not sparse_or_dense(self.A_full):
				raise TypeError('cannot calculate structure.A_mean from'
								'structure.A_full: A_full must be one of'
								' ({},{},{})'.format(ndarray, csc_matrix,
								csr_matrix))
			else:
				self.__A_mean = self.A_full.sum(0) / self.A_full.shape[0]
				if not isinstance(self.A_full, ndarray):
					self.__A_mean = vec(self.__A_mean)
Beispiel #7
0
	def frame1_to_0(self, in_):
		"""
		Allocating version of :meth`DiscreteMapping.frame1_to_0`.

		If input array is a matrix, mapping operates on rows. If array
		is a vector, mapping operates on entries.

		Arguments:
			in_: Input array with :attr:`DiscreteMapping.n_frame0` rows
				and ``k`` >= ``1`` columns.

		Returns:
			:class:`numpy.ndarray`: Array with
			:attr:`DiscreteMapping.n_frame0` rows and same number of
			columns as input. Input entries are mapped one-to-one or
			many-to-one *into* output.
		"""
		if is_vector(in_):
			out_ = np.zeros(self.__n_frame0)
		elif sparse_or_dense(in_):
			dim1 = self.__n_frame0
			dim2 = in_.shape[1]
			out_ = np.zeros((dim1, dim2))

		return self.frame1_to_0_inplace(in_, out_)
Beispiel #8
0
	def frame0_to_1(self, in_):
		"""
		Map elements of array ``in_`` to a new array.

		If input array is a matrix, mapping operates on rows. If array
		is a vector, mapping operates on entries.

		A new empty vector or matrix

		Arguments:
			in_: Input array with :attr:`DiscreteMapping.n_frame0` rows
				and ``k`` >= ``1`` columns.

		Returns:
			:class:`numpy.ndarray`: Array with
			:attr:`DiscreteMapping.n_frame1` rows and ``k`` columns.
			Input entries are mapped one-to-one or one-to-many *into*
			output.
		"""
		if is_vector(in_):
			out_ = np.zeros(self.__n_frame1)
		elif sparse_or_dense(in_):
			dim1 = self.__n_frame1
			dim2 = in_.shape[1]
			out_ = np.zeros((dim1, dim2))

		return self.frame0_to_1_inplace(in_, out_)
Beispiel #9
0
 def write_matrix(self, directory, name, matrix, overwrite=False):
     if not sparse_or_dense(matrix):
         raise TypeError('matrix to save must be one of {}'
                         ''.format(CONRAD_MATRIX_TYPES))
     if isinstance(matrix, np.ndarray):
         return self.write_dense_matrix(directory, name, matrix, overwrite)
     else:
         return self.write_sparse_matrix(directory, name, matrix, overwrite)
Beispiel #10
0
    def plannable(self):
        """
		True if structure's attached data is sufficient for optimization.

		Minimum requirements:
			- Structure size determined, and
			- Dose matrix assigned, *or*
			- Structure collapsable and mean dose matrix assigned.
		"""
        size_determined = positive_real_valued(self.size)
        full_mat_usable = sparse_or_dense(self.A_full)
        if full_mat_usable:
            full_mat_usable &= self.size == self.A_full.shape[0]

        collapsed_mat_usable = bool(
            isinstance(self.A_mean, np.ndarray) and self.collapsable)

        usable_matrix_loaded = full_mat_usable or collapsed_mat_usable
        return size_determined and usable_matrix_loaded
Beispiel #11
0
	def plannable(self):
		"""
		True if structure's attached data is sufficient for optimization.

		Minimum requirements:
			- Structure size determined, and
			- Dose matrix assigned, *or*
			- Structure collapsable and mean dose matrix assigned.
		"""
		size_set = positive_real_valued(self.size)
		full_mat_usable = sparse_or_dense(self.A_full)
		if full_mat_usable:
			full_mat_usable &= self.size == self.A_full.shape[0]

		collapsed_mat_usable = bool(
				isinstance(self.A_mean, ndarray) and self.collapsable)

		usable_matrix_loaded = full_mat_usable or collapsed_mat_usable
		return size_set and usable_matrix_loaded
Beispiel #12
0
    def A_full(self, A_full):
        if A_full is None:
            return

        # verify type of A_full
        if not sparse_or_dense(A_full):
            raise TypeError('input A must by a numpy or scipy csr/csc '
                            'sparse matrix')

        if self.size is not None:
            if A_full.shape[0] != self.size:
                raise ValueError('# rows of "A_full" must correspond to '
                                 'value  of property size ({}) of {} '
                                 'object'.format(self.size, Structure))
        else:
            self.size = A_full.shape[0]

        self.__A_full = A_full

        # Pass "None" to self.A_mean setter to trigger calculation of
        # mean dose matrix from full dose matrix.
        self.A_mean = None
Beispiel #13
0
	def A_full(self, A_full):
		if A_full is None:
			return

		# verify type of A_full
		if not sparse_or_dense(A_full):
			raise TypeError('input A must by a numpy or scipy csr/csc '
							'sparse matrix')

		if self.size is not None:
			if A_full.shape[0] != self.size:
				raise ValueError('# rows of "A_full" must correspond to '
								 'value  of property size ({}) of {} '
								 'object'.format(self.size, Structure))
		else:
			self.size = A_full.shape[0]

		self.__A_full = A_full

		# Pass "None" to self.A_mean setter to trigger calculation of
		# mean dose matrix from full dose matrix.
		self.A_mean = None
Beispiel #14
0
	def frame0_to_1_inplace(self, in_, out_, clear_output=False):
		"""
		Map elements of array ``in_`` to elements of array ``out_``.

		Procedure::
			# let forward_map be the map: SET_0 --> SET_1.
			# for each INDEX_0, INDEX_1 in forward_map, do
			# 	out_[INDEX_1] += in_[INDEX_0]
			# end for

		If arrays are matrices, mapping operates on rows. If arrays are
		vectors, mapping operates on entries.

		Arguments:
			in_: Input array with :attr:`AbstractMapping.n_frame0` rows
				and ``k`` >= ``1`` columns.
			out_: Output array with :attr:`AbstractMapping.n_frame1`
				rows and ``k`` >= 1 columns. Modified in-place.
			clear_output (:obj:`bool`, optional): If ``True``, set
				output array to ``0`` before adding input values.

		Returns:
			Vector `out_`, after in-place modification.

		Raises:
			TypeError: If input and output arrays are not (jointly)
				vectors or matrices.
			ValueError: If input and output array dimensions are not
				compatible with each other or consistent with the
				dimensions of the mapping.
		"""
		vector_processing = is_vector(in_) and is_vector(out_)
		matrix_processing = sparse_or_dense(in_) and sparse_or_dense(out_)

		if not vector_processing or matrix_processing:
			raise TypeError('arguments "in_" and "out_" be numpy or '
							'scipy vectors or matrices')

		dim_in1 = in_.shape[0]
		dim_out1 = out_.shape[0]
		if vector_processing:
			dim_in2 = 1
			dim_out2 = 1
		else:
			dim_in2 = in_.shape[1]
			dim_out2 = out_.shape[1]

		if bool(
				dim_in_1 != self.n_frame0 or
				dim_out1 != self.n_frame1 or
				dim_in2 != dim_out2):
			raise ValueError('arguments "in_" and "out_" be vectors or '
							 'matrices of dimensions M x N, and K x N, '
							 'respectively, with:\nM = {}\nK={}\n'
							 'Provided:\n input: {}x{}\noutput: {}x{}'
							 ''.format(self.n_frame0, self.n_frame1,
							 dim_in1, dim_in2, dim_out1, dim_out2))
		if clear_output:
			out_ *= 0

		if vector_processing:
			for idx_0, idx_1 in enumerate(self.vec):
				out_[idx_1] += in_[idx_0]

		if matrix_processing:
			for idx_0, idx_1 in enumerate(self.vec):
				out_[idx_1, :] += in_[idx_0, :]

		return out_
Beispiel #15
0
	def frame0_to_1_inplace(self, in_, out_, clear_output=False):
		"""
		Map elements of array ``in_`` to elements of array ``out_``.

		Procedure::
			# let forward_map be the map: SET_0 --> SET_1.
			# for each INDEX_0, INDEX_1 in forward_map, do
			# 	out_[INDEX_1] += in_[INDEX_0]
			# end for

		If arrays are matrices, mapping operates on rows. If arrays are
		vectors, mapping operates on entries.

		Arguments:
			in_: Input array with :attr:`DiscreteMapping.n_frame0` rows
				and ``k`` >= ``1`` columns.
			out_: Output array with :attr:`DiscreteMapping.n_frame1`
				rows and ``k`` >= 1 columns. Modified in-place.
			clear_output (:obj:`bool`, optional): If ``True``, set
				output array to ``0`` before adding input values.

		Returns:
			Vector `out_`, after in-place modification.

		Raises:
			TypeError: If input and output arrays are not (jointly)
				vectors or matrices.
			ValueError: If input and output array dimensions are not
				compatible with each other or consistent with the
				dimensions of the mapping.
		"""
		vector_processing = is_vector(in_) and is_vector(out_)
		matrix_processing = sparse_or_dense(in_) and sparse_or_dense(out_)
		if not (vector_processing or matrix_processing):
			raise TypeError('arguments "in_" and "out_" be numpy or '
							'scipy vectors or matrices')

		dim_in1 = in_.shape[0]
		dim_out1 = out_.shape[0]
		if vector_processing:
			dim_in2 = 1
			dim_out2 = 1
		else:
			dim_in2 = in_.shape[1]
			dim_out2 = out_.shape[1]

		if bool(
				dim_in1 != self.n_frame0 or
				dim_out1 != self.n_frame1 or
				dim_in2 != dim_out2):
			raise ValueError('arguments "in_" and "out_" be vectors or '
							 'matrices of dimensions M x N, and K x N, '
							 'respectively, with:\nM = {}\nK={}\n'
							 'Provided:\n input: {}x{}\noutput: {}x{}'
							 ''.format(self.n_frame0, self.n_frame1,
							 dim_in1, dim_in2, dim_out1, dim_out2))
		if clear_output:
			out_ *= 0

		if vector_processing:
			for idx_0, idx_1 in enumerate(self.vec):
				out_[idx_1] += in_[idx_0]
		else:
			for idx_0, idx_1 in enumerate(self.vec):
				out_[idx_1, :] += in_[idx_0, :]
		# TODO: use efficient slicing when input is sparse. warn when output sparse??

		return out_