#!/usr/bin/env python
# -*- coding: utf-8 -*-

import codecs
import pyplwn

def count_synset_width(db, str = ""):
	"""
	Liczy srednia liczbe synsetow 
	"""
	stats = pyplwn.database.WNStatistics(db)
	results = stats.get_avg_synset_width()
	print "Avg polysemy %s:" % str
	for pos in results:
		if pos == 'all':
			print "\tAll: %s" % (results[pos] )
		else:
			print "\t%s: %s" % (pyplwn.database.DBEnums.get_pos_string(pos), results[pos] )


def compare_synset_width_by_year( host = 'localhost', dbs = ['plwn2006', 'plwn2007', 'plwn2008_czerwiec', 'plwn'] ):
	for dbname in dbs:
		db = pyplwn.database.Database('plwn', 'plwn', host, dbname, 3306)
		count_synset_width(db, dbname)


def print_wn_numbers_by_pos(db):
	stats = pyplwn.database.WNStatistics(db)

	labels = ['No of lemmas', 'No of LUs', 'No of synsets', 'Monosemous lemmas', 'Polysemous lemmas']
	noun = stats.get_wn_numbers( [pyplwn.database.DBEnums.get_pos('subst')] )
	verb = stats.get_wn_numbers( [pyplwn.database.DBEnums.get_pos('verb') ] )
	adj  = stats.get_wn_numbers( [pyplwn.database.DBEnums.get_pos('adj')  ] )
	all  = stats.get_wn_numbers( [ pyplwn.database.DBEnums.get_pos('subst'),pyplwn.database.DBEnums.get_pos('verb'),\
			pyplwn.database.DBEnums.get_pos('adj')]   )

	print r"""\begin{table}[htbp]
\center
\begin{tabular}{|l|r|r|r|r|}
\hline
                & Nouns & Verbs & Adjectives & \emph{All}\\
\hline"""
	for p in xrange( len(noun) ):
		print "%s & %s & %s & %s & %s  \\\\" % (labels[p].ljust(15), str(noun[p]).rjust(7), \
				str(verb[p]).rjust(7), str(adj[p]).rjust(7), str(all[p]).rjust(7) )
		print r"\hline"
	print r"""\end{tabular}
\caption{Different aspects of the plWordNet size.}
\label{tab:plWNSize}
\end{table}
"""

def print_avg_polysemy(db):
	stats = pyplwn.database.WNStatistics(db)
	
	poses = [ ("Nouns", [pyplwn.database.DBEnums.get_pos('subst')] ), 
			  ("Verbs", [pyplwn.database.DBEnums.get_pos('verb')] ),
			  ("Adjectives", [pyplwn.database.DBEnums.get_pos('adj')] )
			]
	print r"""\begin{table}[htbp]
\center
\begin{tabular}{|l|r|r|r|}
\hline
           & Including Monosemous Lemmas & Excluding Monosemous Lemmas  \\
\hline"""
	for (l, p) in poses:
		print "%s & %s & %s \\\\" % ( l.ljust(10), stats.get_avg_polysemy(p, True).rjust(5), stats.get_avg_polysemy(p, False).rjust(5) )
		print r"\hline"
	print r"""\end{tabular}
\caption{Average polysemy.}
\label{tab:plWNPolysemy}
\end{table}
"""

def print_synset_size_histogram(db):
	stats = pyplwn.database.WNStatistics(db)
	
	poses = [ ("Nouns", [pyplwn.database.DBEnums.get_pos('subst')] ), 
			  ("Verbs", [pyplwn.database.DBEnums.get_pos('verb')] ),
			  ("Adjectives", [pyplwn.database.DBEnums.get_pos('adj')] )
			]
	print r"""\begin{table}[htbp]
\center
\begin{tabular}{|l|r|r|r|r|r|r|r|r|r|r|}
\hline
      &\multicolumn{10}{c|}{Percentage of synsets including the $n$ lexical units [\%]} \\
      \cline{2-11}
           & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & $\geq 10$\\
\hline"""
	for l,p in poses:
		print l.ljust(10), "&",
		h,c = stats.get_synset_size_histogram(p)
		for x in sorted(h):
			print ("%2.2f " % (100 * float(h[x]) / c )).rjust(6),
			if x < 10:
				print "&",
		print "\\\\\n\\hline"

	print r"""\end{tabular}
\caption{Sizes of synsets.}
\label{tab:SynsetHist}
\end{table}
"""

