<?php
/*
* csv.php
* http://tasuke.dna.affrc.go.jp/
*
* Author: Ryutaro Itoh
*
* Copyright (c) 2013 National Institute of Agrobiological Sciences   
*
*/

require '../conf/config.php';
require './common.php';
require './commonDB.php';

$time_start = microtime(true);

////////////////////////////////// Connecting with DB
if( !$conn = new mysqli($host, $user, $pswd, $db)) {
    error_log("Connection failed.\n");
    exit;
}

////////////////////////////////// Parameters
(isset($_POST['prm_csv_chr']) && !empty($_POST['prm_csv_chr'])) ? $prm_chr=$_POST['prm_csv_chr']:returnError("Error1");
(isset($_POST['prm_csv_qual']) && !empty($_POST['prm_csv_qual'])) ? $prm_qual=$_POST['prm_csv_qual']:returnError("Error5");
(isset($_POST['prm_csv_dp']) && !empty($_POST['prm_csv_dp'])) ? $prm_dp=$_POST['prm_csv_dp']:returnError("Error6");
(isset($_POST['prm_csv_list']) && !empty($_POST['prm_csv_list'])) ? $prm_list=$_POST['prm_csv_list'] : returnError("Error7");
(isset($_POST['choose_flag']) && !empty($_POST['choose_flag'])) ? $choose_flag=$_POST['choose_flag'] : returnError("Error8");
if( $choose_flag == "1" ){ //Position
        (isset($_POST['prm_csv_s']) && !empty($_POST['prm_csv_s'])) ? $prm_s=$_POST['prm_csv_s']:returnError("Error3");
        (isset($_POST['prm_csv_e']) && !empty($_POST['prm_csv_e'])) ? $prm_e=$_POST['prm_csv_e']:returnError("Error4");
} else if ($choose_flag == "2") { //ID
    (isset($_POST['prm_csv_keyword']) && !empty($_POST['prm_csv_keyword'])) ? $prm_csv_keyword=$_POST['prm_csv_keyword']:returnError("Error9");
   list($prm_s,$prm_e)=_GETPOSBYIDS($prm_csv_keyword,$conn);
} else {
    if($prm_e-$prm_s>199999){  // Maximum size is 200K
        $prm_e=$prm_s+199999;
    }
}
$enabledEffImpacts = array("0" => True, "1" => True, "2" => True, "3" => True, "-1" => True);
if(isset($_POST['prm_csv_effgrps']) && !empty($_POST['prm_csv_effgrps'])) {
	try {
		$impacts = json_decode($_POST['prm_csv_effgrps']);
		$filterEffImpact = _setSnpEffImpactFilterMap($enabledEffImpacts, $impacts);	// Do not use return value(boolean)
	} catch ( Exception $ex ) {}
}
(isset($_POST['prm_csv_usegtrow']) && !empty($_POST['prm_csv_usegtrow'])) ? $prm_usegtrow=true : $prm_usegtrow=false;	// Invalid

///varidating prm///
_pregMatch($prm_chr);
_pregMatch($prm_csv_list);
 _pregMatch($prm_csv_keyword);
if (!(is_numeric($prm_qual)) || !(is_numeric($prm_dp)) || !(is_numeric($choose_flag))) {
                 $errmsg = "<font color=\"#FF0000\">Error: Input Parameter Invalid!</font>";
                  echo $errmsg;
                  exit;
}
if (!(is_numeric($prm_s)) || !(is_numeric($prm_e))) {
                 $errmsg = "<font color=\"#FF0000\">Error: Input Parameter Invalid!</font>";
                  echo $errmsg;
                  exit;
}

// Global variables
$isPlus = modeIsPlus($conn);
$fastaTable = getSerialTableByColumn($conn, $db, "sys_fasta", $prm_chr."_f");
$dn2table = array();
$gtNa = "./.";

