#!/usr/local/bin/perl

# a program to detect de novo CNVs

die "Usage: pre_twinning_denovos <.out file> <output file>\n"    	
        unless @ARGV == 2;

$output = "@ARGV[1]";

open OUT , ">$output" or die "Can't open $output: @ARGV[1].txt!\n";



###############################################################################################################################################
######################################## open CNV calls (BS vs PC) and store info in hashes ##################################################

open (READ1, "@ARGV[0]") || die "Cannot open @ARGV[0]\n";

# The tab-delimited columns of the input file represent: 
# 0 - perID:			person ID - must be in format: 00001-01 -> family ID (5 nrs) + "-" + person ID (2 nrs)
# 1 - overlap_prop:		proportion overlap (Birdsuite & PennCNV)
# 2 - overlap_size:		size overlap (Birdsuite & PennCNV)
# 3 - start:			segment start (overlap Birdsuite & PennCNV)
# 4 - end:			segment end (overlap Birdsuite & PennCNV)
# 5 - chr_BS: 		chr (Birdsuite)
# 6 - start_BS:		segment start (Birdsuite)
# 7 - end_BS:			segment end (Birdsuite)
# 8 - size_BS:		size of CNV (Birdsuite)
# 9 - num_probes_BS:		number of loci (CN or SNP probes) in the segment (Birdsuite)
# 10 - cn_BS:			CN call (Birdsuite)
# 11 - chr_PC: 		chr (PennCNV)
# 12 - start_PC:		segment start (PennCNV)
# 13 - end_PC:		segment end (PennCNV)
# 14 - size_PC:		size of CNV (PennCNV)
# 15 - num_probes_PC:	number of loci (CN or SNP probes) in the segment (PennCNV)
# 16 - cn_PC:			CN call (PennCNV)
# 17 - lod_score_BS:		LOD score of the probability of the segment being the stated copy number versus the copy number of the flanking segments
# 18 - cn_agreement: 	has to be 1 for all CNVs (means Birdsuite & PennCNV call is the same) or -1 (means that there were no losses or gains -> come from Birdsuite)


$nrfam = -1;
$nrstart = -1;
$nrend = -1;

		while ($line=<READ1>)
		{
			if ($line =~ "perID")				# skip the header
			{
			next;
			}

		@splitCNline = split (/\s+/  , $line);				# create array

		if (@famIDraw[$nrfam] != substr(@splitCNline[0], 0, 5))
			{
			$nrfam++;
			}

		@famIDraw[$nrfam] = substr(@splitCNline[0], 0, 5);		# store family id (first 5 numbers of sample number)
		$perID = substr(@splitCNline[0], 6, 2);				# store person id (last 2 numbers of sample number)
		$chr = @splitCNline[5];						# store chromosome number (BS!)
		$start = @splitCNline[3];
		$end = @splitCNline[4];

		$CNV{$chr}{$start,$end} = "$chr\t" . "$start\t" . "$end" ;

		$CNVchr{$chr}{$start,$end} = $chr;
		$CNVstart{$chr}{$start,$end} = $start;
		$CNVend{$chr}{$start,$end} = $end;

		$size{$chr}{$start,$end} = @splitCNline[2];
		$numprobes_1{$chr}{$start,$end} = @splitCNline[9];
		$numprobes_2{$chr}{$start,$end} = @splitCNline[15];

		$cn{@famIDraw[$nrfam]}{$perID}{$CNV{$chr}{$start,$end}} = @splitCNline[16];
		$lod{@famIDraw[$nrfam]}{$perID}{$CNV{$chr}{$start,$end}} = @splitCNline[17];

		}

$totalcnvs = 0;

close READ1;

##################################################################################################################################################


######## filter out duplicates from the family nr array #######

    	undef %saw;
    	@famID = grep(!$saw{$_}++, @famIDraw);

###############################################################


################ print header of the output file ################

	print OUT "famID\t";
	print OUT "chr\t";
	print OUT "start\t";
	print OUT "end\t";
	print OUT "size\t";
	print OUT "tw1_cn\t";
	print OUT "tw1_lod_score\t";
	print OUT "tw2_cn\t";
	print OUT "tw2_lod_score\t";
	print OUT "father_cn\t";
	print OUT "father_lod_score\t";
       print OUT "mother_cn\t";
	print OUT "mother_lod_score\n";


