"""
Package align is a package for aligning (comparing) DNA, RNA, and protein sequences.

Biology is fickle and full of quirks that make it hard to do even the most basic of tasks
which we would normally take for granted when working with other kinds of data.

Comparing two biological sequences to see if they're roughly equivalent is one of those tasks.

Essentially two almost identical sequences with almost identical functionality can contain
small insertions or deletions that shift the entire string such that a meaningful comparison via
hamming distance or levenshtein distance becomes impossible.

For example:

Timothy Stiles
||||||| ||||||
Timothy Stiles

is an easy match with hamming or levenshtein distance.

However, say we introduce a new character to the beginning of the sequence.

Timothy Stiles
xxxxxxxxxxxxxxxx
A Timothy Stiles

Now our edit distance via levenshtein is maximized at 16 and we wouldn't
be able to tell that semantically these strings are almost identical.

This frame shifting seen above is incredibly common within biological sequences and alignment
algorithms are designed in part to deal with these shifts so that when we compare two sequences
like the two below we can get a more useful edit distance.

GAAAAAAT
GAA----T

As of writing this package includes the two most basic algorithms for alignment,
Needleman-Wunsch and Smith-Waterman. Needleman-Wunsch is used when you are
looking for global alignment between two full-length sequences, while
Smith-Waterman is better at smaller sequences with local similarities and
handling sequences with long non-homologous regions. BLAST, on the other hand,
takes advantage of more heuristic techniques to speed up alignment, and is better
at finding similar sequences in large database, sacrificing precision for faster
results.

Both are "dynamic programming algorithms" which is a fancy 1980's term for they use
matrices. If you're familiar with kernel operations, linear filters, or whatever term
ML researchers are using nowadays for, "slide a window over a matrix and determine that
entry's values using its neighbor's values", then this should be pretty easy to grok.

If not these algorithms essentially compare every character in one sequence with another
sequence and create an edit distance along with human readable string to show gaps like the
previous example.

I'm not really an expert on alignment so if you want to learn more about this class of algorithms
wikipedia has a decent overview.

https://en.wikipedia.org/wiki/Sequence_alignment

Even if I may not know the answer to your alignment questions please ask and I'll do my best
to help!

TTFN,
Tim

"""
# python wrapper for package github.com/bebop/poly/search/align within overall package poly
# This is what you import to use the package.
# File is generated by gopy. Do not edit.
# gopy pkg -vm=python3 github.com/bebop/poly

# the following is required to enable dlopen to open the _go.so file
import os,sys,inspect,collections
try:
	import collections.abc as _collections_abc
except ImportError:
	_collections_abc = collections

cwd = os.getcwd()
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
os.chdir(currentdir)
from . import _poly
from . import go

os.chdir(cwd)

# to use this code in your end-user python file, import it as follows:
# from poly import align
# and then refer to everything using align. prefix
# packages imported by this package listed below:

from . import matrix



# ---- Types ---


#---- Enums from Go (collections of consts with same type) ---


#---- Constants from Go: Python can only ask that you please don't change these! ---


# ---- Global Variables: can only use functions to access ---


# ---- Interfaces ---


# ---- Structs ---

# Python type for struct align.Scoring
class Scoring(go.GoClass):
	"""Scoring is a struct that holds the scoring matrix for match, mismatch, and gap penalties.\n"""
	def __init__(self, *args, **kwargs):
		"""
		handle=A Go-side object is always initialized with an explicit handle=arg
		otherwise parameters can be unnamed in order of field names or named fields
		in which case a new Go object is constructed first
		"""
		if len(kwargs) == 1 and 'handle' in kwargs:
			self.handle = kwargs['handle']
			_poly.IncRef(self.handle)
		elif len(args) == 1 and isinstance(args[0], go.GoClass):
			self.handle = args[0].handle
			_poly.IncRef(self.handle)
		else:
			self.handle = _poly.align_Scoring_CTor()
			_poly.IncRef(self.handle)
			if  0 < len(args):
				self.SubstitutionMatrix = args[0]
			if "SubstitutionMatrix" in kwargs:
				self.SubstitutionMatrix = kwargs["SubstitutionMatrix"]
			if  1 < len(args):
				self.GapPenalty = args[1]
			if "GapPenalty" in kwargs:
				self.GapPenalty = kwargs["GapPenalty"]
	def __del__(self):
		_poly.DecRef(self.handle)
	def __str__(self):
		pr = [(p, getattr(self, p)) for p in dir(self) if not p.startswith('__')]
		sv = 'align.Scoring{'
		first = True
		for v in pr:
			if callable(v[1]):
				continue
			if first:
				first = False
			else:
				sv += ', '
			sv += v[0] + '=' + str(v[1])
		return sv + '}'
	def __repr__(self):
		pr = [(p, getattr(self, p)) for p in dir(self) if not p.startswith('__')]
		sv = 'align.Scoring ( '
		for v in pr:
			if not callable(v[1]):
				sv += v[0] + '=' + str(v[1]) + ', '
		return sv + ')'
	@property
	def SubstitutionMatrix(self):
		return matrix.SubstitutionMatrix(handle=_poly.align_Scoring_SubstitutionMatrix_Get(self.handle))
	@SubstitutionMatrix.setter
	def SubstitutionMatrix(self, value):
		if isinstance(value, go.GoClass):
			_poly.align_Scoring_SubstitutionMatrix_Set(self.handle, value.handle)
		else:
			raise TypeError("supplied argument type {t} is not a go.GoClass".format(t=type(value)))
	@property
	def GapPenalty(self):
		return _poly.align_Scoring_GapPenalty_Get(self.handle)
	@GapPenalty.setter
	def GapPenalty(self, value):
		if isinstance(value, go.GoClass):
			_poly.align_Scoring_GapPenalty_Set(self.handle, value.handle)
		else:
			_poly.align_Scoring_GapPenalty_Set(self.handle, value)
	def Score(self, a, b):
		"""Score(int a, int b) int, str"""
		return _poly.align_Scoring_Score(self.handle, a, b)


# ---- Slices ---


# ---- Maps ---


# ---- Constructors ---
def NewScoring(substitutionMatrix, gapPenalty):
	"""NewScoring(object substitutionMatrix, int gapPenalty) object, str
	
	NewScoring returns a new Scoring struct with default values for DNA.
	"""
	return Scoring(handle=_poly.align_NewScoring(substitutionMatrix.handle, gapPenalty))


# ---- Functions ---


