<commit_before>'''
Random, unsorted collection of algorithms/utility functions for PyRate.

Author: <NAME>, NCI
'''

# TODO: later refactoring could move these to more relevant modules 


import math
from numpy import sin, cos, unique, histogram, diag, dot
from shared import EpochList, IfgException
from ifgconstants import DAYS_PER_YEAR

from scipy.linalg import qr, solve, lstsq

# constants
MM_PER_METRE = 1000


def is_square(arr):
	shape = arr.shape
	if len(shape) == 2 and (shape[0] == shape[1]):
		return True
	return False


def least_squares_covariance(A,b,v):
	"""Least squares solution in the presence of known covariance.

	This function is known as lscov() in MATLAB.
	A: design matrix
	b: observations (vector of phase values)
	v: covariances (weights) in vector form
	"""
	#	X = LSCOV(A,b,V) returns the vector X that minimizes
	#	(A*X-b)'*inv(V)*(A*X-b) for the case in which length(b) > length(X).
	#	This is the over-determined least squares problem with covariance V.
	#	The solution is found without needing to invert V which is a square
	#	symmetric matrix with dimensions equal to length(b).
	#
	#	The classical linear algebra solution to this problem is:
	#
	#	    x = inv(A'*inv(V)*A)*A'*inv(V)*b
	#
	#	Reference:
	#	    <NAME>, "Introduction to Applied Mathematics",
	#	    Wellesley-Cambridge, p. 398, 1986.
	#	<NAME> 3-31-89

	# convert vectors to 2D singleton array
	if len(A.shape) != 2:
		raise ValueError('')

	m, n = A.shape
	if m <= n:
		raise ValueError('Problem must be over-determined')

	V = diag(1.0 / v.squeeze())
	q, r = qr(A) # Orthogonal-triangular Decomposition
	efg = dot(q.T, dot(V, q)) # TODO: round it??
	g = efg[n:, n:] # modified to 0 indexing
	cd = dot(q.T, b) # q.T * b
	f = efg[:n, n:] # TODO: check +1/indexing
	c = cd[:n] # modified to 0 indexing
	d = cd[n:] # modified to 0 indexing
	r = r[:n,:n] # modified to 0 indexing

	is_sq = is_square(g)
	func = solve if is_sq else lstsq
	tmp = func(g, d)
	is_sq = is_square(r)
	func = solve if is_sq else lstsq
	return func(r, (c-f * tmp))


def wavelength_radians_to_mm(data, wavelength):
	'''
	Translates phase from radians to millimetres
	data: ifg phase data
	wavelength: normally included with SAR instrument pass data
	'''
	return data * MM_PER_METRE * (wavelength / (4 * math.pi))


def los_conversion(phase_data, unit_vec):
	'''
	Converts phase from line-of-sight (LOS) to horizontal/vertical components.
	phase_data - phase band data array (eg. ifg.phase_data)
	unit_vec - 3 component sequence, eg. [EW, NS, vertical]
	'''
	# NB: currently not tested as implementation is too simple
	return phase_data * unit_vec


def unit_vector(incidence, azimuth):
	'''Returns unit vector tuple (east_west, north_south, vertical).'''
	vertical = cos(incidence)
	north_south = sin(incidence) * cos(azimuth)
	east_west = sin(incidence) * sin(azimuth)
	return east_west, north_south, vertical


def ifg_date_lookup(ifgs, date_pair):
	'''<commit_msg>Added comment to explain magic number.<commit_after>'''
Random, unsorted collection of algorithms/utility functions for PyRate.

Author: <NAME>, NCI
'''

# TODO: later refactoring could move these to more relevant modules 


import math
from numpy import sin, cos, unique, histogram, diag, dot
from shared import EpochList, IfgException
from ifgconstants import DAYS_PER_YEAR

from scipy.linalg import qr, solve, lstsq

# constants
MM_PER_METRE = 1000


def is_square(arr):
	shape = arr.shape
	if len(shape) == 2 and (shape[0] == shape[1]):
		return True
	return False


def least_squares_covariance(A,b,v):
	"""Least squares solution in the presence of known covariance.

	This function is known as lscov() in MATLAB.
	A: design matrix
	b: observations (vector of phase values)
	v: covariances (weights) in vector form
	"""
	#	X = LSCOV(A,b,V) returns the vector X that minimizes
	#	(A*X-b)'*inv(V)*(A*X-b) for the case in which length(b) > length(X).
	#	This is the over-determined least squares problem with covariance V.
	#	The solution is found without needing to invert V which is a square
	#	symmetric matrix with dimensions equal to length(b).
	#
	#	The classical linear algebra solution to this problem is:
	#
	#	    x = inv(A'*inv(V)*A)*A'*inv(V)*b
	#
	#	Reference:
	#	    <NAME>, "Introduction to Applied Mathematics",
	#	    Wellesley-Cambridge, p. 398, 1986.
	#	<NAME> 3-31-89

	# convert vectors to 2D singleton array
	if len(A.shape) != 2:
		raise ValueError('')

	m, n = A.shape
	if m <= n:
		raise ValueError('Problem must be over-determined')

	V = diag(1.0 / v.squeeze())
	q, r = qr(A) # Orthogonal-triangular Decomposition
	efg = dot(q.T, dot(V, q)) # TODO: round it??
	g = efg[n:, n:] # modified to 0 indexing
	cd = dot(q.T, b) # q.T * b
	f = efg[:n, n:] # TODO: check +1/indexing
	c = cd[:n] # modified to 0 indexing
	d = cd[n:] # modified to 0 indexing
	r = r[:n,:n] # modified to 0 indexing

	is_sq = is_square(g)
	func = solve if is_sq else lstsq
	tmp = func(g, d)
	is_sq = is_square(r)
	func = solve if is_sq else lstsq
	return func(r, (c-f * tmp))


def wavelength_radians_to_mm(data, wavelength):
	'''
	Translates phase from radians to millimetres
	data: ifg phase data
	wavelength: normally included with SAR instrument pass data
	'''
	# '4' is 2*2, the 1st 2 is that the raw signal is 'there and back', to get
	# the vector length between satellite and ground, half the signal is needed
	# second 2*pi is because one wavelength is equal to 2 radians
	return data * MM_PER_METRE * (wavelength / (4 * math.pi))


def los_conversion(phase_data, unit_vec):
	'''
	Converts phase from line-of-sight (LOS) to horizontal/vertical components.
	phase_data - phase band data array (eg. ifg.phase_data)
	unit_vec - 3 component sequence, eg. [EW, NS, vertical]
	'''
	# NB: currently not tested as implementation is too simple
	return phase_data * unit_vec


def unit_vector(incidence, azimuth):
	'''Returns unit vector tuple (east_west, north_south, vertical).'''
	vertical = cos(incidence)
	north_south = sin(incidence) * cos(azimuth)
	east_west = sin(incidence) * sin(azimuth)
	return east_west, north_south, vertical


def ifg_date_lookup(ifgs, date_pair):
	'''
{'fraction_non_alphanumeric': 0.11419702662963568, 'fraction_numerical': 0.010945923868648913, 'mean_word_length': 4.140218303946264, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3784338', 'n_tokens_mistral': 2313, 'n_tokens_neox': 2126, 'n_words': 753}