##################################################################

############## get maximum & minimum value subs ##############

sub max {

my (@maxinput) = @_;

	if ($maxinput[0] > $maxinput[1])
	{
	return $maxinput[0];
	}

	if ($maxinput[0] <= $maxinput[1])
	{
	return $maxinput[1];
	}

}

sub min {

my (@mininput) = @_;

	if ($mininput[0] > $mininput[1])
	{
	return $mininput[1];
	}

	if ($mininput[0] <= $mininput[1])
	{
	return $mininput[0];
	}

}

#################################################################

############## check pre-twinning de novos sub ###############

sub denovo {

my (@cns) = @_;					# input array = CN dad; CN mom; CN twin 1; CN twin 2

	if (($cns[0] == -1) || ($cns[1] == -1) || ($cns[2] == -1) || ($cns[3] == -1))
	{
	return 0;
	}

	if (($cns[0] == 0) && ($cns[1] == 0))			# both parents CN=0
	{
		if (($cns[2] != 0) && ($cns[3] != 0))
			{
			return 1;
			}
	}

	if (($cns[0] == 1) && ($cns[1] == 1))			# both parents CN=1
	{
		if (($cns[2] == $cns[3]) && (($cns[2] != 0) && ($cns[2] != 1) && ($cns[2] != 2)))
			{
			return 1;
			}
	}

	if (($cns[0] == 2) && ($cns[1] == 2))			# both parents CN=2
	{
		if (($cns[2] == $cns[3]) && ($cns[2] != 2))
			{
			return 1;
			}
	}

	if (($cns[0] == 3) && ($cns[1] == 3))			# both parents CN=3
	{
		if (($cns[2] == $cns[3]) && (($cns[2] != 2) && ($cns[2] != 3) && ($cns[2] != 4)))
			{
			return 1;
			}
	}

	if (($cns[0] == 4) && ($cns[1] == 4))			# both parents CN=4
	{
		if (($cns[2] == $cns[3]) && ($cns[2] != 4))
			{
			return 1;
			}
	}

	if ((($cns[0] == 0) && ($cns[1] == 1)) || (($cns[0] == 1) && ($cns[1] == 0)))			# 1 parents CN=0, 1 parent CN=1
	{
		if (($cns[2] == $cns[3]) && (($cns[2] != 0) && ($cns[2] != 1)))
			{
			return 1;
			}
	}

	if ((($cns[0] == 0) && ($cns[1] == 2)) || (($cns[0] == 2) && ($cns[1] == 0)))			# 1 parents CN=0, 1 parent CN=2
	{
		if (($cns[2] == $cns[3]) && ($cns[2] != 1))
			{
			return 1;
			}
	}

	if ((($cns[0] == 0) && ($cns[1] == 3)) || (($cns[0] == 3) && ($cns[1] == 0)))			# 1 parents CN=0, 1 parent CN=3
	{
		if (($cns[2] == $cns[3]) && (($cns[2] != 1) && ($cns[2] != 2)))
			{
			return 1;
			}
	}

	if ((($cns[0] == 0) && ($cns[1] == 4)) || (($cns[0] == 4) && ($cns[1] == 0)))			# 1 parents CN=0, 1 parent CN=4
	{
		if (($cns[2] == $cns[3]) && ($cns[2] != 2))
			{
			return 1;
			}
	}

	if ((($cns[0] == 1) && ($cns[1] == 2)) || (($cns[0] == 2) && ($cns[1] == 1)))			# 1 parents CN=1, 1 parent CN=2
	{
		if (($cns[2] == $cns[3]) && (($cns[2] != 1) && ($cns[2] != 2)))
			{
			return 1;
			}
	}

	if ((($cns[0] == 1) && ($cns[1] == 3)) || (($cns[0] == 3) && ($cns[1] == 1)))			# 1 parents CN=1, 1 parent CN=3
	{
		if (($cns[2] == $cns[3]) && (($cns[2] != 1) && ($cns[2] != 2) && ($cns[2] != 3)))
			{
			return 1;
			}
	}

	if ((($cns[0] == 1) && ($cns[1] == 4)) || (($cns[0] == 4) && ($cns[1] == 1)))			# 1 parents CN=1, 1 parent CN=4
	{
		if (($cns[2] == $cns[3]) && (($cns[2] != 2) && ($cns[2] != 3)))
			{
			return 1;
			}
	}

	if ((($cns[0] == 2) && ($cns[1] == 3)) || (($cns[0] == 3) && ($cns[1] == 2)))			# 1 parents CN=2, 1 parent CN=3
	{
		if (($cns[2] == $cns[3]) && (($cns[2] != 2) && ($cns[2] != 3)))
			{
			return 1;
			}
	}

	if ((($cns[0] == 2) && ($cns[1] == 4)) || (($cns[0] == 4) && ($cns[1] == 2)))			# 1 parents CN=2, 1 parent CN=4
	{
		if (($cns[2] == $cns[3]) && ($cns[2] != 3))
			{
			return 1;
			}
	}

	if ((($cns[0] == 3) && ($cns[1] == 4)) || (($cns[0] == 4) && ($cns[1] == 3)))			# 1 parents CN=3, 1 parent CN=4
	{
		if (($cns[2] == $cns[3]) && (($cns[2] != 3) && ($cns[2] != 4)))
			{
			return 1;
			}
	}

return 0;

}

