"""
Package mash is for sketching sequence data to make it easier to compare to other sequence.

The package is named mash after the mash sketching algorithm, which is based on the MinHash algorithm.

Mash: fast genome and metagenome distance estimation using MinHash.
Ondov, B.D., Treangen, T.J., Melsted, P. et al.
Genome Biol 17, 132 (2016).
https://doi.org/10.1186/s13059-016-0997-x

Mash Screen: high-throughput sequence containment estimation for genome discovery.
Ondov, B., Starrett, G., Sappington, A. et al.
Genome Biol 20, 232 (2019).
https://doi.org/10.1186/s13059-019-1841-x

tl;dr for the papers above:

Comparing biological sequences is really hard because similar sequences can have frameshifts that make it impossible
to measure similarity using more common metric distances like hamming distance or levenshtein distance.

Bioinformatics and nlp researchers have come up with tons of string comparison algorithms that are better suited for
comparing biological sequences. For example poly already implements a few of them like the Needleman-Wunsch and Smith-Waterman
algorithms in our "align" package.

Mash is a different approach to comparing biological sequences. It uses a technique called sketching to reduce the
complexity of the sequence to a vector of hashes. The hashes are generated by sliding a window of size k along the
sequence and hashing each kmer. The hash is then stored in a vector of size s. The vector is sorted and the smallest
hash is kept. The process is repeated until the vector is full. The vector of hashes is the sketch.

The sketch is then compared to other sketches by counting the number of hashes that are the same between the two sketches.
The number of hashes that are the same is divided by the size of the sketch to get a distance between 0 and 1.

Hash vectors can only be compared to other hash vectors that use the same sliding window size.
Sketch size limits how many hashes can be stored in the vector and the return vector
will always be of length of the sketch size and filled the smallest hashes that were generated
and sorted from smallest to largest.

The larger the sketch size the more accurate the distance calculation will be but the longer it will take to calculate.

TTFN,
Tim

"""
# python wrapper for package github.com/bebop/poly/search/mash 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 mash
# and then refer to everything using mash. prefix
# packages imported by this package listed below:




# ---- 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 mash.Mash
class Mash(go.GoClass):
	"""Mash is a collection of hashes of kmers from a given sequence.\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.mash_Mash_CTor()
			_poly.IncRef(self.handle)
			if  0 < len(args):
				self.KmerSize = args[0]
			if "KmerSize" in kwargs:
				self.KmerSize = kwargs["KmerSize"]
			if  1 < len(args):
				self.SketchSize = args[1]
			if "SketchSize" in kwargs:
				self.SketchSize = kwargs["SketchSize"]
			if  2 < len(args):
				self.Sketches = args[2]
			if "Sketches" in kwargs:
				self.Sketches = kwargs["Sketches"]
	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 = 'mash.Mash{'
		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 = 'mash.Mash ( '
		for v in pr:
			if not callable(v[1]):
				sv += v[0] + '=' + str(v[1]) + ', '
		return sv + ')'
	@property
	def KmerSize(self):
		return _poly.mash_Mash_KmerSize_Get(self.handle)
	@KmerSize.setter
	def KmerSize(self, value):
		if isinstance(value, go.GoClass):
			_poly.mash_Mash_KmerSize_Set(self.handle, value.handle)
		else:
			_poly.mash_Mash_KmerSize_Set(self.handle, value)
	@property
	def SketchSize(self):
		return _poly.mash_Mash_SketchSize_Get(self.handle)
	@SketchSize.setter
	def SketchSize(self, value):
		if isinstance(value, go.GoClass):
			_poly.mash_Mash_SketchSize_Set(self.handle, value.handle)
		else:
			_poly.mash_Mash_SketchSize_Set(self.handle, value)
	@property
	def Sketches(self):
		return go.Slice_uint32(handle=_poly.mash_Mash_Sketches_Get(self.handle))
	@Sketches.setter
	def Sketches(self, value):
		if isinstance(value, go.GoClass):
			_poly.mash_Mash_Sketches_Set(self.handle, value.handle)
		else:
			raise TypeError("supplied argument type {t} is not a go.GoClass".format(t=type(value)))
	def Sketch(self, sequence, goRun=False):
		"""Sketch(str sequence) 
		
		Sketch generates a mash sketch of the sequence.
		"""
		_poly.mash_Mash_Sketch(self.handle, sequence, goRun)
	def Similarity(self, other):
		"""Similarity(object other) float
		
		Similarity returns the Jaccard similarity between two sketches (number of matching hashes / sketch size)
		"""
		return _poly.mash_Mash_Similarity(self.handle, other.handle)
	def Distance(self, other):
		"""Distance(object other) float
		
		Distance returns the Jaccard distance between two sketches (1 - similarity)
		"""
		return _poly.mash_Mash_Distance(self.handle, other.handle)


# ---- Slices ---


# ---- Maps ---


# ---- Constructors ---
def New(kmerSize, sketchSize):
	"""New(int kmerSize, int sketchSize) object
	
	New initializes a new mash sketch.
	"""
	return Mash(handle=_poly.mash_New(kmerSize, sketchSize))


# ---- Functions ---