////////////////////////////////// Generation unique pos list 
////////////////////////////////// Getting pos filtered on qual, dp
$list=explode(",", $prm_list);
list($uniqPOS, $fltrPOS) = _allLIST($list, $prm_qual, $prm_dp, $prm_chr, $prm_s, $prm_e, $enabledEffImpacts, $conn);

//////////////////////////////////////////////////////////////////////
// Writing csv file
//////////////////////////////////////////////////////////////////////

echo _HEADER($list,$prm_s,$prm_e,$conn);

if($isPlus) {
	outputForSingleVcf($conn, $list, $prm_chr, $uniqPOS, $fltrPOS);
} else {
	outputForMultiVcf($conn, $list, $prm_chr, $uniqPOS, $fltrPOS);
}

$time = microtime(true) - $time_start;
error_log("csv.php time(sec):". $time);

function outputForMultiVcf($conn, $list, $prm_chr, $uniqPOS, $fltrPOS) {
    global $gtNa;

    $noAltGt = NULL;
    $naGt = NULL;

    $uniqPOS_cnt = count($uniqPOS);
    for ( $i=0; $i<$uniqPOS_cnt; $i++ ) {
	$ref = "";
	$lenRef = 0;
	$altArr = NULL;
	$colEff = array();	// elements is always 1.

	// Get GT info.
	$hitSnp = false;
	$hitIns = false;
	$hitDel = false;
	$gts = array();
	$list_cnt = count($list);
	for ( $j=0; $j<$list_cnt; $j++ ) {
		$chkDPStr = _CHKDP($list[$j], $prm_chr, $uniqPOS[$i], $conn);

		$vars = _SELECT_VAR($list[$j], $prm_chr, $uniqPOS[$i], $conn);
		if(count($vars) === 0) {
			if(!empty($noAltGt)) {
				$gts[] = $noAltGt;
			} else {
				$gts[] = "z";	// Later convert it to the format "0/0 ...".
			}
			continue;
		} 
		list($strVar, $strRef, $strAlt, $strGt, $strEff, $strAlts, $strGtrow, $strPosvcf) = $vars[0];
		if(empty($ref) && !empty($strRef)) {
			$ref = $strRef;
			$lenRef = strlen($ref);
			$altArr = explode(",", $strAlts);
		}
		if(count($colEff) === 0 && !empty($strEff)) $colEff[] = $strEff;
//		if ( empty($chkDPStr) || !empty($strVar)) {
		if ( !empty($chkDPStr) || $strGt === "./.") {
			// DEPTH = NA
			if(!empty($naGt)) {
				$gts[] = $naGt;
			} else {
				$gts[] = ".";	// Later convert it to the format "./. ...".
			}
		} else {
			// DEPTH != NA
			if( !empty($strEff) ) $colEff[] = $strEff;
			$gts[] = $strGtrow;

			// Check SNP/INS/DEL
			$gtArr = preg_split("/[\|\/]/", $strGtrow);
			$numGts = count($gtArr);
			for($k=0; $k<$numGts; $k++) {
				if($gtArr[$k] === "0") continue;
				$alt = $altArr[$gtArr[$k]-1];
				$lenAlt = strlen($alt);
				if($lenRef === $lenAlt) {
					$hitSnp = true;
				} else if($lenRef < $lenAlt) {
					$hitIns = true;
				} else {
					$hitDel = true;
				}
			}
		}
/*
		 else {
			// DEPTH = NA
			if(!empty($naGt)) {
				$gts[] = $naGt;
			} else {
				$gts[] = ".";	// Later convert it to the format "./. ...".
			}
		}
*/
	}

	// Track, FILTER.
	$genesStr = "";
	if(count($colEff)) {
		$genesStr = _GENEfromEff($colEff);
	} else {
		$genesStr = _GENE($uniqPOS[$i], $prm_chr, $conn);
	}

	$fltrStr = _FILTER($uniqPOS[$i], $fltrPOS);
	$effStr = _EFF($colEff);
	$vars = array();
	if($hitSnp) $vars[] = "SNP";
	if($hitIns) $vars[] = "INS";
	if($hitDel) $vars[] = "DEL";
	$varsStr = implode(",", $vars);

	// Change the length of "0/0" and "./." depending on the ploidy. 
	// This is only executed on the first line.
	if(empty($noAltGt)) {
		$cntGts = count($gts);
		for($j=0; $j<$cntGts; $j++) {
			if(preg_match("/^\d/", $gts[$j])) {
				$noAltGt = preg_replace("/\d+/", "0", $gts[$j]);
				$naGt = preg_replace("/\d+/", ".", $gts[$j]);
				continue;
			}
		}
		for($j=0; $j<$cntGts; $j++) {
			if($gts[$j] === "z") {
				$gts[$j] = $noAltGt;
			} else if($gts[$j] === ".") {
				$gts[$j] = $naGt;
			}
		}
	}

	echo implode("\t", array(
		$prm_chr,
		$uniqPOS[$i],
		$varsStr,
		$ref,
		implode(",", $altArr),
		$fltrStr,
		$genesStr,
		$effStr,
		implode("\t", $gts)
	)). "\n";
    }
}
function outputForSingleVcf($conn, $list, $prm_chr, $uniqPOS, $fltrPOS) {
  global $gtNa;

  $uniqPOS_cnt = count($uniqPOS);
  for ( $i=0; $i<$uniqPOS_cnt; $i++ ) {

    // PreRun: Get "current position variant information" and "longest REF-seq" for all accessions.
    $accss = array();
    $colEffs = array();
    $longestRefs = array();

    $list_cnt = count($list);
    for ( $j=0; $j<$list_cnt; $j++ ) {
        $chkDPStr = _CHKDP($list[$j], $prm_chr, $uniqPOS[$i], $conn);

	$vars = _SELECT_VAR($list[$j], $prm_chr, $uniqPOS[$i], $conn);
	foreach ($vars as $var) {
		list($strVar, $strRef, $strAlt, $strGt, $strEff, $strAlts, $strGtrow, $strPosvcf) = $var;
		if(!array_key_exists($strPosvcf, $accss)) {
			$accss[$strPosvcf] = array();
			for ( $k=0; $k<$list_cnt; $k++ ) {
				$accss[$strPosvcf][$k] = array("gt" => "");	// Initialize array.
			}
			$longestRefs[$strPosvcf] = "";
			$colEffs[$strPosvcf] = array();
		}
		if ( empty($chkDPStr) || !empty($strVar)) {
			// DEPTH != NA
			if( !empty($strEff) ) $colEffs[$strPosvcf][] = $strEff;
			$refLen = strlen($strRef);
			if($refLen > strlen($longestRefs[$strPosvcf])) {
				$longestRefs[$strPosvcf] = $strRef;
			}
			//TODO Switching the value to be assigned using $prm_usegtrow uses less memory.
			$accss[$strPosvcf][$j] = array("var" => $strVar, "ref" => $strRef, "alt" => $strAlt, "gt" => $strGt, "gtrow" => $strGtrow);
		} else {
			// DEPTH = NA
			$accss[$strPosvcf][$j] = array("gt" => $gtNa);
		}
	}
    }

    // Basically, the length of $pos_vcfs is 1, but it also supports cases where multiple pos are obtained (e.g., when multiple SingleVCFs are used). 
    $pos_vcfs = array_keys($accss);
    sort($pos_vcfs);
    foreach($pos_vcfs as $pos_vcf) {
	$accs = $accss[$pos_vcf];
	$colEff = $colEffs[$pos_vcf];
	$longestRef = $longestRefs[$pos_vcf];
	$longestRefLen = strlen($longestRef);

	// Convert ALT-seq to match "longest REF"
	$sumAltkeys = array();
	$hitSnp = false;
	$hitIns = false;
	$hitDel = false;
	for($j=0; $j<$list_cnt; $j++) {
		$acc = $accs[$j];
//error_log("Tabei:". $i. ",". $j. ",". $acc["gt"]. ",". $acc["var"]);
		if($acc["gt"] === $gtNa) {
		} else {
			if ( empty($acc["var"]) || $acc["gt"] === "0/0" || $acc["gt"] === "0|0") continue;

			$altArr = explode(",", $acc["alt"]);
			$altCnvArr = array();
			$numAlts = count($altArr);
			for($k=0; $k<$numAlts; $k++) {
				$alt = $altArr[$k];
				$altCnv = "";
				$lenRef = strlen($acc["ref"]);
				$lenAlt = strlen($altArr[$k]);
				$var = "";
				if($lenRef === $lenAlt) {
					$hitSnp = true;
					$altCnv = _convVar("SNP", $longestRef, $acc["ref"], $alt);
				} else if($lenRef < $lenAlt) {
					$hitIns = true;
					if(_isTransposon($alt)) {
						$altCnv = $alt;
					} else {
						$altCnv = _convVar("INS", $longestRef, $acc["ref"], $alt);
					}
				} else {
					$hitDel = true;
					$altCnv = _convVar("DEL", $longestRef, $acc["ref"], $alt);
				}
	
				if(!array_key_exists($altCnv, $sumAltkeys)) {
					$sumAltkeys[$altCnv] = 0;
				}
				$sumAltkeys[$altCnv]++;
	
				$altCnvArr[] = $altCnv;
			}
			$accs[$j]["altCnvArr"] = $altCnvArr;
		}
    	}

	// Assign GT numbers in order of appearance frequency of ALT-alleles.
	$sortedAltkeys = array();
	$uniAltkeys = array();
	arsort($sumAltkeys);
	$gtIdx = 0;
	foreach($sumAltkeys as $altCnv => $sum) {
		$gtIdx++;
		$uniAltkeys[$altCnv] = $gtIdx;
		$sortedAltkeys[] = $altCnv;
//error_log($i. ":". $altCnv. ",". $sum);
	}

	// Generate GT strings.
	$colVar = array();
	for($j=0; $j<$list_cnt; $j++) {
		$acc = $accs[$j];
		if($acc["gt"] === $gtNa) {
			$colVar[$j] = $gtNa;
		} else if ( empty($acc["var"]) || $acc["gt"] === "0/0" || $acc["gt"] === "0|0") {
			$colVar[$j] = "0/0";
		} else {
//error_log("Tabei:". $prm_usegtrow. " ". $altsMvcf. " => ". implode(",", array_keys($uniAltkeys)));
			$altGt = "";
			$gt1 = $uniAltkeys[$acc["altCnvArr"][0]];
			if ( $acc["gt"] === "1/1" || $acc["gt"] === "1|1") {
				$altGt = $gt1. "/". $gt1; 
			} else if($acc["gt"] === "0/1" || $acc["gt"] === "0|1") {
				$altGt = "0/". $gt1;
			} else if ($acc["gt"] === "1/0" || $acc["gt"] === "1|0") {
				$altGt = $gt1. "/0";
			} else {
				// $strGt === "1/2"
				$gt2 = $uniAltkeys[$acc["altCnvArr"][1]];
				$altGt = $gt1. "/". $gt2;
			}
			$colVar[$j] = $altGt;
		}
	}

	// Track, FILTER
	$genesStr = "";
	if(count($colEff)) {
		$genesStr = _GENEfromEff($colEff);
	} else {
		$genesStr = _GENE($uniqPOS[$i], $prm_chr, $conn);
	}
//	$genesStr = _GENE($uniqPOS[$i], $prm_chr, $conn);

	$fltrStr = _FILTER($uniqPOS[$i], $fltrPOS);
	$effStr = _EFF($colEff);
	$vars = array();
	if($hitSnp) $vars[] = "SNP";
	if($hitIns) $vars[] = "INS";
	if($hitDel) $vars[] = "DEL";
	$varsStr = implode(",", $vars);

	echo implode("\t", array(
		$prm_chr,
		$uniqPOS[$i],
		$varsStr,
		$longestRef,
		implode(",", $sortedAltkeys),
		$fltrStr,
		$genesStr,
		$effStr,
		implode("\t", $colVar)
	)). "\n"; 
    }
  }
}

