## tsne plot (cluster algorithm)  E.Korsching  2024 2026

f.tsne <- function(mat, lv, col="blue", psym=20, pp=20, is.d=F, se.se=392, text=F, title="", lpos="topright", ret=F){
	require(Rtsne)		# R wrapper for the c implementation of the original author
	#  in contrast tsne() is a pure R implementation (less flexible)
	# rows: samples/observations, columns: variables (our structure : t() )
	# mat(rows), lv(vector), col(vector), psym(vector): same order;  samples in rows, sample groups, colors per group, data symbols
	#   "gold3", "grey", "maroon3"   pch c(0,15,1,16,5,6)
	rnames <- dimnames(mat)[[1]]
	dimnames(mat)[[1]] <- lv
	set.seed(se.se)
	a.out <- Rtsne(mat,
			pca=FALSE,
			perplexity=pp,
			theta=0.0,
			check_duplicates=F, # T -> F see: https://stats.stackexchange.com/questions/223602/why-does-the-implementation-of-t-sne-in-r-default-to-the-removal-of-duplicates
			is_distance=is.d,
			normalize=!is.d,
			max_iter=4000,
			num_threads=1)
	if(text){
		plot(a.out$Y, col="gray", pch=".", asp=1, main=title, xlab="c1", ylab="c2")
	}else{
		plot(a.out$Y, col=col, pch=psym, asp=1, main=title, xlab="c1", ylab="c2")		# xlim defunc because of asp
	}
	if(text){ text(a.out$Y, labels=rnames, col=col, cex=0.7, font=1) }
	if(!text){ legend(lpos, legend=lv, col=col, pch=psym, ncol=2) }
	if(ret){ return(a.out) }else{ return() }
}