def print_longest_synsets(db):
	poses = [ ("Nouns", [pyplwn.database.DBEnums.get_pos('subst')] ), 
			  ("Verbs", [pyplwn.database.DBEnums.get_pos('verb')] ),
			  ("Adjectives", [pyplwn.database.DBEnums.get_pos('adj')] )
			]
	stats = pyplwn.database.WNStatistics(db)
	for l,p in poses:
		print l, ":", stats.get_longest_synset(p),'\n'

def print_units_polysemy_histogram(db):
	poses = [ ("Nouns", [pyplwn.database.DBEnums.get_pos('subst')] ), 
			  ("Verbs", [pyplwn.database.DBEnums.get_pos('verb')] ),
			  ("Adjectives", [pyplwn.database.DBEnums.get_pos('adj')] )
			]
	stats = pyplwn.database.WNStatistics(db)
	print r"""\begin{table}[htbp]
\center
\begin{tabular}{|l|r|r|r|r|r|r|r|r|r|r|}
\hline
      &\multicolumn{10}{c|}{Percentage of lemmas belonging to the $n$ synsets [\%]} \\
      \cline{2-11}
           & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & $\geq 10$\\
\hline"""
	for l,p in poses:
		print l.ljust(10), "&",
		h,c = stats.get_units_polysemy_histogram(p)
		for x in sorted(h):
			print ("%2.2f " % ( 100*float(h[x]) / c )).rjust(6),
			if x < 10:
				print "&",
		print "\\\\\n\\hline"
	print r"""\end{tabular}
\caption{No of synsets which a lemmas belongs to.}
\label{tab:LemmaHist}
\end{table}
"""

def print_most_polysemous_unit_senses(db):
	poses = [ ("Nouns", [pyplwn.database.DBEnums.get_pos('subst')] ), 
			  ("Verbs", [pyplwn.database.DBEnums.get_pos('verb')] ),
			  ("Adjectives", [pyplwn.database.DBEnums.get_pos('adj')] )
			]
	stats = pyplwn.database.WNStatistics(db)
	for l,p in poses:
		print l, ":"
		senses = stats.get_most_polysemous_unit_senses(p)
		for s in senses:
			print "\t", s

def print_longest_path(db):
	stats = pyplwn.database.WNStatistics(db)
	paths = stats.get_longest_hyperonymy_path()
	print 
	print "Longest hypernymy path:",len( paths[0] )
	for path in paths:
		for syn_id in path:
			print r'\noindent\synset{',
			synset = db.Synsets.get_synset_by_id(syn_id)
			for u in synset.units:
				u = u.lemma.replace(u'sjl - ', u'')
				print '\exmplg{%s}{??}' % u,
			print '}\\\\'
		print

def print_relations_count(db):
	stats = pyplwn.database.WNStatistics(db)

	print r"""
\begin{table}[htbp]
\center
\begin{tabular}{|l|r|r|r|r|}
\hline
Relation       &\multicolumn{4}{c|}{No of instances} \\
               \cline{2-5}
               & Nouns   &  Verbs  & Adjectives & \emph{All}\\"""
	synset_stats = stats.get_synset_relation_count()
	noun = pyplwn.database.DBEnums.get_pos('subst')
	verb = pyplwn.database.DBEnums.get_pos('verb')
	adj  = pyplwn.database.DBEnums.get_pos('adj')
	
	s = synset_stats[11]
	print "\\hline"
	print "Hypernymy      & %7s & %7s & %6s & %7s \\\\" % ( s[noun], s[verb], s[adj], s[noun] + s[verb] + s[adj])
	print "\\hline"
	s = synset_stats[15]
	print "Holonymy       & %7s & %7s & %6s & %7s \\\\" % ( s[noun], s[verb], s[adj], s[noun] + s[verb] + s[adj])
	print "\\hline"
	s = synset_stats[14]
	print "Meronymy       & %7s & %7s & %6s & %7s \\\\" % ( s[noun], s[verb], s[adj], s[noun] + s[verb] + s[adj])
	print "\\hline"
	print "\\hline"
   
	lex_stats = stats.get_lexical_relation_count()
	s = lex_stats[16]
	print "Troponymy      & %7s & %7s & %6s & %7s \\\\" % ( s[noun], s[verb], s[adj], s[noun] + s[verb] + s[adj])
	print "\\hline"
	s = lex_stats[12]
	print "Antonymy       & %7s & %7s & %6s & %7s \\\\" % ( s[noun], s[verb], s[adj], s[noun] + s[verb] + s[adj])
	print "\\hline"
	s = lex_stats[13]
	print "Conversion     & %7s & %7s & %6s & %7s \\\\" % ( s[noun], s[verb], s[adj], s[noun] + s[verb] + s[adj])
	print "\\hline"
	s = lex_stats[17]
	print "Relatedness    & %7s & %7s & %6s & %7s \\\\" % ( s[noun], s[verb], s[adj], s[noun] + s[verb] + s[adj])
	print "\\hline"
	s = lex_stats[18]
	print "Pertainymy     & %7s & %7s & %6s & %7s \\\\" % ( s[noun], s[verb], s[adj], s[noun] + s[verb] + s[adj])
	print "\\hline"
	s = lex_stats[19]
	print "Fuzzynimy      & %7s & %7s & %6s & %7s \\\\" % ( s[noun], s[verb], s[adj], s[noun] + s[verb] + s[adj])
	print "\\hline"
	
	print """\end{tabular}
\caption{Different aspects of the plWordNet size.}
\label{tab:relInst}
\end{table}
"""

