Commits

Anonymous committed dc11494

Bug fixes and removing unused code.

Comments (0)

Files changed (5)

 	echo "<script>";
 	foreach($delFiles as $file) {
 		$classArray = explode("/", $file);
-		$myClass = substr($classArray[2], 0, -4);
+		$myClassArray = explode('.', $classArray[2]);
+		$myClass = $myClassArray[0];
 		echo "$(\".$myClass\").html('');";
 		unlink($file);
 		$relations = file_get_contents('temp/' . $classArray[1] . '/relations.txt');
 	if (is_file('temp/' . $classArray[1] . '/relations.txt') == true) {
 		$relations = file_get_contents('temp/' . $classArray[1] . '/relations.txt');
 		$relationsArray=explode("~", $relations);
-		echo "var colorArray = new Array('blue', 'orange', 'green', '#336633', '#000000', '#FF9900', '#999900','#c2374c', '#CC9933', '#0000cc', '#336633', '#000000', '#FF9900', '#999900','#c2374c', '#CC9933', '#0000cc', '#336633', '#000000', '#FF9900', '#999900');
+		array_pop($relationsArray);
+		echo "var colorArray = new Array('rgba(20,83,154, .8)', 'rgba(154,110,9, .8)', 'rgba(29,142,17, .8)', 'rgba(100,20,162, .8)', 'rgba(0,0,0, .8)', 'rgba(153,0,0, .8)', 'rgba(168,168,8, .8)');
 		var c = -1;
 		var canvas = document.getElementById('relationsCanvas');
 		var context = canvas.getContext('2d');
 			echo $relation;
 			echo "
 				c++;
+				if(c == 7) {
+					c=0;	
+				}
 				var figPos = $('.' + jq(relArray[0])).offset();
 				var len = relArray.length;
 				var title = relArray[0] + ': ';
 <?php
-//error_reporting(0);
 $username = $_POST['userID'];
 if(is_dir("temp/" . $username) == false | $username == '') {
 	echo "<script> window.alert(\"ID does not match any sessions\");
-		$('#start').css('display', 'none');";
+	if(get_cookie('rcircostoken') != '') {
+		forgetCookie();
+	}
+	$('#start').css('display', 'none');";
 	exit;
 }
 $outDir="temp/" . $username ."/";
-	$illegal = array('/', '\\', ' ', '(', ')', "|", '~', "'", '"', "?", "#", "$", "%", "&", ",", "!", "@", "^", "*", ";", "[", "]", "{", "}", "<",">","+" );
+	$illegal = array(':', '|','/', '\\', '(', ')', '~', "'", '"', "?", "#", "$", "%", "&", ",", "!", "@", "^", "*", ";", "[", "]", "{", "}", "<",">","+", "-", " ");
 if($_FILES["file1"]["tmp_name"]=='') {
 	$file1 = '';
 } else {
 	$c++;
 }
 $c = 0;
-$fileConnectArray = array();
 $geneFiles = array();
 $linkFiles = array();
 $heatmapFiles = array();
 $lineScatFiles = array();
 $tileFiles = array();
 $n1 = 0;
-foreach (glob($outDir . '*') as $allfile1) {
+$files = glob($outDir . '*');
+usort($files, function($a, $b) {
+	return filemtime($b) < filemtime($a);
+});
+foreach ($files as $allfile1) {
 	if(substr($allfile1, strlen($username) + 6) != 'hist' & substr($allfile1, strlen($username) + 6) != 'relations.txt' & substr($allfile1, strlen($username)+6, -6) != 'zzzzzzz' & substr($allfile1, strlen($username)+6, -6) != 'zzzzzz') {
 		$n1 += 1;
 	}
 $canvasNum *= 80;
 echo "<table id='fileManager' width=\"400\" align=\"center\" cellpadding='3' cellspacing='2' style='border: 1px solid #CCCCCC;background-color:#DEEBDC; '>
 		<tr><td>&nbsp;</td><td>Filename</td><td>Date uploaded</td><td>Filesize (KB)</td><td rowspan=$rowNum><canvas width='300' height='$canvasNum' id='relationsCanvas'></canvas></td></tr>";
-foreach (glob($outDir . '*') as $allfile1) {
+foreach ($files as $allfile1) {
 	if(substr($allfile1, strlen($username) + 6) != 'hist' & substr($allfile1, strlen($username) + 6) != 'relations.txt' & substr($allfile1, strlen($username)+6, -6) != 'zzzzzzz' & substr($allfile1, strlen($username)+6, -6) != 'zzzzzz') {
 		$time = filemtime($allfile1);
-		$class = substr($allfile1, 6 + strlen($username), -4);
+		$class = substr($allfile1, 6 + strlen($username));
+		$classExplode = explode(".", $class);
+		$class = $classExplode[0];
 		echo "<tr style='display: table-row'><td height='70' class='". $class ."'><input id='delList[]' type='checkbox' value=" .  $allfile1. "
 				name='delList[]'></input></td>";
 		echo "<td class='". $class ."'>" . substr($allfile1, strlen($username) + 6) . "</td>";
-		echo "<td class='". $class ."'>" .date(j, $time). "/". date(n, $time). "/". date(y,$time). "</td>";
+		echo "<td class='". $class ."'>" .date(n, $time). "/". date(j, $time). "/". date(y,$time). "</td>";
 		echo "<td id='".$class."' class='". $class ."'>" . round(filesize($allfile1)/1024, 1) . "</td>";
 		if (empty($images[$c]) == false) {
-			$imgClass = substr($images[$c], 11 + strlen($username), -4);
+			$imgClass = substr($images[$c], 11 + strlen($username));
+			$imgExplode = explode(".", $imgClass);
+			$imgClass = $imgExplode[0];
 			if(substr($images[$c], -3) == 'pdf') {
-				echo "<td></td><td><a id='$images[c]' class='$imgClass' href='$images[$c]' target='_blank'>Download</a>";
+				echo "<td></td><td><a id='$images[$c]' class='$imgClass' href='$images[$c]' target='_blank'>Download</a>";
 			} else {
-				echo "<td></td><td>" . "<a id='$images[$c]' class='$imgClass' href='$images[$c]' target='_blank'><img align='center' src='". $images[$c] ."' height='40' width='40'></a>";
+				echo "<td></td><td><a id='$images[$c]' class='$imgClass' href='$images[$c]' target='_blank'><img align='center' src='". $images[$c] ."' height='40' width='40'></a>";
 			}
 		}
 		echo "</tr>";
 		$q=FALSE;
-		if('txt' == substr($allfile1, -3)) {
 		$fh = fopen($allfile1, 'r');
-		$data = fgetcsv($fh, "\t");
-		$data2 = explode("\t", $data[0]);
-		if($data2[3] == 'Gene') {
-			$geneFiles[$c] = $allfile1;
-		} elseif ($data2[3] == 'GeneName') {
-			$heatmapFiles[$c] = $allfile1;
-		} elseif ($data2[3] == 'Data') {
-			$histogramFiles[$c] = $allfile1;
-		} elseif ($data2[3] == 'num.mark') {
-			$lineScatFiles[$c] = $allfile1;
-		} elseif (empty($data2[3]) && $data2[0] == 'Chromosome') {
-			$tileFiles[$c] = $allfile1;
-		} elseif (substr($data2[3], 0, 11) == 'Chromosome.') {
-			$linkFiles[$c] = $allfile1;
-		}
+		if('txt' == substr($allfile1, -3)) {
+			$data = fgetcsv($fh, "\t");
+			$data2 = explode("\t", $data[0]);
+			if($data2[3] == 'Gene') {
+				$geneFiles[$c] = $allfile1;
+			} elseif ($data2[3] == 'GeneName') {
+				$heatmapFiles[$c] = $allfile1;
+			} elseif ($data2[3] == 'Data') {
+				$histogramFiles[$c] = $allfile1;
+			} elseif ($data2[3] == 'num.mark') {
+				$lineScatFiles[$c] = $allfile1;
+			} elseif (empty($data2[3]) && $data2[0] == 'Chromosome') {
+				$tileFiles[$c] = $allfile1;
+			} elseif (substr($data2[3], 0, 11) == 'Chromosome.') {
+				$linkFiles[$c] = $allfile1;
+			}
 		} else {
-			$fh = fopen($allfile1, 'r');
 			$data = fgetcsv($fh, ",");
 			if($data[3] == 'Gene') {
 				$geneFiles[$c] = $allfile1;
 			}
 		}
 		$c++;
-	} else if (substr($allfile1, strlen($username)+6, -6) == 'zzzzzzz' | substr($allfile1, strlen($username)+6, -6) == 'zzzzzz' | $allfile1 == 'hist') {
+	} 
+}
+foreach($files as $allfile1) {
+	if (substr($allfile1, strlen($username)+6, -6) == 'zzzzzzz' | substr($allfile1, strlen($username)+6, -6) == 'zzzzzz' | $allfile1 == 'hist') {
 		if (empty($images[$c]) == false) {
-			echo $seed2;
-			$imgClass = substr($images[$c], 11 + strlen($username), -4);
-			echo "<tr><td></td><td></td><td></td><td></td><td></td><td>" . "<a id='$images[$c]' class='$imgClass' href='$images[$c]' target='_blank'><img align='center' src='". $images[$c] ."' height='40' width='40'></a></tr>";
+			$imgClass = substr($images[$c], 11 + strlen($username));
+			$imgExplode = explode(".", $imgClass);
+			$imgClass = $imgExplode[0];
+			if(substr($images[$c], -3) == 'pdf') {
+				echo "<tr height='70'><td></td><td></td><td></td><td></td><td></td><td><a id='$images[$c]' class='$imgClass' href='$images[$c]' target='_blank'>Download</a></td></tr>";
+			} else {
+				echo "<tr height='70'><td></td><td></td><td></td><td></td><td></td><td>" . "<a id='$images[$c]' class='$imgClass' href='$images[$c]' target='_blank'><img align='center' src='". $images[$c] ."' height='40' width='40'></a></td></tr>";
+			}
 		}
-	$c++;
+			$c++;
 	}
 }
 $histScript = '';
 		$linkScript .= "<option value='$file' selected='selected'>$filename</option>";
 	}
 }
-$script ="<script>var colorArray = new Array('blue', 'orange', 'green', '#336633', '#000000', '#FF9900', '#999900','#c2374c', '#CC9933', '#0000cc', '#336633', '#000000', '#FF9900', '#999900','#c2374c', '#CC9933', '#0000cc', '#336633', '#000000', '#FF9900', '#999900');
+$script ="<script>var colorArray = new Array('rgba(20,83,154, .8)', 'rgba(154,110,9, .8)', 'rgba(29,110,17, .8)', 'rgba(100,20,162, .8)', 'rgba(0,0,0, .8)', 'rgba(100,0,0, .8)', 'rgba(168,168,8, .8)');
 		var c = -1;";
 if (is_file('temp/' . $username . '/relations.txt') == true) {
 	$relations = file_get_contents('temp/' . $username . '/relations.txt');
 	$relationsArray=explode("~", $relations);
+	array_pop($relationsArray);
 	foreach ($relationsArray as $relation) {
 		$script .= $relation;
 		$script .= "
 				c++;
+				if(c == 7) {
+					c = 0;
+				}
 				var figPos = $('.' + jq(relArray[0])).offset();
 				var len = relArray.length;
 				var title = relArray[0] + ': ';
 
 </script>
 <script type="text/javascript">
-Array.prototype.remove = function() {
-    var what, a = arguments, L = a.length, ax;
-    while (L && this.length) {
-        what = a[--L];
-        while ((ax = this.indexOf(what)) !== -1) {
-            this.splice(ax, 1);
-        }
-    }
-    return this;
-};
-
 function cookieAjax() {
 	return 		$.ajax({
 		type: "POST",
 		promise.success(function (data) {
 			$('#seed_div').html(data);
 		});
-//		var dis = document.getElementById('userID');
-//		var token = get_cookie('rcircostoken');
-//		dis.type = "hidden";
-//		dis.value = token;
-//		dis = document.getElementById('username');
-//		dis.value = token;
-//		$("#ID").html(token);
-//		$("#cookie").html("<button type='button' onclick='Javascript: forgetCookie();'>Forget Cookie</button>");
 	}
 	var deloptions = {
 			target:			'#delete_div',
  * plot name to prevent errors
  */
 function fixName() {
-	var illegal = new Array('|','/', '\\', '(', ')', '.', '~', "'", '"', "?", "#", "$", "%", "&", ",", "!", "@", "^", "*", ";", "[", "]", "{", "}", "<",">","+" );
+	var illegal = new Array(':', '|','/', '\\', '(', ')', '.', '~', "'", '"', "?", "#", "$", "%", "&", ",", "!", "@", "^", "*", ";", "[", "]", "{", "}", "<",">","+", "-", " ");
 	var name = $('#plotName').val();
   	var error = false;
-	for(var i = 0; i<26; i++) {
+  	length = illegal.length;
+	for(var i = 0; i<length; i++) {
 		var charExists = (name.indexOf(illegal[i]) >= 0);
 		if(charExists) {
 			error = true;
 	}
 }
 /*
- * Draws a line given start and stop coordinates
+ * Draws a curved given start and stop coordinates
  */
 function DrawLine(x1, y1, x2, y2, color) {
 	var canvas = document.getElementById('relationsCanvas');
 </form>
 
 <form id="circosForm" name="circosForm" method="post" action="rcircos_action.php" enctype="multipart/form-data" style="display: none">
-<!-- 
-Initialize table
- -->
 <table width="800" align="center" cellpadding='3' cellspacing='2' style='border: 1px solid #CCCCCC;background-color:#DEEBDC; '>
   <tr>
     <td width="1"><input name="username" type="hidden" id="username"></td>
 	 -->
 			<tr>
 				<td>&nbsp;</td>
+				<td>&nbsp;</td>
 				<td><strong>File Type:</strong><select name='fileType' id='fileType'>
 						<option value="png" >png</option>
 						<option value="jpeg" >jpeg</option>
 						<option value="pdf">pdf</option>
 				</select>
 				 </td>
-				<td nowrap="nowrap"><div align="left"><strong>Eliminate spacing</strong><input type="checkbox" name="spacing" id="spacing" checked align="left"></div> </td>
 				<td><a
 					onclick="Javascript:  var dis=document.getElementById('chrInclude'); im = document.getElementById('img_1'); if(dis.style.display == 'block'){ dis.style.display = 'none'; im.src='images/expand.gif'; } else { dis.style.display = 'block'; im.src='images/collapse.gif';};"
 					href="Javascript: void(0);"> Chr: Include <img id="img_1"

rcircos_action.php

 	$linkType = "table";
 } elseif(substr($linkFile, -3) == "csv") {
 	$linkType = "csv";
-} elseif($linkFile != '') {
-	echo "ERROR: data files must be .csv or .txt";
-	exit();
-}
+} 
 if(substr($Track1File, -3) =="txt") {
 	$track1FileType = "table";
 } elseif(substr($Track1File, -3) == "csv") {
 		$track1FileType = "csv";
-} elseif($Track1File !='') {
-	echo "ERROR: data files must be .csv or .txt";
-	exit();
-}
+} 
 if(substr($Track2File, -3) =="txt") {
 	$track2FileType = "table";
 } elseif(substr($Track2File, -3) == "csv") {
 		$track2FileType = "csv";
-} elseif($Track2File != '') {
-	echo "ERROR: data files must be .csv or .txt";
-	exit();
-}
+} 
 if(substr($Track3File, -3) =="txt") {
 	$track3FileType = "table";
 } elseif(substr($Track3File, -3) == "csv") {
 		$track3FileType = "csv";
-} elseif($Track3File != '') {
-	echo "ERROR: data files must be .csv or .txt";
-	exit();
-}
+} 
 if(substr($Track4File, -3) =="txt") {
 	$track4FileType = "table";
 } elseif(substr($Track4File, -3) == "csv") {
 		$track4FileType = "csv";
-} elseif($Track4File != '') {
-	echo "ERROR: data files must be .csv or .txt";
-	exit();
 }
 if(substr($Track5File, -3) =="txt") {
 	$track5FileType = "table";
 //echo "<pre>" . print_r($_FILES, true) . "</pre>";
 //echo "<pre>" . print_r($_POST, true) . "</pre>";
 $username = $_POST['username'];
-$spacing = $_POST['spacing'];
 $chrList = $_POST['chrList'];
 $missingChrs = array();
 $i = 0;
 linkNumber <- 0;
 c <- 0;
 probe <- F;
-if('$spacing' != '') {
 	if('$geneFile' =='') {
 		c <- c-3
 		probe <- T;
 		linkNumber <- c;
-	}
-	for( i in 1:5) {
-		TrackType <- TrackTypes[i];
-		TrackFile <- TrackFiles[i];
-		FileType <- FileTypes[i];
-		if(TrackType == "Heatmap" & TrackFile !='') {
-		c <- c+1;
-			if(FileType == "table") {
-				TrackData <- read.table(TrackFile, sep="\t", quote="", head=T);
-			} else {
-				TrackData <- read.csv(TrackFile, sep=",", quote="", head=T);
-			}
-			RCircos.Heatmap.Plot(TrackData, 6, c+3, "in");
-			linkNumber <- c;
-		} else if(TrackType == "Histogram" & TrackFile!='') {
-		c <- c+1;
-		
-			if(FileType == "table") {
-				TrackData <- read.table(TrackFile, sep="\t", quote="", head=T);
-			} else {
-				TrackData <- read.csv(TrackFile, sep=",", quote="", head=T);
-			}
-			RCircos.Histogram.Plot(TrackData, 4, c+3, "in");
-			linkNumber <- c;
-		} else if(TrackType == "Line" & TrackFile !='') {
-		c <- c+1;
-			if(FileType == "table") {
-				TrackData <- read.table(TrackFile, sep="\t", quote="", head=T);
-			} else {
-				TrackData <- read.csv(TrackFile, sep=",", quote="", head=T);
-			}
-			RCircos.Line.Plot(TrackData, 5, c+3, "in");
-			linkNumber <- c;
-		} else if(TrackType == "Scatter" & TrackFile !='') {
-		c <- c+1;
-			if(FileType == "table") {
-				TrackData <- read.table(TrackFile, sep="\t", quote="", head=T);
-			} else {
-				TrackData <- read.csv(TrackFile, sep=",", quote="", head=T);
-			}
-			RCircos.Scatter.Plot(TrackData, 5, c+3, "in", 1);
-			linkNumber <- c;
-		} else if(TrackType == "Tile" & TrackFile !='') {
-		c <- c+1;
-			if(FileType == "table") {
-				TrackData <- read.table(TrackFile, sep="\t", quote="", head=T);
-			} else {
-				TrackData <- read.csv(TrackFile, sep=",", quote="", head=T);
-			}
-			RCircos.Tile.Plot(TrackData, c+3, "in");
-			linkNumber <- c;
-		} 
-	}
-} else {
-	for( i in 1:5) {
-		TrackType <- TrackTypes[i];
-		TrackFile <- TrackFiles[i];
-		if(TrackType == "Heatmap" & TrackFile !='') {
-			if(FileType == "table") {
-				TrackData <- read.table(TrackFile, sep="\t", quote="", head=T);
-			} else {
-				TrackData <- read.csv(TrackFile, sep=",", quote="", head=T);
-			}
-			RCircos.Heatmap.Plot(TrackData, 6, i + 3, "in");
-			linkNumber <- i;
-		} else if(TrackType == "Histogram" & TrackFile!='') {
-			if(FileType == "table") {
-				TrackData <- read.table(TrackFile, sep="\t", quote="", head=T);
-			} else {
-				TrackData <- read.csv(TrackFile, sep=",", quote="", head=T);
-			}
-			RCircos.Histogram.Plot(TrackData, 4, i+3, "in");
-			linkNumber <- i;
-		} else if(TrackType == "Line" & TrackFile !='') {
-			if(FileType == "table") {
-				TrackData <- read.table(TrackFile, sep="\t", quote="", head=T);
-			} else {
-				TrackData <- read.csv(TrackFile, sep=",", quote="", head=T);
-			}
-			RCircos.Line.Plot(TrackData, 5, i+3, "in");
-			linkNumber <- i;
-		} else if(TrackType == "Scatter" & TrackFile !='') {
-			if(FileType == "table") {
-				TrackData <- read.table(TrackFile, sep="\t", quote="", head=T);
-			} else {
-				TrackData <- read.csv(TrackFile, sep=",", quote="", head=T);
-			}
-			RCircos.Scatter.Plot(TrackData, 5, i+3, "in", 1);
-			linkNumber <- i;
-		} else if(TrackType == "Tile" & TrackFile !='') {
-			if(FileType == "table") {
-				TrackData <- read.table(TrackFile, sep="\t", quote="", head=T);
-			} else {
-				TrackData <- read.csv(TrackFile, sep=",", quote="", head=T);
-			}
-			RCircos.Tile.Plot(TrackData, i+3, "in");
-			linkNumber <- i;
-		} 
-	}
+}
+for( i in 1:5) {
+	TrackType <- TrackTypes[i];
+	TrackFile <- TrackFiles[i];
+	FileType <- FileTypes[i];
+	if(TrackType == "Heatmap" & TrackFile !='') {
+	c <- c+1;
+		if(FileType == "table") {
+			TrackData <- read.table(TrackFile, sep="\t", quote="", head=T);
+		} else {
+			TrackData <- read.csv(TrackFile, sep=",", quote="", head=T);
+		}
+		RCircos.Heatmap.Plot(TrackData, 6, c+3, "in");
+		linkNumber <- c;
+	} else if(TrackType == "Histogram" & TrackFile!='') {
+	c <- c+1;
+	
+		if(FileType == "table") {
+			TrackData <- read.table(TrackFile, sep="\t", quote="", head=T);
+		} else {
+			TrackData <- read.csv(TrackFile, sep=",", quote="", head=T);
+		}
+		RCircos.Histogram.Plot(TrackData, 4, c+3, "in");
+		linkNumber <- c;
+	} else if(TrackType == "Line" & TrackFile !='') {
+	c <- c+1;
+		if(FileType == "table") {
+			TrackData <- read.table(TrackFile, sep="\t", quote="", head=T);
+		} else {
+			TrackData <- read.csv(TrackFile, sep=",", quote="", head=T);
+		}
+		RCircos.Line.Plot(TrackData, 5, c+3, "in");
+		linkNumber <- c;
+	} else if(TrackType == "Scatter" & TrackFile !='') {
+	c <- c+1;
+		if(FileType == "table") {
+			TrackData <- read.table(TrackFile, sep="\t", quote="", head=T);
+		} else {
+			TrackData <- read.csv(TrackFile, sep=",", quote="", head=T);
+		}
+		RCircos.Scatter.Plot(TrackData, 5, c+3, "in", 1);
+		linkNumber <- c;
+	} else if(TrackType == "Tile" & TrackFile !='') {
+	c <- c+1;
+		if(FileType == "table") {
+			TrackData <- read.table(TrackFile, sep="\t", quote="", head=T);
+		} else {
+			TrackData <- read.csv(TrackFile, sep=",", quote="", head=T);
+		}
+		RCircos.Tile.Plot(TrackData, c+3, "in");
+		linkNumber <- c;
+	} 
 }
 if('$geneFile' == '' & linkNumber == 0 & '$linkFile' != '' & probe == F) {
 	if("$linkType" == "table") {
 	html = html + \"<option value='$circosPlot'>$fileName.$fileType</option>\";
 	$('#historySelect').html(html);
 } else {
-	html = \"History:(month:day:hour:minute:second)<select name='historySelect' id='historySelect' onchange='Javascript: histUpdate();'><option value='none'>No option selected</option><option value='$circosPlot'>$fileName.$fileType;</option>\"
+	html = \"History:(month:day:hour:minute:second)<select name='historySelect' id='historySelect' onchange='Javascript: histUpdate();'><option value='none'>No option selected</option><option value='$circosPlot'>$fileName.$fileType</option>\"
 	$('#history').html(html);
 }
 
 	html = html + \"<option value='$circosPlot'>$fileName.$fileType</option>\";
 	$('#historySelect').html(html);
 } else {
-	html = \"History:(month:day:hour:minute:second)<select name='historySelect' id='historySelect' onchange='Javascript: histUpdate();'><option value='none'>No option selected</option><option value='$circosPlot'>$fileName.$fileType;</option>\"
+	html = \"History:(month:day:hour:minute:second)<select name='historySelect' id='historySelect' onchange='Javascript: histUpdate();'><option value='none'>No option selected</option><option value='$circosPlot'>$fileName.$fileType</option>\"
 	$('#history').html(html);
 }
 

rcircos_help.html

 <p><a href="rcircos_workflow.html">Step by step instructions</a></p>
 <p>Test Data: <a href="rcircos_test_data.zip">Download</a></p>
 <a name="geneLabels" id="geneLabels"></a>
-<p><strong>Gene Label Data</strong> <br>
+<p><strong>Gene Label Data</strong><br>
 </p>
 <table cellspacing="3" cellpadding="3">