#################################################################

##########################################################################################################
########### create two sets (in hashes) of CNVs that overlap between parents and between twins ###########

for($j=1;$j<=24;++$j)
	{
		foreach $key1 (sort keys %{$CNV{$j}})
		{
			foreach $key2 (sort keys %{$CNV{$j}})
			{
				if (($CNVstart{$j}{$key2} < $CNVstart{$j}{$key1}) && ($CNVend{$j}{$key2} < $CNVstart{$j}{$key1}))
				{
				next;
				}


				if (($CNVstart{$j}{$key2} > $CNVend{$j}{$key1}) && ($CNVend{$j}{$key2} > $CNVend{$j}{$key1}))
				{
				next;
				}

				for($i=0;$i<@famID;++$i)
				{
					if
                                        	(
                                        	(($CNVstart{$j}{$key1} >= $CNVstart{$j}{$key2}) && ($CNVstart{$j}{$key1} <= $CNVend{$j}{$key2})) ||
						(($CNVend{$j}{$key1} >= $CNVstart{$j}{$key2}) && ($CNVend{$j}{$key1} <= $CNVend{$j}{$key2})) ||
						(($CNVstart{$j}{$key2} >= $CNVstart{$j}{$key1}) && ($CNVstart{$j}{$key2} <= $CNVend{$j}{$key1})) ||
						(($CNVend{$j}{$key2} >= $CNVstart{$j}{$key1}) && ($CNVend{$j}{$key2} <= $CNVend{$j}{$key1}))
						)
                                        {
					######## set missing copy nrs to -1 ########	$key1

					if ($cn{$famID[$i]}{'01'}{$CNV{$j}{$key1}} eq "")
						{
						$cn{$famID[$i]}{'01'}{$CNV{$j}{$key1}} = -1;
						}

					if ($cn{$famID[$i]}{'02'}{$CNV{$j}{$key1}} eq "")
						{
						$cn{$famID[$i]}{'02'}{$CNV{$j}{$key1}} = -1;
						}

					if ($cn{$famID[$i]}{'31'}{$CNV{$j}{$key1}} eq "")
						{
						$cn{$famID[$i]}{'31'}{$CNV{$j}{$key1}} = -1;
						}

					if ($cn{$famID[$i]}{'41'}{$CNV{$j}{$key1}} eq "")
						{
						$cn{$famID[$i]}{'41'}{$CNV{$j}{$key1}} = -1;
						}

					#############################################
					######## set missing copy nrs to -1 ########	$key2

					if ($cn{$famID[$i]}{'01'}{$CNV{$j}{$key2}} eq "")
						{
						$cn{$famID[$i]}{'01'}{$CNV{$j}{$key2}} = -1;
						}

					if ($cn{$famID[$i]}{'02'}{$CNV{$j}{$key2}} eq "")
						{
						$cn{$famID[$i]}{'02'}{$CNV{$j}{$key2}} = -1;
						}

					if ($cn{$famID[$i]}{'31'}{$CNV{$j}{$key2}} eq "")
						{
						$cn{$famID[$i]}{'31'}{$CNV{$j}{$key2}} = -1;
						}

					if ($cn{$famID[$i]}{'41'}{$CNV{$j}{$key2}} eq "")
						{
						$cn{$famID[$i]}{'41'}{$CNV{$j}{$key2}} = -1;
						}

					#############################################


					####### set missing lod scores to -1 ########	$key1

					if ($lod{$famID[$i]}{'01'}{$CNV{$j}{$key1}} eq "")
						{
						$lod{$famID[$i]}{'01'}{$CNV{$j}{$key1}} = -1;
						}

					if ($lod{$famID[$i]}{'02'}{$CNV{$j}{$key1}} eq "")
						{
						$lod{$famID[$i]}{'02'}{$CNV{$j}{$key1}} = -1;
						}

					if ($lod{$famID[$i]}{'31'}{$CNV{$j}{$key1}} eq "")
						{
						$lod{$famID[$i]}{'31'}{$CNV{$j}{$key1}} = -1;
						}

					if ($lod{$famID[$i]}{'41'}{$CNV{$j}{$key1}} eq "")
						{
						$lod{$famID[$i]}{'41'}{$CNV{$j}{$key1}} = -1;
						}

					#############################################
					####### set missing lod scores to -1 ########	$key2

					if ($lod{$famID[$i]}{'01'}{$CNV{$j}{$key2}} eq "")
						{
						$lod{$famID[$i]}{'01'}{$CNV{$j}{$key2}} = -1;
						}

					if ($lod{$famID[$i]}{'02'}{$CNV{$j}{$key2}} eq "")
						{
						$lod{$famID[$i]}{'02'}{$CNV{$j}{$key2}} = -1;
						}

					if ($lod{$famID[$i]}{'31'}{$CNV{$j}{$key2}} eq "")
						{
						$lod{$famID[$i]}{'31'}{$CNV{$j}{$key2}} = -1;
						}

					if ($lod{$famID[$i]}{'41'}{$CNV{$j}{$key2}} eq "")
						{
						$lod{$famID[$i]}{'41'}{$CNV{$j}{$key2}} = -1;
						}

					#############################################

                                        if 	(
                                        		($cn{$famID[$i]}{'31'}{$CNV{$j}{$key1}} != -1) &&
                                                	($cn{$famID[$i]}{'41'}{$CNV{$j}{$key2}} != -1)
                                           	)
                                                	{
		       				$start = max($CNVstart{$j}{$key1},$CNVstart{$j}{$key2});
							$end = min($CNVend{$j}{$key1},$CNVend{$j}{$key2});
                                                	$CNVstart_par{$j}{$start,$end} = $start;
                                                	$CNVend_par{$j}{$start,$end} = $end;
                                                	$CNVchr_par{$j}{$start,$end} = $j;
                                                	$CNVsize_par{$j}{$start,$end} = $end - $start;
                                      		$CNV_par{$j}{$start,$end} = "$j\t" . "$start\t" . "$end" ;

                                        		$cn_par{$famID[$i]}{'31'}{$CNV_par{$j}{$start,$end}} = $cn{$famID[$i]}{'31'}{$CNV{$j}{$key1}};
							$lod_par{$famID[$i]}{'31'}{$CNV_par{$j}{$start,$end}} = $lod{$famID[$i]}{'31'}{$CNV{$j}{$key1}};
                                                	$cn_par{$famID[$i]}{'41'}{$CNV_par{$j}{$start,$end}} = $cn{$famID[$i]}{'41'}{$CNV{$j}{$key2}};
							$lod_par{$famID[$i]}{'41'}{$CNV_par{$j}{$start,$end}} = $lod{$famID[$i]}{'41'}{$CNV{$j}{$key2}};
                                                	}

                                        if 	(
                                               	($cn{$famID[$i]}{'01'}{$CNV{$j}{$key1}} != -1) &&
                                                	($cn{$famID[$i]}{'02'}{$CNV{$j}{$key2}} != -1)
                                           	)
                                                	{
		       				$start = max($CNVstart{$j}{$key1},$CNVstart{$j}{$key2});
							$end = min($CNVend{$j}{$key1},$CNVend{$j}{$key2});
                                                	$CNVstart_tw{$j}{$start,$end} = $start;
                                                	$CNVend_tw{$j}{$start,$end} = $end;
                                                	$CNVchr_tw{$j}{$start,$end} = $j;
                                                	$CNVsize_tw{$j}{$start,$end} = $end - $start;
                                      		$CNV_tw{$j}{$start,$end} = "$j\t" . "$start\t" . "$end" ;

                                        		$cn_tw{$famID[$i]}{'01'}{$CNV_tw{$j}{$start,$end}} = $cn{$famID[$i]}{'01'}{$CNV{$j}{$key1}};
							$lod_tw{$famID[$i]}{'01'}{$CNV_tw{$j}{$start,$end}} = $lod{$famID[$i]}{'01'}{$CNV{$j}{$key1}};
                                                	$cn_tw{$famID[$i]}{'02'}{$CNV_tw{$j}{$start,$end}} = $cn{$famID[$i]}{'02'}{$CNV{$j}{$key2}};
							$lod_tw{$famID[$i]}{'02'}{$CNV_tw{$j}{$start,$end}} = $lod{$famID[$i]}{'02'}{$CNV{$j}{$key2}};
                                                	}

                                        }
				}
			}
		}
	}

