Jump to content
  • Revista PROGRAMAR: Já está disponível a edição #60 da revista programar. Faz já o download aqui!

diokhan

grafico com tamanho dinamico

Recommended Posts

diokhan

boas, eu tenho este código que faz um gráfico em GD:

function GraphPatent($id)
	{
		try {
		    $stmt = $this->dbh->prepare("SELECT B.Q_START_BLAST, B.Q_END_BLAST, B.EVALUE,
		    							B.ACCESSION_ID, P.LENGTH_PROTEIN FROM PROTEIN AS P
										Inner Join BLAST AS B ON B.ID_PROTEIN = P.ID_PROTEIN
										Inner Join BLAST_NAME_DB AS BN ON BN.ID_BLAST_DB = B.ID_BLAST_DB
										WHERE P.ID_PROTEIN = :id AND BN.DESCRIPTION LIKE '%pat%'
										LIMIT 0, 20");
			$stmt->bindParam(':id', $id);
		    $stmt->execute();

		} catch (PDOException $e) {
			return -1;
		    echo 'Query error: ' . $e->getMessage();
		}

		$count = $stmt->rowCount();
       	$stmt->closeCursor();

       	if (empty($count))
       	{
       		return 0;
       		exit;
       	}else{

       		$stmt2 = $this->dbh->prepare("SELECT P.LENGTH_PROTEIN FROM PROTEIN AS P WHERE P.ID_PROTEIN = :id");
       		$stmt2->bindParam(':id', $id);
		    $stmt2->execute();

		    $result = $stmt2->fetch(PDO::FETCH_BOTH);
       		// altura e largura da imagem
       		$iw = 800;
			$ih = $count * 35 + 55;
			// margem geral da imagem
			$gm = 20;
			// escala da timeline em px
			$ts = 40;


			// escala de referencia
			$scale = 20;
			// factor de diferenca entre escala em px e escala de referencia
			$fscale = 2;
			// escala maxima de referencia
			$mscale = ceil($result['LENGTH_PROTEIN']) + 40;

		    // fontes
			$fonts['arial'] = './Fonts/arial.ttf';
			$fonts['tahoma'] = './Fonts/tahoma.ttf';

			// cria a imagem
			$img = imagecreatetruecolor($iw, $ih);

			// define as cores
			$colors2['white'] = imagecolorallocate($img, 255, 255, 255); // white background graph
			$colors2['grey'] = imagecolorallocate($img, 235, 235, 235); // grey back graph
			$colors['black'] = imagecolorallocate($img, 0, 0, 0);
			$colors['blue'] = imagecolorallocate($img, 16, 78, 139);
			$colors['green'] = imagecolorallocate($img, 0, 128, 0);
			$colors['grey'] = imagecolorallocate($img, 139, 139, 131);
			$colors['red'] = imagecolorallocate($img, 205, 0, 0);

			$radius = 3;
			$rad = 20;
			$drawGraph = new Graphs;

			// preenche o background
			imagefilledrectangle($img, 0, 0, $iw, $ih, $colors2['grey']);
			$graphDraw = $drawGraph->imagefillroundedrect($img, 0, 0, $iw, $ih, $rad, $colors2['white']);

			// preenche a linha principal da timeline
			imagefilledrectangle($img, $gm, $gm, $iw-$mscale, $gm+1, $colors['black']);

			// preenche a escala da timeline
			$x = $gm;
			$s = 0;
			while($s <= ($mscale))
			{
				imagefilledrectangle($img, $x, $gm, $x+1, $gm+7, $colors['black']);
				if ($s < 10)
					$tmargin = $x-1;
				elseif ($s < 100)
					$tmargin = $x-3;
				else
					$tmargin = $x-6;
				imagefttext($img, 8, 0, $tmargin, $gm+20, $colors['red'], $fonts['tahoma'], $s);
				$s = $s+$scale;
				$x = $x+$ts;
			}

       	// busca valores do blast patenteado
       		try
			{
			    $stmt2 = $this->dbh->prepare("SELECT B.Q_START_BLAST, B.Q_END_BLAST, B.EVALUE,
			    							B.ACCESSION_ID FROM PROTEIN AS P
											Inner Join BLAST AS B ON B.ID_PROTEIN = P.ID_PROTEIN
											Inner Join BLAST_NAME_DB AS BN ON BN.ID_BLAST_DB = B.ID_BLAST_DB
											WHERE P.ID_PROTEIN = :id AND BN.DESCRIPTION LIKE '%pat%'
											LIMIT 0, 20");
				$stmt2->bindParam(':id', $id);
			    $stmt2->execute();
			} catch (PDOException $e) {
				return -1;
			    echo 'Query error: ' . $e->getMessage();
			}

			$res2 = $stmt2->fetchAll(PDO::FETCH_BOTH);
    		$graphPat = array();
    		$j = 0;
    		foreach( $res2 as $row )
		    {
				$graphPat[$j]['start'] = $row["Q_START_BLAST"];
				$graphPat[$j]['end'] = $row["Q_END_BLAST"];
				$graphPat[$j]['label1'] = $row["ACCESSION_ID"];
				$graphPat[$j]['label2'] = $row["EVALUE"];
				if ($row["EVALUE"] <= 1e-20){
					$graphPat[$j]['color'] = $colors['red'];
				}else{
					$graphPat[$j]['color'] = $colors['blue'];
				}
				$j++;
			}

			$x = 50;
			foreach ($graphPat as $b)
			{
				// posicao texto inicio
				if ($b['start'] < 10){
					$tsmargin = -7;
				}elseif ($b['start'] < 100){
					$tsmargin = -12;
				}else{
					$tsmargin = -17;
				}
				// posicao texto fim
				if ($b['end'] < 10){
					$temargin = 4;
				}elseif ($b['end'] < 100){
					$temargin = 4;
				}else{
					$temargin = 4;
				}

				// grafico
				$graphDraw = $drawGraph->imagefillroundedrect($img, $gm+($b['start']*$fscale), $gm+$x, $gm+($b['end']*$fscale), $gm+$x+12, $radius, $b['color']);
				//imagefilledrectangle($img, $gm+($b['start']*$fscale), $gm+$x, $gm+($b['end']*$fscale), $gm+$x+12, $b['color']);
				// texto inicio
				imagefttext($img, 8, 0, $gm+($b['start']*$fscale)+$tsmargin-3, $gm+$x+10, $colors['red'], $fonts['tahoma'], $b['start']);
				// texto fim
				imagefttext($img, 8, 0, $gm+($b['end']*$fscale)+$temargin, $gm+$x+10, $colors['red'], $fonts['tahoma'], $b['end']);
				// label
				imagefttext($img, 8, 0, $gm+($b['start']*$fscale), $x+15, $colors['black'], $fonts['tahoma'], $b['label1']." - (".$b['label2'].")");
				$x=$x+35;
			}

			$rand = mt_rand(1,2147483647); // random
			imagepng($img, 'images/graph/blastPat'.$rand.'.png'); // grava a imagem em png com random
			//imagepng($img, 'images/graph/proteinPatTest.png'); // grava a imagem em png sem random
			imagedestroy($img);  // liberta a imagem da memoria
			return $rand;
		}
	}

mas estou a tentar adaptar para o tamanho do gráfico e da escala seja dinâmico, conforme o tamanho da sequência, que vou buscar a tabela, alguém pode dar uma ajuda ou dicas de como o devo fazer? 🤔


...Join the dark side...and get a free cookie...

Share this post


Link to post
Share on other sites
diokhan

sei que deve haver outra solução mais simples, mas neste momento o que consegui fazer foi isto:

// escala da timeline em px
			if (ceil($result[0]) < 200){
				$ts = 70;
			}elseif (ceil($result[0]) >= 200 && ceil($result[0]) < 300){
				$ts = 50;
			}elseif (ceil($result[0]) >= 300 && ceil($result[0]) < 400){
				$ts = 35;
			}elseif (ceil($result[0]) >= 400 && ceil($result[0]) < 500){
				$ts = 70;
			}elseif (ceil($result[0]) >= 500 && ceil($result[0]) < 600){
				$ts = 58.4;
			}elseif (ceil($result[0]) >= 600 && ceil($result[0]) < 700){
				$ts = 50;
			}elseif (ceil($result[0]) >= 700 && ceil($result[0]) < 800){
				$ts = 43.8;
			}elseif (ceil($result[0]) >= 800 && ceil($result[0]) < 900){
				$ts = 38.9;
			}elseif (ceil($result[0]) >= 900 && ceil($result[0]) < 1000){
				$ts = 70;
			}elseif (ceil($result[0]) >= 1000 && ceil($result[0]) < 1100){
				$ts = 63.8;
			}elseif (ceil($result[0]) >= 1100 && ceil($result[0]) < 1400){
				$ts = 50;
			}elseif (ceil($result[0]) >= 1400){
				$ts = 35;
			}

			// escala de referencia
        		if (ceil($result[0]) < 200){
				$scale = 20;
			}elseif (ceil($result[0]) >= 200 && ceil($result[0]) < 300){
				$scale = 20;
			}elseif (ceil($result[0]) >= 300 && ceil($result[0]) < 400){
				$scale = 20;
			}elseif (ceil($result[0]) >= 400 && ceil($result[0]) < 500){
				$scale = 50;
			}elseif (ceil($result[0]) >= 500 && ceil($result[0]) < 600){
				$scale = 50;
			}elseif (ceil($result[0]) >= 600 && ceil($result[0]) < 700){
				$scale = 50;
			}elseif (ceil($result[0]) >= 700 && ceil($result[0]) < 800){
				$scale = 50;
			}elseif (ceil($result[0]) >= 800 && ceil($result[0]) < 900){
				$scale = 50;
			}elseif (ceil($result[0]) >= 900 && ceil($result[0]) < 1000){
				$scale = 100;
			}elseif (ceil($result[0]) >= 1000 && ceil($result[0]) < 1100){
				$scale = 100;
			}elseif (ceil($result[0]) >= 1100 && ceil($result[0]) < 1400){
				$scale = 100;
			}elseif (ceil($result[0]) >= 1400){
				$scale = 100;
			}

			// factor de diferenca entre escala em px e escala de referencia
        		if (ceil($result[0]) < 200){
				$fscale = 3.5;
			}elseif (ceil($result[0]) >= 200 && ceil($result[0]) < 300){
				$fscale = 2.5;
			}elseif (ceil($result[0]) >= 300 && ceil($result[0]) < 400){
				$fscale = 1.8;
			}elseif (ceil($result[0]) >= 400 && ceil($result[0]) < 500){
				$fscale = 1.4;
			}elseif (ceil($result[0]) >= 500 && ceil($result[0]) < 600){
				$fscale = 1.2;
			}elseif (ceil($result[0]) >= 600 && ceil($result[0]) < 700){
				$fscale = 1;
			}elseif (ceil($result[0]) >= 700 && ceil($result[0]) < 800){
				$fscale = 0.9;
			}elseif (ceil($result[0]) >= 800 && ceil($result[0]) < 900){
				$fscale = 0.8;
			}elseif (ceil($result[0]) >= 900 && ceil($result[0]) < 1000){
				$fscale = 0.7;
			}elseif (ceil($result[0]) >= 1000 && ceil($result[0]) < 1100){
				$fscale = 0.65;
			}elseif (ceil($result[0]) >= 1100 && ceil($result[0]) < 1400){
				$fscale = 0.5;
			}elseif (ceil($result[0]) >= 1400){
				$fscale = 0.35;
			}

			// escala maxima de referencia
        		if (ceil($result[0]) < 200){
				$mscale = 200;
			}elseif (ceil($result[0]) >= 200 && ceil($result[0]) < 300){
				$mscale = 300;
			}elseif (ceil($result[0]) >= 300 && ceil($result[0]) < 400){
				$mscale = 400;
			}elseif (ceil($result[0]) >= 400 && ceil($result[0]) < 500){
				$mscale = 500;
			}elseif (ceil($result[0]) >= 500 && ceil($result[0]) < 600){
				$mscale = 600;
			}elseif (ceil($result[0]) >= 600 && ceil($result[0]) < 700){
				$mscale = 700;
			}elseif (ceil($result[0]) >= 700 && ceil($result[0]) < 800){
				$mscale = 800;
			}elseif (ceil($result[0]) >= 800 && ceil($result[0]) < 900){
				$mscale = 900;
			}elseif (ceil($result[0]) >= 900 && ceil($result[0]) < 1000){
				$mscale = 1000;
			}elseif (ceil($result[0]) >= 1000 && ceil($result[0]) < 1100){
				$mscale = 1100;
			}elseif (ceil($result[0]) >= 1100 && ceil($result[0]) < 1400){
				$mscale = 1400;
			}elseif (ceil($result[0]) >= 1400){
				$mscale = 2000;
			}

se alguém puder dar umas ideias para melhorar o meu código com algum ciclo mais simples aceito opiniões


...Join the dark side...and get a free cookie...

Share this post


Link to post
Share on other sites
diokhan

encontrei uma solução mais simples:

// altura e largura da imagem
		    $iw = 800;
			$ih = $count * 35 + 55;

			// margem geral da imagem
			$gm = 20;

			// escala maxima de referencia
			$mscale = $result[0] + 20;
			//echo "mscale ".$mscale." / ";			

			// escala da timeline em px
			$ts = 70;

			// escala de referencia
			$scale = round($result[0] / 10);
			//echo "scale ".$scale;

			// factor de diferenca entre escala em px e escala de referencia
			if ($result[0] < 400){
				$div = $result[0] + 15;
				$calc = (68.5 /$div) * 11;
			}elseif ($result[0] >= 400 && $result[0] < 1000){
				$div = $result[0] + 80;
				$calc = (68.5 /$div) * 12;
			}elseif ($result[0] >= 1000){
				$div = $result[0] + 80;
				$calc = (68.5 /$div) * 11;
			}
			$fscale = number_format($calc, 1, '.', '');
			//echo " / fscale ".$fscale;

feito por mim, se alguém encontrar erros ou melhorias avisem :thumbsup:


...Join the dark side...and get a free cookie...

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.