def print_multihypernymy(db):
	stats = pyplwn.database.WNStatistics(db)

	adj,subst,verb = stats.get_hypernymy_level()
	print "Adj count: ", adj[0]
	print "Adj level: ", adj[1]
	print "Adj: ", adj[2]
	print "children: ", adj[3]

	print "\nVerb count: ", verb[0]
	print "Verb level: ", verb[1]
	print "Verb: ", verb[2]
	print "children: ", verb[3]
	
	print "\nSubst count: ", subst[0]
	print "Subst level: ", subst[1]
	print "Subst: ", subst[2]
	print "children: ", subst[3]


def get_count(db, query):
	db.cursor.execute(query)
	return long( db.cursor.fetchone()[0] )
	
def print_progress(db1, db2):
	query = "SELECT COUNT(*) FROM lexicalunit"
	lex1 = get_count(db1, query)
	lex2 = get_count(db2, query)

	query = "SELECT COUNT( DISTINCT(lemma) ) FROM lexicalunit"
	lemmas1 = get_count(db1, query)
	lemmas2 = get_count(db2, query)

	query = "SELECT COUNT( DISTINCT (syn_id) ) FROM unitandsynset"
	synsets1 = get_count(db1, query)
	synsets2 = get_count(db2, query)

	query = "SELECT COUNT( * ) FROM synsetrelation"
	synsetsrel1 = get_count(db1, query)
	synsetsrel2 = get_count(db2, query)

	query = "SELECT COUNT( * ) FROM lexicalrelation"
	lexrel1 = get_count(db1, query)
	lexrel2 = get_count(db2, query)

	print "Lexical units: %s -> %s (%s)" % (lex1,lex2, lex2-lex1)
	print "Lemmas: %s -> %s (%s)" % (lemmas1, lemmas2, lemmas2-lemmas1)
	print "Synsets: %s -> %s (%s)" % (synsets1, synsets2, synsets2-synsets1)
	print "Synset relations: %s -> %s (%s)" % (synsetsrel1, synsetsrel2, synsetsrel2-synsetsrel1)
	print "Lexical relations: %s -> %s (%s)" % (lexrel1, lexrel2, lexrel2-lexrel1)

def print_structure_changes(databases = ['plwn12_2006','plwn9_2007','plwn6_2008','plwn11_2008', 'plwn1'], user='plwn', passwd='plwn', host='localhost', port = 3306):
	synsets = []
	singeltos = []
	avg = []
	units = []
	for db_name in databases:
		db = pyplwn.database.Database(user, passwd , host, db_name, port, encoding = "utf8")
		db.poses = pyplwn.database.DBEnums.get_all_poses()
		wns = pyplwn.database.WNStatistics(db)
		# no of synsets
		no_of_synsets = db.Synsets.get_synset_count()
		synsets.append(no_of_synsets)
		# no of singelton synsets
		q = 'SELECT COUNT(*) FROM (SELECT count(syn_id) AS ccc, lex_id, syn_id FROM unitandsynset u group by syn_id ) as ddd WHERE ddd.ccc = 1'
		db.cursor.execute(q)
		no_of_singeltons = db.cursor.fetchone()[0]
		singeltos.append(no_of_singeltons)
		# avg. lus in synset 
		
		q = 'SELECT COUNT( DISTINCT(lex_id ) ) FROM unitandsynset;'
		no_of_units = get_count(db,q)
		units.append(no_of_units)

		# print
		avg.append( float(no_of_units) / float(no_of_synsets) )
	
	print "plWN &", " & ".join(databases)
	print "Lexical units &", " & ".join([str(x) for x in units]), '    \\\\'
	print '\hline'
	print "Synsets &", " & ".join([str(x) for x in synsets]), '    \\\\'
	print '\hline'
	print "Singelton synsets &", " & ".join([str(x) for x in singeltos]), '    \\\\'
	print '\hline'
	print "LUs in synset (average) &", " & ".join(["%.2f" % x  for x in avg]), '    \\\\'
	print '\hline'