##########################################################################################################

#######################################################################################################
################# Compare the parental CNVs with the childrens CNVs and print output ##################

for($j=1;$j<=24;++$j)
	{
		foreach $key1 (sort keys %{$CNV_par{$j}})
		{
			foreach $key2 (sort keys %{$CNV_tw{$j}})
			{
				if (($CNVstart_tw{$j}{$key2} < $CNVstart_par{$j}{$key1}) && ($CNVend_tw{$j}{$key2} < $CNVstart_par{$j}{$key1}))
				{
				next;
				}

				if (($CNVstart_tw{$j}{$key2} > $CNVend_par{$j}{$key1}) && ($CNVend_tw{$j}{$key2} > $CNVend_par{$j}{$key1}))
				{
				next;
				}

				for($i=0;$i<@famID;++$i)
				{

				if 	(
					(($CNVstart_par{$j}{$key1} >= $CNVstart_tw{$j}{$key2}) && ($CNVstart_par{$j}{$key1} <= $CNVend_tw{$j}{$key2})) ||
					(($CNVend_par{$j}{$key1} >= $CNVstart_tw{$j}{$key2}) && ($CNVend_par{$j}{$key1} <= $CNVend_tw{$j}{$key2})) ||
					(($CNVstart_tw{$j}{$key2} >= $CNVstart_par{$j}{$key1}) && ($CNVstart_tw{$j}{$key2} <= $CNVend_par{$j}{$key1})) ||
					(($CNVend_tw{$j}{$key2} >= $CNVstart_par{$j}{$key1}) && ($CNVend_tw{$j}{$key2} <= $CNVend_par{$j}{$key1}))
					)
                                	{
					######## set missing copy nrs to -1 ########	$key1

					if ($cn_par{$famID[$i]}{'31'}{$CNV_par{$j}{$key1}} eq "")
						{
						$cn_par{$famID[$i]}{'31'}{$CNV_par{$j}{$key1}} = -1;
						}

					if ($cn_par{$famID[$i]}{'41'}{$CNV_par{$j}{$key1}} eq "")
						{
						$cn_par{$famID[$i]}{'41'}{$CNV_par{$j}{$key1}} = -1;
						}

					#############################################
					######## set missing copy nrs to -1 ########	$key2

					if ($cn_tw{$famID[$i]}{'01'}{$CNV_tw{$j}{$key2}} eq "")
						{
						$cn_tw{$famID[$i]}{'01'}{$CNV_tw{$j}{$key2}} = -1;
						}

					if ($cn_tw{$famID[$i]}{'02'}{$CNV_tw{$j}{$key2}} eq "")
						{
						$cn_tw{$famID[$i]}{'02'}{$CNV_tw{$j}{$key2}} = -1;
						}

					#############################################


					####### set missing lod scores to -1 ########	$key1

					if ($lod_par{$famID[$i]}{'31'}{$CNV_par{$j}{$key1}} eq "")
						{
						$lod_par{$famID[$i]}{'31'}{$CNV_par{$j}{$key1}} = -1;
						}

					if ($lod_par{$famID[$i]}{'41'}{$CNV_par{$j}{$key1}} eq "")
						{
						$lod_par{$famID[$i]}{'41'}{$CNV_par{$j}{$key1}} = -1;
						}

					#############################################
					####### set missing lod scores to -1 ########	$key2

					if ($lod_tw{$famID[$i]}{'01'}{$CNV_tw{$j}{$key2}} eq "")
						{
						$lod_tw{$famID[$i]}{'01'}{$CNV_tw{$j}{$key2}} = -1;
						}

					if ($lod_tw{$famID[$i]}{'02'}{$CNV_tw{$j}{$key2}} eq "")
						{
						$lod_tw{$famID[$i]}{'02'}{$CNV_tw{$j}{$key2}} = -1;
						}

					#############################################

                                        ###################### assign temporary CN-value to missing twin if co-twin is not missing #########################

                                        $cn_01 = $cn_tw{$famID[$i]}{'01'}{$CNV_tw{$j}{$key2}};
                                        $cn_02 = $cn_tw{$famID[$i]}{'02'}{$CNV_tw{$j}{$key2}};

                                        if (($cn_tw{$famID[$i]}{'01'}{$CNV_tw{$j}{$key2}} != -1) && ($cn_tw{$famID[$i]}{'02'}{$CNV_tw{$j}{$key2}} == -1))
                                                   {
                                                   $cn_02 = $cn_tw{$famID[$i]}{'01'}{$CNV_tw{$j}{$key2}};
                                                   }
					
                                        if (($cn_tw{$famID[$i]}{'01'}{$CNV_tw{$j}{$key2}} == -1) && ($cn_tw{$famID[$i]}{'02'}{$CNV_tw{$j}{$key2}} != -1))
                                                   {
                                                   $cn_01 = $cn_tw{$famID[$i]}{'02'}{$CNV_tw{$j}{$key2}};
                                                   }

                                        ####################################################################################################################

						$denovo = denovo($cn_par{$famID[$i]}{'31'}{$CNV_par{$j}{$key1}},$cn_par{$famID[$i]}{'41'}{$CNV_par{$j}{$key1}},$cn_01,$cn_02);

                                        if ($denovo == 1)
                                               	{
                                                	$start = max($CNVstart_par{$j}{$key1},$CNVstart_tw{$j}{$key2});
						   	$end = min($CNVend_par{$j}{$key1},$CNVend_tw{$j}{$key2});
						   	$size = $end - $start;

                                                	print OUT "$famID[$i]\t";
						   	print OUT "$j\t";
						   	print OUT "$start\t";
						   	print OUT "$end\t";
						   	print OUT "$size\t";
						   	print OUT "$cn_tw{$famID[$i]}{'01'}{$CNV_tw{$j}{$key2}}\t";
						   	print OUT "$lod_tw{$famID[$i]}{'01'}{$CNV_tw{$j}{$key2}}\t";
						   	print OUT "$cn_tw{$famID[$i]}{'02'}{$CNV_tw{$j}{$key2}}\t";
						   	print OUT "$lod_tw{$famID[$i]}{'02'}{$CNV_tw{$j}{$key2}}\t";
						   	print OUT "$cn_par{$famID[$i]}{'31'}{$CNV_par{$j}{$key1}}\t";
						   	print OUT "$lod_par{$famID[$i]}{'31'}{$CNV_par{$j}{$key1}}\t";
						   	print OUT "$cn_par{$famID[$i]}{'41'}{$CNV_par{$j}{$key1}}\t";
						   	print OUT "$lod_par{$famID[$i]}{'41'}{$CNV_par{$j}{$key1}}\n";
                                           	}
                                 	}
                        	}
			}
		}
	}