function _convVar($var, $longestRef, $gtRef, $gtAlt) {
	$cnvAlt = "";
	if($var === 'SNP') {
		$cnvAlt = $gtAlt. substr($longestRef, strlen($gtAlt));
	} else if($var === 'INS') {
//		$cnvAlt = $gtAlt. substr($longestRef, 1);
		$cnvAlt = $gtAlt. substr($longestRef, strlen($gtRef));
	} else {
		// $var === DEL
		$cnvAlt = $gtAlt. substr($longestRef, strlen($gtRef)); 
	}
	return $cnvAlt;
}
function _SELECT_VAR($a,$b,$c,$conn){
    global $isPlus;

    $query = "";
    if($isPlus) {
//	$query = "SELECT variant,REF,ALT,GT,EFF,ALT,GT,pos FROM ".$a."_variant WHERE ". getGtNotZeroSql(). " and chr=? and pos=? order by variant desc";	// s > i > d
	$query = "SELECT variant,REF,ALT,GT,EFF,ALT,GT,(CASE WHEN variant='d' THEN pos-1 ELSE pos END) FROM ".$a."_variant WHERE ".
		getGtNotZeroSql(). " and chr=? and pos=? order by variant desc";	// s > i > d
    } else {
	// In mvcf-DB mode, it is necessary to reproduce the original VCF's "1position=1ALTset".
	// In the case of DEL, it is registered in the DB with "pos=pos+1". If SNP and DEL are adjacent,
	// different ALT sets will be obtained between samples. Therefore, use pos_vcf instead of pos.
	// If there is a DEL in the boundary of pos, it cannot be obtained.
	// (It is the same as the original VCF)
	$query = "SELECT variant,REF,ALT,GT,EFF,ALTS,GTROW,s.pos_vcf FROM sys_variant s,". $a. "_variant v WHERE ". getGtNotZeroSql().
		" and s.chr=v.chr and s.pos_vcf=v.pos_vcf and v.chr=? and v.pos_vcf=? order by variant desc";	// s > i > d
    }
    $stmt = $conn->stmt_init();
    $stat = $stmt->prepare($query);

    if(!$stat) { return array(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); }

    $stmt->bind_param("si", $b, $c); 
    $stmt->execute();
    $stmt->store_result();
    $stmt->bind_result($row0,$row1,$row2,$row3,$row4,$rowAlts,$rowGtrow,$rowPos);
    $arr = array();
    while ($stmt->fetch()) {
        $arr[] = array($row0,$row1,$row2,$row3,$row4,$rowAlts,$rowGtrow,$rowPos);
    }
    $stmt->free_result();
    $stmt->close();
    return $arr;
}

