/src/Comppi/BuildBundle/Command/GenerateGexfGraphCommand.php

https://github.com/erenon/ComPPI · PHP · 157 lines · 104 code · 35 blank · 18 comment · 4 complexity · b61e3b07f617e73c54a79facd54d53c9 MD5 · raw file

  1. <?php
  2. namespace Comppi\BuildBundle\Command;
  3. use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
  4. use Symfony\Component\Console\Input\InputArgument;
  5. use Symfony\Component\Console\Input\InputInterface;
  6. use Symfony\Component\Console\Input\InputOption;
  7. use Symfony\Component\Console\Output\OutputInterface;
  8. use Doctrine\DBAL\Types\IntegerType as IntegerParameter;
  9. class GenerateGexfGraphCommand extends ContainerAwareCommand
  10. {
  11. /**
  12. * @var Comppi\BuildBundle\Service\GexfWriter\GexfWriter
  13. */
  14. protected $writer;
  15. /**
  16. * @var Doctrine\DBAL\Connection
  17. */
  18. protected $connection;
  19. /**
  20. * @var Comppi\BuildBundle\Service\SpecieProvider\SpecieDescriptor
  21. */
  22. protected $specie;
  23. protected $buildPath;
  24. protected $buildTarget;
  25. protected function configure() {
  26. $this
  27. ->setName('comppi:generate:gexf')
  28. ->addArgument('specie', InputArgument::REQUIRED, 'Abbreviation of species to load')
  29. ;
  30. }
  31. protected function initialize(InputInterface $input, OutputInterface $output) {
  32. $specieAbbr = $input->getArgument('specie');
  33. if (!$specieAbbr) {
  34. throw new \Exception("Please specify a species! Species availabe: ce, dm, hs, sc");
  35. }
  36. $container = $this->getContainer();
  37. $this->writer = $container->get('comppi.build.gexfWriter');
  38. $this->specie = $container
  39. ->get('comppi.build.specieProvider')
  40. ->getSpecieByAbbreviation($specieAbbr);
  41. $this->buildPath = $container->getParameter('comppi.build.buildPath');
  42. $this->buildTarget = $this->buildPath
  43. . DIRECTORY_SEPARATOR
  44. . 'comppi-' . $this->specie->abbreviation . '.gexf';
  45. $this->connection = $container
  46. ->get('doctrine.orm.default_entity_manager')
  47. ->getConnection();
  48. // @TODO this hack is required here because of a PDO bug
  49. // https://bugs.php.net/bug.php?id=44639
  50. $this->connection->getWrappedConnection()
  51. ->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
  52. // avoid memory leak
  53. $this->connection->getConfiguration()->setSQLLogger(null);
  54. $this->checkBuildDir();
  55. }
  56. protected function execute(InputInterface $input, OutputInterface $output) {
  57. $this->writer->open($this->buildTarget);
  58. $this->writer->nodes();
  59. $this->addNodes($output);
  60. $this->writer->edges();
  61. $this->addEdges($output);
  62. $this->writer->close();
  63. }
  64. private function checkBuildDir() {
  65. if (!is_dir($this->buildPath)) {
  66. mkdir($this->buildPath, 0777, true);
  67. }
  68. }
  69. private function addNodes(OutputInterface $output) {
  70. $selectProteins = $this->connection->prepare(
  71. 'SELECT id, proteinName FROM Protein' .
  72. ' WHERE specieId = ? ORDER BY id ASC LIMIT ?, ?'
  73. );
  74. $selectProteins->bindValue(1, $this->specie->id, IntegerParameter::INTEGER);
  75. // init params
  76. $offset = 0;
  77. $blockSize = 1000;
  78. $selectProteins->bindValue(2, $offset, IntegerParameter::INTEGER);
  79. $selectProteins->bindValue(3, $blockSize, IntegerParameter::INTEGER);
  80. $selectProteins->execute();
  81. while ($selectProteins->rowCount() > 0) {
  82. // iterate over rows
  83. $proteins = $selectProteins->fetchAll(\Doctrine\ORM\AbstractQuery::HYDRATE_ARRAY);
  84. foreach ($proteins as $protein) {
  85. $this->writer->addNode($protein['id'], $protein['proteinName']);
  86. }
  87. $output->writeln(' > ' . $selectProteins->rowCount() . ' proteins processed');
  88. // select proteins again
  89. $offset += $blockSize;
  90. $selectProteins->closeCursor();
  91. $selectProteins->bindValue(2, $offset, IntegerParameter::INTEGER);
  92. $selectProteins->execute();
  93. }
  94. }
  95. private function addEdges(OutputInterface $output) {
  96. $selectInteractions = $this->connection->prepare(
  97. 'SELECT actorAId, actorBId FROM Interaction' .
  98. ' LEFT JOIN Protein ON Interaction.actorAId = Protein.id' .
  99. ' WHERE Protein.specieId = ? ORDER BY Interaction.id ASC LIMIT ?, ?'
  100. );
  101. $selectInteractions->bindValue(1, $this->specie->id, IntegerParameter::INTEGER);
  102. // init params
  103. $offset = 0;
  104. $blockSize = 1000;
  105. $selectInteractions->bindValue(2, $offset, IntegerParameter::INTEGER);
  106. $selectInteractions->bindValue(3, $blockSize, IntegerParameter::INTEGER);
  107. $selectInteractions->execute();
  108. while ($selectInteractions->rowCount() > 0) {
  109. // iterate over rows
  110. $interactions = $selectInteractions->fetchAll(\Doctrine\ORM\AbstractQuery::HYDRATE_ARRAY);
  111. foreach ($interactions as $interaction) {
  112. $this->writer->addEdge($interaction['actorAId'], $interaction['actorBId']);
  113. }
  114. $output->writeln(' > ' . $selectInteractions->rowCount() . ' interactions processed');
  115. // select interactions again
  116. $offset += $blockSize;
  117. $selectInteractions->closeCursor();
  118. $selectInteractions->bindValue(2, $offset, IntegerParameter::INTEGER);
  119. $selectInteractions->execute();
  120. }
  121. }
  122. }