class MyError(Exception):
	def __init__(self, msg):
		self.msg = msg


def get_lu_density(db):
	import matplotlib.pyplot as plt
	poses = pyplwn.database.DBEnums.get_all_poses()
	try:
		for pos in poses:
			posstr = pyplwn.database.DBEnums.get_pos_string(pos)
			print "Generating data for", posstr
			db.set_pos_filter([pos])
			units = db.LexicalUnits.get_all_units()
			alllu = []
			for lu in units:
				sum_rels = 0
				query = "SELECT COUNT(*) FROM lexicalrelation WHERE parent_id = %d;"% lu.id
				db.cursor.execute( query )
				count = int( db.cursor.fetchone()[0])
				sum_rels += count
				
				synsets = db.Synsets.get_synsets_id_for_unit(lu)
				if len(synsets) > 1:
					s = "More then one synset for: %d %s " % (lu.id, lu.lemma)
					#print s
					continue
					#raise MyError(s)
				if len(synsets) == 1:
					synset_id = list(synsets)[0]
					query = "SELECT COUNT(*) FROM synsetrelation WHERE parent_id = %d;" % synset_id
					db.cursor.execute( query )
					count = int( db.cursor.fetchone()[0])
					sum_rels += count
					
					synsets_full = db.Synsets.get_synset_by_id(synset_id)
					sum_rels += len(synsets_full.units)
				
				if sum_rels > 100:
					print sum_rels, lu.lemma
					#continue
				if sum_rels == 0:
					continue
				
				alllu.append(sum_rels)
			
			
				
			
			print "Pos: %s, sum: %d,  count: %d" % (posstr, sum(alllu), len(alllu))
			if len(alllu) > 0:
				print "Generating histograms for", pos
				
				list_bins = [5, 10, 20, 50]
				for bins in list_bins:
					plt.hist(alllu, bins=bins)
					plt.title("Deinsity of relation histogram for %s" % posstr)
					plt.savefig(posstr + str(bins) + 'hist.png')
					plt.clf()
					
					plt.hist([x for x in alllu if x > 0], bins=bins)
					plt.title("Deinsity of relation histogram for %s without zeros" % posstr)
					plt.savefig(posstr + str(bins) + 'hist_nozero.png')
					plt.clf()
				
				print "Avg for %s is %.3f" % ( posstr, float(sum(alllu)) / float(len(alllu)))
	except MyError, inst:
		print inst.msg
				

def main():
	# zapytanie do wyboru singeltonowych synsetów:
	# SELECT * FROM (SELECT count(syn_id) AS ccc, lex_id, syn_id FROM unitandsynset u group by syn_id ) as ddd WHERE ddd.ccc = 1
	import sys
	#print_structure_changes()
	#db = pyplwn.database.Database(user = "wordnet", passwd = "w0rdn3tDBP@sswd", host = "plwordnet.pwr.wroc.pl", db = "wordnet_temp", port = 3308, encoding = "utf8")
	db = pyplwn.database.Database(user = "plwn", passwd = "plwn", host = "localhost", db = "plwn1",
								 port = 3306, encoding = "utf8")
	#db1 = pyplwn.database.Database('plwn', 'plwn', 'localhost', 'plwn2008_czerwiec', 3306)
	#print '-----------------------------\nWielkość synsetu (pyplwn to baza 11.2008):'
	#compare_synset_width_by_year('localhost')
	#count_synset_width(db, 'robocza - stan biezacy')
	#print '-----------------------------\nSłowosieć w liczbach:\n'
	#print_wn_numbers_by_pos( db )
	#print '-----------------------------\nŚrednia polisemia:\n'
	#print_avg_polysemy(db)
	#print '-----------------------------\nHistogram wielkości synsetów:\n'
	#print_synset_size_histogram(db)
	#print '-----------------------------\n"Najdluzsze" synsety:\n'
	#print_longest_synsets(db)
	#print '-----------------------------\nHistogram polisemii:\n'
	#print_units_polysemy_histogram(db)
	#print '-----------------------------\nNajbardziej polisemiczne:\n'
	#print_most_polysemous_unit_senses(db)
	#print '-----------------------------\nNajdluzsza sciezka:\n'
	#print_longest_path(db)
	#print '-----------------------------\nLiczenie relacji:\n'
	#print_relations_count(db)
	#print '-----------------------------\nWielo-hiperonimia:\n'
	#print_multihypernymy(db)
	#print'------------------------------\nZmiana pomiedzy 06.2008 a teraz:\n'
	#print_progress(db1, db)
	
	get_lu_density(db)
	
if __name__ == '__main__':
	main()
	