function _GETPOSBYIDS($a,$conn){
    $query = "SELECT pos, end FROM sys_track WHERE id like ? and parent=1 order by id LIMIT 1";
    $param = "%".$a."%";
    $stmt = $conn->stmt_init();
    $stmt->prepare($query);
    $stmt->bind_param("s", $param); 
    $stmt->execute();
    $stmt->store_result();
    $stmt->bind_result($row0,$row1);
    $stmt->fetch();
    $rtn_array = array((int)$row0, (int)$row1);
//    $rtn_array = array((int)$row0+100,(int)$row1+100);
    $stmt->free_result();
    $stmt->close();
    return $rtn_array;
}

/*
function _GETREF($a,$b,$conn){
    global $fastaTable;
    $query = "SELECT `".$a."_f` FROM ". $fastaTable. " WHERE pos= ?";
//    $query = "SELECT `".$a."_f` FROM sys_fasta WHERE pos= ?";
    $stmt = $conn->stmt_init();
    $stmt->prepare($query);
    $stmt->bind_param("i", $b); 
    $stmt->execute();
    $stmt->store_result();
    $stmt->bind_result($row0);
    $stmt->fetch();
    $rtn = $row0;
    $stmt->free_result();
    $stmt->close();
    return $rtn;
}
*/

function _HEADER($a,$b,$c,$conn){
    //$str=$b."~".$c."\n";
    $str="#Chr\tpos\ttype\tref\talt\tFiltered qual or dp\tGene\tAnnotation";
    $query="SELECT accession_id, sub_variety FROM sys_accession WHERE accession_db= ? ";
    $stmt = $conn->stmt_init();
    $stmt->prepare($query);
    for($i=0;$i<count($a);$i++){
        $stmt->bind_param("s", $a[$i]); 
        $stmt->execute();
        $stmt->store_result();
        $stmt->bind_result($row0,$row1);
        while ($stmt->fetch()) {
            //$str=$str."#".($i+1)." ".$row0." ".$row1."\n";
//            $str=$str."\t".$row0." ".$row1;
             $str = $str. "\t". $row0;
        }
        $stmt->free_result();
    }
    $stmt->close();
    $str=$str."\n";
    return $str;
}
function _allLIST($a, $b, $c, $d, $e, $f,$enabledEffImpacts, $conn) {
	global $isPlus;

	$all=array();
	$filtered=array();
	$stmt = $conn->stmt_init();
	for($i=0;$i<count($a);$i++){
		if($isPlus) {
			$query="SELECT pos,EFF,QUAL,DP FROM ".$a[$i]."_variant WHERE ". getGtNotZeroSql(). " and chr=? and pos>=? and pos<=?";
		} else {
			$query="SELECT v.pos_vcf,EFF,GQ,DP FROM sys_variant s,". $a[$i]. "_variant v WHERE ". 
				getGtNotZeroSql(). " and s.chr=v.chr and s.pos_vcf=v.pos_vcf and v.chr=? and v.pos>=? and v.pos<=?";
		}
		$stmt->prepare($query);
		$stmt->bind_param("sii", $d, $e, $f);
		$stmt->execute();
		$stmt->store_result();
		$stmt->bind_result($row0, $rowEff, $rowQual, $rowDp);
		$uniPos = array();
		while ($stmt->fetch()) {
			if(array_key_exists($row0, $uniPos)) continue;
			$uniPos[$row0] = true;

			$all[]=$row0;

			$doFilter = False;

			// SnpEff Filter
			if(empty($rowEff)) {
				if(!$enabledEffImpacts["-1"]) $doFilter = True;
			} else {
				$eff_list=explode(",", $rowEff);
				$t = count($eff_list);
				$hitImpact = False;
				for($k=0; $k<$t; $k++){
					$effInfo = _parseSnpEff($eff_list[$k]);
					$impact = $effInfo["impactc"];
					if(!empty($impact) && $enabledEffImpacts[(string)$impact]) $hitImpact = True;
				}
				if(!$hitImpact) $doFilter = True;
			}

			// QUAL
			if(!$doFilter && $rowQual < $b) $doFilter = True;

			// DP
			if(!$doFilter && $rowDp < $c) $doFilter = True;

			if($doFilter) $filtered[] = $row0;
		}
		$stmt->free_result();
	}
	$stmt->close();

	$returnAllArr = array_values(array_unique($all));
	sort($returnAllArr);
	$returnFilteredArr = array_values(array_unique($filtered));
	return array($returnAllArr, $returnFilteredArr);
}
function _FILTER($a, $b){
    $k = array_search($a, $b);
    if ( $k !== false ) {
        return "yes"; //filtered
    } else {
        return "no"; //not filtered
    }
}

function _getFirstAllele($str) {
	$alleles = explode(",", $str);
	return $alleles[0];
}

function _COL($a) {
    return implode("\t", $a);
}

function _GENE($a, $b, $conn) {
    // Retrieving tracks
    $cnt=0;
    $query="SELECT * FROM (SELECT id,IF(parent=0,type,'') FROM sys_track WHERE chr=? and ?>=pos AND ?<=end ORDER BY type) as a GROUP BY id";
    $stmt = $conn->stmt_init();
    $stmt->prepare($query);
    $stmt->bind_param("sii", $b, $a, $a); 
    $stmt->execute();
    $stmt->store_result();
    $stmt->bind_result($row0,$row1);
    while ($stmt->fetch()) {
        if ( $row0 != "" ) {
            $g[$cnt][0]=$row0;
            $g[$cnt][1]=$row1;
            $cnt++;
        }
    }
    $stmt->free_result();
    $stmt->close();
    $str="";
    for($i=0;$i<$cnt;$i++){
        $str .= $g[$i][0];
        if ( $g[$i][1] != "" ) $str .= ":".$g[$i][1];
        if ( $i < $cnt-1 ) $str .= ",";
/*
        $str=$str.$g[$i][0];
        if ( $g[$i][1] != "" ) $str=$str.":".$g[$i][1];
        if ( $i < $cnt-1 ) $str=$str.",";
*/
    }
    return $str;
}
function _GENEfromEff($colEff) {
	global $ANNcol, $EFFcol;

	$uniGene = array();
	$icount = count($colEff);
	for($i=0; $i<$icount; $i++) {
		$effsAcc = preg_split("/\s*,\s*/", $colEff[$i]);
		$jcount = count($effsAcc);
		for($j=0; $j<$jcount; $j++) {
			$eff = $effsAcc[$j];
			$col = $ANNcol;
			if(preg_match("/^[^\|\(]+\(.+$/", $eff)) $col = $EFFcol;     //TODO common function

			$vals = explode("|", $eff);
			$uniGene[$vals[$col]] = true;
		}
	}
	return implode(",", array_keys($uniGene));
}

function _EFF($colEff) {
    $str = "";
    $uniqEffMap = array();
    $uniqEffArray = array();
    $icount = count($colEff);
    for($i=0; $i<$icount; $i++) {
        $effsAcc = preg_split("/\s*,\s*/", $colEff[$i]);
	$jcount = count($effsAcc);
        for($j=0; $j<$jcount; $j++) {
            $eff = $effsAcc[$j];
            $key = preg_replace("/\s/", "", strtolower($eff));
            if(!array_key_exists($key, $uniqEffMap)) {
                $str .= $eff. ",";
            }
            $uniqEffMap[$key] = True;
        }
    }
    $str = preg_replace("/,$/", "", $str);
    return $str;
}

function _CHKDP($a, $b, $c, $conn){
    global $db, $dn2table;

    $table = "";
    if(array_key_exists($a, $dn2table)) {  
        $table = $dn2table[$a];
    } else {
        $table = getSerialTableByColumn($conn, $db, $a."_accession", $b."_b");
        $dn2table[$a] = $table;
    }
    $query="SELECT pos FROM ". $table. " WHERE `".$b."_b` is null and pos= ? ";
//    $query="SELECT pos FROM ".$a."_accession WHERE `".$b."_b` is null and pos= ? ";
    $stmt = $conn->stmt_init();
    $stat = $stmt->prepare($query);
    if(!$stat) { return NULL; }
    $stmt->bind_param("i", $c); 
    $stmt->execute();
    $stmt->store_result();
    $stmt->bind_result($row0);
    $stmt->fetch();
    $rtn = $row0;
    $stmt->free_result();
    $stmt->close();
    return $rtn;
}

function returnError($str){
    echo $str;
}

function _stopError($str){
    echo $str;
    exit;
}
?>
