From abbceb6cde72282b8b85e9452d45e3d6ecc41da5 Mon Sep 17 00:00:00 2001 From: BonfaceKilz Date: Fri, 7 Aug 2020 15:07:52 +0300 Subject: Move wqflask/tests/api to wqflask/tests/wqflask * wqflask/tests(api): Move all the files here to tests/wqflask. The test dir should mirror the actual module structure --- wqflask/tests/api/__init__.py | 0 wqflask/tests/api/test_gen_menu.py | 407 ----------------------------- wqflask/tests/wqflask/__init__.py | 0 wqflask/tests/wqflask/api/__init__.py | 0 wqflask/tests/wqflask/api/test_gen_menu.py | 407 +++++++++++++++++++++++++++++ 5 files changed, 407 insertions(+), 407 deletions(-) delete mode 100644 wqflask/tests/api/__init__.py delete mode 100644 wqflask/tests/api/test_gen_menu.py create mode 100644 wqflask/tests/wqflask/__init__.py create mode 100644 wqflask/tests/wqflask/api/__init__.py create mode 100644 wqflask/tests/wqflask/api/test_gen_menu.py (limited to 'wqflask') diff --git a/wqflask/tests/api/__init__.py b/wqflask/tests/api/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/wqflask/tests/api/test_gen_menu.py b/wqflask/tests/api/test_gen_menu.py deleted file mode 100644 index 79c77fec..00000000 --- a/wqflask/tests/api/test_gen_menu.py +++ /dev/null @@ -1,407 +0,0 @@ -"""Test cases for wqflask.api.gen_menu""" -import unittest -import mock - -from wqflask.api.gen_menu import gen_dropdown_json -from wqflask.api.gen_menu import get_species -from wqflask.api.gen_menu import get_groups -from wqflask.api.gen_menu import get_types -from wqflask.api.gen_menu import get_datasets -from wqflask.api.gen_menu import phenotypes_exist -from wqflask.api.gen_menu import genotypes_exist -from wqflask.api.gen_menu import build_datasets -from wqflask.api.gen_menu import build_types - - -class TestGenMenu(unittest.TestCase): - """Tests for the gen_menu module""" - - def setUp(self): - self.test_group = { - 'mouse': [ - ['H_T1', - 'H_T', - 'Family:DescriptionA' - ], - ['H_T2', "H_T'", 'Family:None'] - ], - 'human': [ - ['BXD', 'BXD', 'Family:None'], - ['HLC', 'Liver: Normal Gene Expression with Genotypes (Merck)', - 'Family:Test'] - ] - } - - self.test_type = { - 'mouse': { - 'H_T2': [('Phenotypes', - 'Traits and Cofactors', - 'Phenotypes'), - ('Genotypes', - 'DNA Markers and SNPs', - 'Genotypes'), - ['M', 'M', 'Molecular Trait Datasets']], - 'H_T1': [('Phenotypes', - 'Traits and Cofactors', - 'Phenotypes'), - ('Genotypes', - 'DNA Markers and SNPs', - 'Genotypes'), - ['M', 'M', 'Molecular Trait Datasets']] - }, - 'human': { - 'HLC': [('Phenotypes', - 'Traits and Cofactors', - 'Phenotypes'), - ('Genotypes', - 'DNA Markers and SNPs', - 'Genotypes'), - ['M', 'M', 'Molecular Trait Datasets']], - 'BXD': [('Phenotypes', - 'Traits and Cofactors', - 'Phenotypes'), - ('Genotypes', - 'DNA Markers and SNPs', - 'Genotypes'), - ['M', 'M', 'Molecular Trait Datasets']] - } - } - - @mock.patch('wqflask.api.gen_menu.g') - def test_get_species(self, db_mock): - """Test that assertion is raised when dataset and dataset_name - are defined""" - db_mock.db.execute.return_value.fetchall.return_value = ( - ('human', 'Human'), - ('mouse', 'Mouse')) - self.assertEqual(get_species(), - [['human', 'Human'], ['mouse', 'Mouse']]) - db_mock.db.execute.assert_called_once_with( - "SELECT Name, MenuName FROM Species ORDER BY OrderId" - ) - - @mock.patch('wqflask.api.gen_menu.g') - def test_get_groups(self, db_mock): - """Test that species groups are grouped correctly""" - db_mock.db.execute.return_value.fetchall.side_effect = [ - # Mouse - (('BXD', 'BXD', None), - ('HLC', 'Liver: Normal Gene Expression with Genotypes (Merck)', - 'Test')), - # Human - (('H_T1', "H_T", "DescriptionA"), - ('H_T2', "H_T'", None)) - ] - - self.assertEqual(get_groups([["human", "Human"], ["mouse", "Mouse"]]), - self.test_group) - - for name in ["mouse", "human"]: - db_mock.db.execute.assert_any_call( - ("SELECT InbredSet.Name, InbredSet.FullName, " + - "IFNULL(InbredSet.Family, 'None') " + - "FROM InbredSet, Species WHERE Species.Name " + - "= '{}' AND InbredSet.SpeciesId = Species.Id GROUP by " + - "InbredSet.Name ORDER BY IFNULL(InbredSet.FamilyOrder, " + - "InbredSet.FullName) ASC, IFNULL(InbredSet.Family, " + - "InbredSet.FullName) ASC, InbredSet.FullName ASC, " + - "InbredSet.MenuOrderId ASC").format(name) - ) - - @mock.patch('wqflask.api.gen_menu.g') - def test_phenotypes_exist_called_with_correct_query(self, db_mock): - """Test that phenotypes_exist is called with the correct query""" - db_mock.db.execute.return_value.fetchone.return_value = None - phenotypes_exist("test") - db_mock.db.execute.assert_called_with( - "SELECT Name FROM PublishFreeze " - "WHERE PublishFreeze.Name = 'testPublish'" - ) - - @mock.patch('wqflask.api.gen_menu.g') - def test_phenotypes_exist_with_falsy_values(self, db_mock): - """Test that phenotype check returns correctly when given - a None value""" - for x in [None, False, (), [], ""]: - db_mock.db.execute.return_value.fetchone.return_value = x - self.assertFalse(phenotypes_exist("test")) - - @mock.patch('wqflask.api.gen_menu.g') - def test_phenotypes_exist_with_truthy_value(self, db_mock): - """Test that phenotype check returns correctly when given Truthy """ - for x in ["x", ("result"), ["result"], [1]]: - db_mock.db.execute.return_value.fetchone.return_value = (x) - self.assertTrue(phenotypes_exist("test")) - - @mock.patch('wqflask.api.gen_menu.g') - def test_genotypes_exist_called_with_correct_query(self, db_mock): - """Test that genotypes_exist is called with the correct query""" - db_mock.db.execute.return_value.fetchone.return_value = None - genotypes_exist("test") - db_mock.db.execute.assert_called_with( - "SELECT Name FROM GenoFreeze WHERE GenoFreeze.Name = 'testGeno'" - ) - - @mock.patch('wqflask.api.gen_menu.g') - def test_genotypes_exist_with_falsy_values(self, db_mock): - """Test that genotype check returns correctly when given - a None value""" - for x in [None, False, (), [], ""]: - db_mock.db.execute.return_value.fetchone.return_value = x - self.assertFalse(genotypes_exist("test")) - - @mock.patch('wqflask.api.gen_menu.g') - def test_genotypes_exist_with_truthy_value(self, db_mock): - """Test that genotype check returns correctly when given Truthy """ - for x in ["x", ("result"), ["result"], [1]]: - db_mock.db.execute.return_value.fetchone.return_value = (x) - self.assertTrue(phenotypes_exist("test")) - - @mock.patch('wqflask.api.gen_menu.g') - def test_build_datasets_with_type_phenotypes(self, db_mock): - """Test that correct dataset is returned for a phenotype type""" - db_mock.db.execute.return_value.fetchall.return_value = ( - (602, "BXDPublish", "BXD Published Phenotypes"), - ) - self.assertEqual(build_datasets("Mouse", "BXD", "Phenotypes"), - [['602', "BXDPublish", "BXD Published Phenotypes"]]) - db_mock.db.execute.assert_called_with( - "SELECT InfoFiles.GN_AccesionId, PublishFreeze.Name, " + - "PublishFreeze.FullName FROM InfoFiles, PublishFreeze, " + - "InbredSet WHERE InbredSet.Name = 'BXD' AND " + - "PublishFreeze.InbredSetId = InbredSet.Id AND " + - "InfoFiles.InfoPageName = PublishFreeze.Name " + - "ORDER BY PublishFreeze.CreateTime ASC" - ) - self.assertEqual(build_datasets("Mouse", "MDP", "Phenotypes"), - [['602', "BXDPublish", "Mouse Phenome Database"]]) - - db_mock.db.execute.return_value.fetchall.return_value = () - db_mock.db.execute.return_value.fetchone.return_value = ( - "BXDPublish", "Mouse Phenome Database" - ) - self.assertEqual(build_datasets("Mouse", "MDP", "Phenotypes"), - [["None", "BXDPublish", "Mouse Phenome Database"]]) - - @mock.patch('wqflask.api.gen_menu.g') - def test_build_datasets_with_type_phenotypes_and_no_results(self, db_mock): - """Test that correct dataset is returned for a phenotype type with no - results - - """ - db_mock.db.execute.return_value.fetchall.return_value = None - db_mock.db.execute.return_value.fetchone.return_value = (121, - "text value") - self.assertEqual(build_datasets("Mouse", "BXD", "Phenotypes"), - [["None", "121", "text value"]]) - db_mock.db.execute.assert_called_with( - "SELECT PublishFreeze.Name, PublishFreeze.FullName " - "FROM PublishFreeze, InbredSet " - "WHERE InbredSet.Name = 'BXD' AND " - "PublishFreeze.InbredSetId = InbredSet.Id " - "ORDER BY PublishFreeze.CreateTime ASC" - ) - - @mock.patch('wqflask.api.gen_menu.g') - def test_build_datasets_with_type_genotypes(self, db_mock): - """Test that correct dataset is returned for a phenotype type""" - db_mock.db.execute.return_value.fetchone.return_value = ( - 635, "HLCPublish", "HLC Published Genotypes" - ) - - self.assertEqual(build_datasets("Mouse", "HLC", "Genotypes"), - [["635", "HLCGeno", "HLC Genotypes"]]) - db_mock.db.execute.assert_called_with( - "SELECT InfoFiles.GN_AccesionId FROM InfoFiles, " - "GenoFreeze, InbredSet WHERE InbredSet.Name = 'HLC' AND " - "GenoFreeze.InbredSetId = InbredSet.Id AND " - "InfoFiles.InfoPageName = GenoFreeze.ShortName " + - "ORDER BY GenoFreeze.CreateTime DESC" - ) - db_mock.db.execute.return_value.fetchone.return_value = () - self.assertEqual(build_datasets("Mouse", "HLC", "Genotypes"), - [["None", "HLCGeno", "HLC Genotypes"]]) - - @mock.patch('wqflask.api.gen_menu.g') - def test_build_datasets_with_type_mrna(self, db_mock): - """Test that correct dataset is returned for a mRNA - expression/ Probeset""" - db_mock.db.execute.return_value.fetchall.return_value = ( - (112, "HC_M2_0606_P", - "Hippocampus Consortium M430v2 (Jun06) PDNN"), ) - self.assertEqual(build_datasets("Mouse", "HLC", "mRNA"), [[ - "112", 'HC_M2_0606_P', "Hippocampus Consortium M430v2 (Jun06) PDNN" - ]]) - db_mock.db.execute.assert_called_once_with( - "SELECT ProbeSetFreeze.Id, ProbeSetFreeze.Name, " + - "ProbeSetFreeze.FullName FROM ProbeSetFreeze, " + - "ProbeFreeze, InbredSet, Tissue, Species WHERE " + - "Species.Name = 'Mouse' AND Species.Id = " + - "InbredSet.SpeciesId AND InbredSet.Name = 'HLC' AND " + - "ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id and " + - "Tissue.Name = 'mRNA' AND ProbeFreeze.TissueId = " + - "Tissue.Id and ProbeFreeze.InbredSetId = InbredSet.Id " + - "ORDER BY ProbeSetFreeze.CreateTime DESC") - - @mock.patch('wqflask.api.gen_menu.build_datasets') - @mock.patch('wqflask.api.gen_menu.g') - def test_build_types(self, db_mock, datasets_mock): - """Test that correct tissue metadata is returned""" - datasets_mock.return_value = [ - ["112", 'HC_M2_0606_P', - "Hippocampus Consortium M430v2 (Jun06) PDNN"] - ] - db_mock.db.execute.return_value.fetchall.return_value = ( - ('Mouse Tissue'), ('Human Tissue'), ('Rat Tissue') - ) - self.assertEqual(build_types('mouse', 'random group'), - [['M', 'M', 'Molecular Trait Datasets'], - ['H', 'H', 'Molecular Trait Datasets'], - ['R', 'R', 'Molecular Trait Datasets']]) - db_mock.db.execute.assert_called_once_with( - "SELECT DISTINCT Tissue.Name " + - "FROM ProbeFreeze, ProbeSetFreeze, InbredSet, " + - "Tissue, Species WHERE Species.Name = 'mouse' " + - "AND Species.Id = InbredSet.SpeciesId AND " + - "InbredSet.Name = 'random group' AND " + - "ProbeFreeze.TissueId = Tissue.Id AND " + - "ProbeFreeze.InbredSetId = InbredSet.Id AND " + - "ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id " + - "ORDER BY Tissue.Name" - ) - - @mock.patch('wqflask.api.gen_menu.build_types') - @mock.patch('wqflask.api.gen_menu.genotypes_exist') - @mock.patch('wqflask.api.gen_menu.phenotypes_exist') - def test_get_types_with_existing_genotype_and_phenotypes( - self, - phenotypes_exist_mock, - genotypes_exist_mock, - build_types_mock): - """Test that build types are constructed correctly if phenotypes and genotypes - exist - - """ - phenotypes_exist_mock.return_value = True - genotypes_exist_mock.return_value = True - - expected_result = self.test_type - - build_types_mock.return_value = [ - ['M', 'M', 'Molecular Trait Datasets'] - ] - self.assertEqual(get_types(self.test_group), expected_result) - - @mock.patch('wqflask.api.gen_menu.build_types') - @mock.patch('wqflask.api.gen_menu.genotypes_exist') - @mock.patch('wqflask.api.gen_menu.phenotypes_exist') - def test_get_types_with_buildtype_and_non_existent_genotype_and_phenotypes( - self, - phenotypes_exist_mock, - genotypes_exist_mock, - build_types_mock): - """Test that build types are constructed correctly if phenotypes_exist and - genotypes_exist are false but build_type is falsy - - """ - phenotypes_exist_mock.return_value = False - genotypes_exist_mock.return_value = False - - build_types_mock.return_value = [] - self.assertEqual(get_types(self.test_group), { - 'mouse': {}, - 'human': {} - }) - - @mock.patch('wqflask.api.gen_menu.build_types') - @mock.patch('wqflask.api.gen_menu.genotypes_exist') - @mock.patch('wqflask.api.gen_menu.phenotypes_exist') - def test_get_types_with_non_existent_genotype_phenotypes_and_buildtype( - self, - phenotypes_exist_mock, - genotypes_exist_mock, - build_types_mock): - """Test that build types are constructed correctly if phenotypes_exist, - genotypes_exist and build_types are truthy - - """ - phenotypes_exist_mock.return_value = False - genotypes_exist_mock.return_value = False - - build_types_mock.return_value = [ - ['M', 'M', 'Molecular Trait Datasets'] - ] - expected_result = { - 'mouse': { - 'H_T2': [['M', 'M', 'Molecular Trait Datasets']], - 'H_T1': [['M', 'M', 'Molecular Trait Datasets']]}, - 'human': { - 'HLC': [['M', 'M', 'Molecular Trait Datasets']], - 'BXD': [['M', 'M', 'Molecular Trait Datasets']]}} - self.assertEqual(get_types(self.test_group), - expected_result) - - @mock.patch('wqflask.api.gen_menu.build_datasets') - def test_get_datasets_with_existent_datasets(self, - build_datasets_mock): - """Test correct dataset is returned with existent build_datasets""" - build_datasets_mock.return_value = "Test" - expected_result = { - 'mouse': { - 'H_T2': {'Genotypes': 'Test', - 'M': 'Test', - 'Phenotypes': 'Test'}, - 'H_T1': {'Genotypes': 'Test', - 'M': 'Test', - 'Phenotypes': 'Test'}}, - 'human': {'HLC': {'Genotypes': 'Test', - 'M': 'Test', - 'Phenotypes': 'Test'}, - 'BXD': {'Genotypes': 'Test', - 'M': 'Test', - 'Phenotypes': 'Test'}}} - self.assertEqual(get_datasets(self.test_type), - expected_result) - - @mock.patch('wqflask.api.gen_menu.build_datasets') - def test_get_datasets_with_non_existent_datasets(self, - build_datasets_mock): - """Test correct dataset is returned with non-existent build_datasets""" - build_datasets_mock.return_value = None - expected_result = { - 'mouse': { - 'H_T2': {}, - 'H_T1': {}}, - 'human': {'HLC': {}, - 'BXD': {}}} - self.assertEqual(get_datasets(self.test_type), - expected_result) - - @mock.patch('wqflask.api.gen_menu.get_datasets') - @mock.patch('wqflask.api.gen_menu.get_types') - @mock.patch('wqflask.api.gen_menu.get_groups') - @mock.patch('wqflask.api.gen_menu.get_species') - def test_gen_dropdown_json(self, - species_mock, - groups_mock, - types_mock, - datasets_mock): - "Test that the correct dictionary is constructed properly" - species_mock.return_value = ("speciesA speciesB speciesC speciesD" - .split(" ")) - datasets_mock.return_value = ("datasetA datasetB datasetC datasetD" - .split(" ")) - groups_mock.return_value = ("groupA groupB groupC groupD" - .split(" ")) - types_mock.return_value = ("typeA typeB typeC typeD" - .split(" ")) - datasets_mock.return_value = ("datasetA datasetB datasetC datasetD" - .split(" ")) - - expected_result = { - 'datasets': ['datasetA', 'datasetB', 'datasetC', 'datasetD'], - 'types': ['typeA', 'typeB', 'typeC', 'typeD'], - 'groups': ['groupA', 'groupB', 'groupC', 'groupD'], - 'species': ['speciesA', 'speciesB', 'speciesC', 'speciesD']} - - self.assertEqual(gen_dropdown_json(), expected_result) diff --git a/wqflask/tests/wqflask/__init__.py b/wqflask/tests/wqflask/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/wqflask/tests/wqflask/api/__init__.py b/wqflask/tests/wqflask/api/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/wqflask/tests/wqflask/api/test_gen_menu.py b/wqflask/tests/wqflask/api/test_gen_menu.py new file mode 100644 index 00000000..79c77fec --- /dev/null +++ b/wqflask/tests/wqflask/api/test_gen_menu.py @@ -0,0 +1,407 @@ +"""Test cases for wqflask.api.gen_menu""" +import unittest +import mock + +from wqflask.api.gen_menu import gen_dropdown_json +from wqflask.api.gen_menu import get_species +from wqflask.api.gen_menu import get_groups +from wqflask.api.gen_menu import get_types +from wqflask.api.gen_menu import get_datasets +from wqflask.api.gen_menu import phenotypes_exist +from wqflask.api.gen_menu import genotypes_exist +from wqflask.api.gen_menu import build_datasets +from wqflask.api.gen_menu import build_types + + +class TestGenMenu(unittest.TestCase): + """Tests for the gen_menu module""" + + def setUp(self): + self.test_group = { + 'mouse': [ + ['H_T1', + 'H_T', + 'Family:DescriptionA' + ], + ['H_T2', "H_T'", 'Family:None'] + ], + 'human': [ + ['BXD', 'BXD', 'Family:None'], + ['HLC', 'Liver: Normal Gene Expression with Genotypes (Merck)', + 'Family:Test'] + ] + } + + self.test_type = { + 'mouse': { + 'H_T2': [('Phenotypes', + 'Traits and Cofactors', + 'Phenotypes'), + ('Genotypes', + 'DNA Markers and SNPs', + 'Genotypes'), + ['M', 'M', 'Molecular Trait Datasets']], + 'H_T1': [('Phenotypes', + 'Traits and Cofactors', + 'Phenotypes'), + ('Genotypes', + 'DNA Markers and SNPs', + 'Genotypes'), + ['M', 'M', 'Molecular Trait Datasets']] + }, + 'human': { + 'HLC': [('Phenotypes', + 'Traits and Cofactors', + 'Phenotypes'), + ('Genotypes', + 'DNA Markers and SNPs', + 'Genotypes'), + ['M', 'M', 'Molecular Trait Datasets']], + 'BXD': [('Phenotypes', + 'Traits and Cofactors', + 'Phenotypes'), + ('Genotypes', + 'DNA Markers and SNPs', + 'Genotypes'), + ['M', 'M', 'Molecular Trait Datasets']] + } + } + + @mock.patch('wqflask.api.gen_menu.g') + def test_get_species(self, db_mock): + """Test that assertion is raised when dataset and dataset_name + are defined""" + db_mock.db.execute.return_value.fetchall.return_value = ( + ('human', 'Human'), + ('mouse', 'Mouse')) + self.assertEqual(get_species(), + [['human', 'Human'], ['mouse', 'Mouse']]) + db_mock.db.execute.assert_called_once_with( + "SELECT Name, MenuName FROM Species ORDER BY OrderId" + ) + + @mock.patch('wqflask.api.gen_menu.g') + def test_get_groups(self, db_mock): + """Test that species groups are grouped correctly""" + db_mock.db.execute.return_value.fetchall.side_effect = [ + # Mouse + (('BXD', 'BXD', None), + ('HLC', 'Liver: Normal Gene Expression with Genotypes (Merck)', + 'Test')), + # Human + (('H_T1', "H_T", "DescriptionA"), + ('H_T2', "H_T'", None)) + ] + + self.assertEqual(get_groups([["human", "Human"], ["mouse", "Mouse"]]), + self.test_group) + + for name in ["mouse", "human"]: + db_mock.db.execute.assert_any_call( + ("SELECT InbredSet.Name, InbredSet.FullName, " + + "IFNULL(InbredSet.Family, 'None') " + + "FROM InbredSet, Species WHERE Species.Name " + + "= '{}' AND InbredSet.SpeciesId = Species.Id GROUP by " + + "InbredSet.Name ORDER BY IFNULL(InbredSet.FamilyOrder, " + + "InbredSet.FullName) ASC, IFNULL(InbredSet.Family, " + + "InbredSet.FullName) ASC, InbredSet.FullName ASC, " + + "InbredSet.MenuOrderId ASC").format(name) + ) + + @mock.patch('wqflask.api.gen_menu.g') + def test_phenotypes_exist_called_with_correct_query(self, db_mock): + """Test that phenotypes_exist is called with the correct query""" + db_mock.db.execute.return_value.fetchone.return_value = None + phenotypes_exist("test") + db_mock.db.execute.assert_called_with( + "SELECT Name FROM PublishFreeze " + "WHERE PublishFreeze.Name = 'testPublish'" + ) + + @mock.patch('wqflask.api.gen_menu.g') + def test_phenotypes_exist_with_falsy_values(self, db_mock): + """Test that phenotype check returns correctly when given + a None value""" + for x in [None, False, (), [], ""]: + db_mock.db.execute.return_value.fetchone.return_value = x + self.assertFalse(phenotypes_exist("test")) + + @mock.patch('wqflask.api.gen_menu.g') + def test_phenotypes_exist_with_truthy_value(self, db_mock): + """Test that phenotype check returns correctly when given Truthy """ + for x in ["x", ("result"), ["result"], [1]]: + db_mock.db.execute.return_value.fetchone.return_value = (x) + self.assertTrue(phenotypes_exist("test")) + + @mock.patch('wqflask.api.gen_menu.g') + def test_genotypes_exist_called_with_correct_query(self, db_mock): + """Test that genotypes_exist is called with the correct query""" + db_mock.db.execute.return_value.fetchone.return_value = None + genotypes_exist("test") + db_mock.db.execute.assert_called_with( + "SELECT Name FROM GenoFreeze WHERE GenoFreeze.Name = 'testGeno'" + ) + + @mock.patch('wqflask.api.gen_menu.g') + def test_genotypes_exist_with_falsy_values(self, db_mock): + """Test that genotype check returns correctly when given + a None value""" + for x in [None, False, (), [], ""]: + db_mock.db.execute.return_value.fetchone.return_value = x + self.assertFalse(genotypes_exist("test")) + + @mock.patch('wqflask.api.gen_menu.g') + def test_genotypes_exist_with_truthy_value(self, db_mock): + """Test that genotype check returns correctly when given Truthy """ + for x in ["x", ("result"), ["result"], [1]]: + db_mock.db.execute.return_value.fetchone.return_value = (x) + self.assertTrue(phenotypes_exist("test")) + + @mock.patch('wqflask.api.gen_menu.g') + def test_build_datasets_with_type_phenotypes(self, db_mock): + """Test that correct dataset is returned for a phenotype type""" + db_mock.db.execute.return_value.fetchall.return_value = ( + (602, "BXDPublish", "BXD Published Phenotypes"), + ) + self.assertEqual(build_datasets("Mouse", "BXD", "Phenotypes"), + [['602', "BXDPublish", "BXD Published Phenotypes"]]) + db_mock.db.execute.assert_called_with( + "SELECT InfoFiles.GN_AccesionId, PublishFreeze.Name, " + + "PublishFreeze.FullName FROM InfoFiles, PublishFreeze, " + + "InbredSet WHERE InbredSet.Name = 'BXD' AND " + + "PublishFreeze.InbredSetId = InbredSet.Id AND " + + "InfoFiles.InfoPageName = PublishFreeze.Name " + + "ORDER BY PublishFreeze.CreateTime ASC" + ) + self.assertEqual(build_datasets("Mouse", "MDP", "Phenotypes"), + [['602', "BXDPublish", "Mouse Phenome Database"]]) + + db_mock.db.execute.return_value.fetchall.return_value = () + db_mock.db.execute.return_value.fetchone.return_value = ( + "BXDPublish", "Mouse Phenome Database" + ) + self.assertEqual(build_datasets("Mouse", "MDP", "Phenotypes"), + [["None", "BXDPublish", "Mouse Phenome Database"]]) + + @mock.patch('wqflask.api.gen_menu.g') + def test_build_datasets_with_type_phenotypes_and_no_results(self, db_mock): + """Test that correct dataset is returned for a phenotype type with no + results + + """ + db_mock.db.execute.return_value.fetchall.return_value = None + db_mock.db.execute.return_value.fetchone.return_value = (121, + "text value") + self.assertEqual(build_datasets("Mouse", "BXD", "Phenotypes"), + [["None", "121", "text value"]]) + db_mock.db.execute.assert_called_with( + "SELECT PublishFreeze.Name, PublishFreeze.FullName " + "FROM PublishFreeze, InbredSet " + "WHERE InbredSet.Name = 'BXD' AND " + "PublishFreeze.InbredSetId = InbredSet.Id " + "ORDER BY PublishFreeze.CreateTime ASC" + ) + + @mock.patch('wqflask.api.gen_menu.g') + def test_build_datasets_with_type_genotypes(self, db_mock): + """Test that correct dataset is returned for a phenotype type""" + db_mock.db.execute.return_value.fetchone.return_value = ( + 635, "HLCPublish", "HLC Published Genotypes" + ) + + self.assertEqual(build_datasets("Mouse", "HLC", "Genotypes"), + [["635", "HLCGeno", "HLC Genotypes"]]) + db_mock.db.execute.assert_called_with( + "SELECT InfoFiles.GN_AccesionId FROM InfoFiles, " + "GenoFreeze, InbredSet WHERE InbredSet.Name = 'HLC' AND " + "GenoFreeze.InbredSetId = InbredSet.Id AND " + "InfoFiles.InfoPageName = GenoFreeze.ShortName " + + "ORDER BY GenoFreeze.CreateTime DESC" + ) + db_mock.db.execute.return_value.fetchone.return_value = () + self.assertEqual(build_datasets("Mouse", "HLC", "Genotypes"), + [["None", "HLCGeno", "HLC Genotypes"]]) + + @mock.patch('wqflask.api.gen_menu.g') + def test_build_datasets_with_type_mrna(self, db_mock): + """Test that correct dataset is returned for a mRNA + expression/ Probeset""" + db_mock.db.execute.return_value.fetchall.return_value = ( + (112, "HC_M2_0606_P", + "Hippocampus Consortium M430v2 (Jun06) PDNN"), ) + self.assertEqual(build_datasets("Mouse", "HLC", "mRNA"), [[ + "112", 'HC_M2_0606_P', "Hippocampus Consortium M430v2 (Jun06) PDNN" + ]]) + db_mock.db.execute.assert_called_once_with( + "SELECT ProbeSetFreeze.Id, ProbeSetFreeze.Name, " + + "ProbeSetFreeze.FullName FROM ProbeSetFreeze, " + + "ProbeFreeze, InbredSet, Tissue, Species WHERE " + + "Species.Name = 'Mouse' AND Species.Id = " + + "InbredSet.SpeciesId AND InbredSet.Name = 'HLC' AND " + + "ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id and " + + "Tissue.Name = 'mRNA' AND ProbeFreeze.TissueId = " + + "Tissue.Id and ProbeFreeze.InbredSetId = InbredSet.Id " + + "ORDER BY ProbeSetFreeze.CreateTime DESC") + + @mock.patch('wqflask.api.gen_menu.build_datasets') + @mock.patch('wqflask.api.gen_menu.g') + def test_build_types(self, db_mock, datasets_mock): + """Test that correct tissue metadata is returned""" + datasets_mock.return_value = [ + ["112", 'HC_M2_0606_P', + "Hippocampus Consortium M430v2 (Jun06) PDNN"] + ] + db_mock.db.execute.return_value.fetchall.return_value = ( + ('Mouse Tissue'), ('Human Tissue'), ('Rat Tissue') + ) + self.assertEqual(build_types('mouse', 'random group'), + [['M', 'M', 'Molecular Trait Datasets'], + ['H', 'H', 'Molecular Trait Datasets'], + ['R', 'R', 'Molecular Trait Datasets']]) + db_mock.db.execute.assert_called_once_with( + "SELECT DISTINCT Tissue.Name " + + "FROM ProbeFreeze, ProbeSetFreeze, InbredSet, " + + "Tissue, Species WHERE Species.Name = 'mouse' " + + "AND Species.Id = InbredSet.SpeciesId AND " + + "InbredSet.Name = 'random group' AND " + + "ProbeFreeze.TissueId = Tissue.Id AND " + + "ProbeFreeze.InbredSetId = InbredSet.Id AND " + + "ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id " + + "ORDER BY Tissue.Name" + ) + + @mock.patch('wqflask.api.gen_menu.build_types') + @mock.patch('wqflask.api.gen_menu.genotypes_exist') + @mock.patch('wqflask.api.gen_menu.phenotypes_exist') + def test_get_types_with_existing_genotype_and_phenotypes( + self, + phenotypes_exist_mock, + genotypes_exist_mock, + build_types_mock): + """Test that build types are constructed correctly if phenotypes and genotypes + exist + + """ + phenotypes_exist_mock.return_value = True + genotypes_exist_mock.return_value = True + + expected_result = self.test_type + + build_types_mock.return_value = [ + ['M', 'M', 'Molecular Trait Datasets'] + ] + self.assertEqual(get_types(self.test_group), expected_result) + + @mock.patch('wqflask.api.gen_menu.build_types') + @mock.patch('wqflask.api.gen_menu.genotypes_exist') + @mock.patch('wqflask.api.gen_menu.phenotypes_exist') + def test_get_types_with_buildtype_and_non_existent_genotype_and_phenotypes( + self, + phenotypes_exist_mock, + genotypes_exist_mock, + build_types_mock): + """Test that build types are constructed correctly if phenotypes_exist and + genotypes_exist are false but build_type is falsy + + """ + phenotypes_exist_mock.return_value = False + genotypes_exist_mock.return_value = False + + build_types_mock.return_value = [] + self.assertEqual(get_types(self.test_group), { + 'mouse': {}, + 'human': {} + }) + + @mock.patch('wqflask.api.gen_menu.build_types') + @mock.patch('wqflask.api.gen_menu.genotypes_exist') + @mock.patch('wqflask.api.gen_menu.phenotypes_exist') + def test_get_types_with_non_existent_genotype_phenotypes_and_buildtype( + self, + phenotypes_exist_mock, + genotypes_exist_mock, + build_types_mock): + """Test that build types are constructed correctly if phenotypes_exist, + genotypes_exist and build_types are truthy + + """ + phenotypes_exist_mock.return_value = False + genotypes_exist_mock.return_value = False + + build_types_mock.return_value = [ + ['M', 'M', 'Molecular Trait Datasets'] + ] + expected_result = { + 'mouse': { + 'H_T2': [['M', 'M', 'Molecular Trait Datasets']], + 'H_T1': [['M', 'M', 'Molecular Trait Datasets']]}, + 'human': { + 'HLC': [['M', 'M', 'Molecular Trait Datasets']], + 'BXD': [['M', 'M', 'Molecular Trait Datasets']]}} + self.assertEqual(get_types(self.test_group), + expected_result) + + @mock.patch('wqflask.api.gen_menu.build_datasets') + def test_get_datasets_with_existent_datasets(self, + build_datasets_mock): + """Test correct dataset is returned with existent build_datasets""" + build_datasets_mock.return_value = "Test" + expected_result = { + 'mouse': { + 'H_T2': {'Genotypes': 'Test', + 'M': 'Test', + 'Phenotypes': 'Test'}, + 'H_T1': {'Genotypes': 'Test', + 'M': 'Test', + 'Phenotypes': 'Test'}}, + 'human': {'HLC': {'Genotypes': 'Test', + 'M': 'Test', + 'Phenotypes': 'Test'}, + 'BXD': {'Genotypes': 'Test', + 'M': 'Test', + 'Phenotypes': 'Test'}}} + self.assertEqual(get_datasets(self.test_type), + expected_result) + + @mock.patch('wqflask.api.gen_menu.build_datasets') + def test_get_datasets_with_non_existent_datasets(self, + build_datasets_mock): + """Test correct dataset is returned with non-existent build_datasets""" + build_datasets_mock.return_value = None + expected_result = { + 'mouse': { + 'H_T2': {}, + 'H_T1': {}}, + 'human': {'HLC': {}, + 'BXD': {}}} + self.assertEqual(get_datasets(self.test_type), + expected_result) + + @mock.patch('wqflask.api.gen_menu.get_datasets') + @mock.patch('wqflask.api.gen_menu.get_types') + @mock.patch('wqflask.api.gen_menu.get_groups') + @mock.patch('wqflask.api.gen_menu.get_species') + def test_gen_dropdown_json(self, + species_mock, + groups_mock, + types_mock, + datasets_mock): + "Test that the correct dictionary is constructed properly" + species_mock.return_value = ("speciesA speciesB speciesC speciesD" + .split(" ")) + datasets_mock.return_value = ("datasetA datasetB datasetC datasetD" + .split(" ")) + groups_mock.return_value = ("groupA groupB groupC groupD" + .split(" ")) + types_mock.return_value = ("typeA typeB typeC typeD" + .split(" ")) + datasets_mock.return_value = ("datasetA datasetB datasetC datasetD" + .split(" ")) + + expected_result = { + 'datasets': ['datasetA', 'datasetB', 'datasetC', 'datasetD'], + 'types': ['typeA', 'typeB', 'typeC', 'typeD'], + 'groups': ['groupA', 'groupB', 'groupC', 'groupD'], + 'species': ['speciesA', 'speciesB', 'speciesC', 'speciesD']} + + self.assertEqual(gen_dropdown_json(), expected_result) -- cgit v1.2.3 From 3980446f45ed93a3b9ebed7e5ae9a4cdbec00feb Mon Sep 17 00:00:00 2001 From: Muriithi Frederick Muriuki Date: Thu, 14 Feb 2019 16:34:39 +0300 Subject: Update the colours to use Pillow's ImageColor * wqflask/wqflask/marker_regression/display_mapping_results.py: Use Pillow's ImageColor module in place of the older Piddle colours. --- .../marker_regression/display_mapping_results.py | 185 ++++++++++++--------- 1 file changed, 103 insertions(+), 82 deletions(-) (limited to 'wqflask') diff --git a/wqflask/wqflask/marker_regression/display_mapping_results.py b/wqflask/wqflask/marker_regression/display_mapping_results.py index 9ac4946b..25846099 100644 --- a/wqflask/wqflask/marker_regression/display_mapping_results.py +++ b/wqflask/wqflask/marker_regression/display_mapping_results.py @@ -27,7 +27,7 @@ import datetime import string from math import * -import piddle as pid +from PIL import (ImageColor) import sys,os import cPickle import httplib @@ -49,6 +49,27 @@ from base.webqtlConfig import TMPDIR, GENERATED_TEXT_DIR, GENERATED_IMAGE_DIR import utility.logger logger = utility.logger.getLogger(__name__ ) +RED = ImageColor.getrgb("red") +BLUE = ImageColor.getrgb("blue") +GRAY = ImageColor.getrgb("gray") +GOLD = ImageColor.getrgb("gold") +BLACK = ImageColor.getrgb("black") +GREEN = ImageColor.getrgb("green") +PURPLE = ImageColor.getrgb("purple") +ORANGE = ImageColor.getrgb("orange") +YELLOW = ImageColor.getrgb("yellow") +DARKRED = ImageColor.getrgb("darkred") +DARKBLUE = ImageColor.getrgb("darkblue") +DARKGRAY = ImageColor.getrgb("darkgray") +DEEPPINK = ImageColor.getrgb("deeppink") +DARKGREEN = ImageColor.getrgb("darkgreen") +GAINSBORO = ImageColor.getrgb("gainsboro") +LIGHTBLUE = ImageColor.getrgb("lightblue") +DARKORANGE = ImageColor.getrgb("darkorange") +DARKVIOLET = ImageColor.getrgb("darkviolet") +MEDIUMPURPLE = ImageColor.getrgb("mediumpurple") +# ---- END: Define common colours ---- # + ######################################### # Inteval Mapping Plot Page ######################################### @@ -96,47 +117,47 @@ class DisplayMappingResults(object): LODFACTOR = 4.61 - SNP_COLOR = pid.orange # Color for the SNP "seismograph" - TRANSCRIPT_LOCATION_COLOR = pid.mediumpurple + SNP_COLOR = ORANGE # Color for the SNP "seismograph" + TRANSCRIPT_LOCATION_COLOR = MEDIUMPURPLE - BOOTSTRAP_BOX_COLOR = pid.yellow - LRS_COLOR = pid.HexColor(0x0000FF) - SIGNIFICANT_COLOR = pid.HexColor(0xEBC7C7) - SUGGESTIVE_COLOR = pid.gainsboro + BOOTSTRAP_BOX_COLOR = YELLOW + LRS_COLOR = ImageColor.getrgb("#0000FF") + SIGNIFICANT_COLOR = ImageColor.getrgb("#EBC7C7") + SUGGESTIVE_COLOR = GAINSBORO SIGNIFICANT_WIDTH = 5 SUGGESTIVE_WIDTH = 5 - ADDITIVE_COLOR_POSITIVE = pid.green - ADDITIVE_COLOR_NEGATIVE = pid.orange - DOMINANCE_COLOR_POSITIVE = pid.darkviolet - DOMINANCE_COLOR_NEGATIVE = pid.red + ADDITIVE_COLOR_POSITIVE = GREEN + ADDITIVE_COLOR_NEGATIVE = ORANGE + DOMINANCE_COLOR_POSITIVE = DARKVIOLET + DOMINANCE_COLOR_NEGATIVE = RED ## BEGIN HaplotypeAnalyst - HAPLOTYPE_POSITIVE = pid.green - HAPLOTYPE_NEGATIVE = pid.red - HAPLOTYPE_HETEROZYGOUS = pid.blue - HAPLOTYPE_RECOMBINATION = pid.darkgray + HAPLOTYPE_POSITIVE = GREEN + HAPLOTYPE_NEGATIVE = RED + HAPLOTYPE_HETEROZYGOUS = BLUE + HAPLOTYPE_RECOMBINATION = DARKGRAY ## END HaplotypeAnalyst - TOP_RIGHT_INFO_COLOR = pid.black + TOP_RIGHT_INFO_COLOR = BLACK - CLICKABLE_WEBQTL_REGION_COLOR = pid.HexColor(0xF5D3D3) - CLICKABLE_WEBQTL_REGION_OUTLINE_COLOR = pid.HexColor(0xFCE9E9) - CLICKABLE_WEBQTL_TEXT_COLOR = pid.HexColor(0x912828) + CLICKABLE_WEBQTL_REGION_COLOR = ImageColor.getrgb("#F5D3D3") + CLICKABLE_WEBQTL_REGION_OUTLINE_COLOR = ImageColor.getrgb("#FCE9E9") + CLICKABLE_WEBQTL_TEXT_COLOR = ImageColor.getrgb("#912828") - CLICKABLE_PHENOGEN_REGION_COLOR = pid.HexColor(0xA2FB94) - CLICKABLE_PHENOGEN_REGION_OUTLINE_COLOR = pid.HexColor(0xCEFEC7) - CLICKABLE_PHENOGEN_TEXT_COLOR = pid.HexColor(0x1FD504) + CLICKABLE_PHENOGEN_REGION_COLOR = ImageColor.getrgb("#A2FB94") + CLICKABLE_PHENOGEN_REGION_OUTLINE_COLOR = ImageColor.getrgb("#CEFEC7") + CLICKABLE_PHENOGEN_TEXT_COLOR = ImageColor.getrgb("#1FD504") - CLICKABLE_UCSC_REGION_COLOR = pid.HexColor(0xDDDDEE) - CLICKABLE_UCSC_REGION_OUTLINE_COLOR = pid.HexColor(0xEDEDFF) - CLICKABLE_UCSC_TEXT_COLOR = pid.HexColor(0x333366) + CLICKABLE_UCSC_REGION_COLOR = ImageColor.getrgb("#DDDDEE") + CLICKABLE_UCSC_REGION_OUTLINE_COLOR = ImageColor.getrgb("#EDEDFF") + CLICKABLE_UCSC_TEXT_COLOR = ImageColor.getrgb("#333366") - CLICKABLE_ENSEMBL_REGION_COLOR = pid.HexColor(0xEEEEDD) - CLICKABLE_ENSEMBL_REGION_OUTLINE_COLOR = pid.HexColor(0xFEFEEE) - CLICKABLE_ENSEMBL_TEXT_COLOR = pid.HexColor(0x555500) + CLICKABLE_ENSEMBL_REGION_COLOR = ImageColor.getrgb("#EEEEDD") + CLICKABLE_ENSEMBL_REGION_OUTLINE_COLOR = ImageColor.getrgb("#FEFEEE") + CLICKABLE_ENSEMBL_TEXT_COLOR = ImageColor.getrgb("#555500") - GRAPH_BACK_LIGHT_COLOR = pid.HexColor(0xFBFBFF) - GRAPH_BACK_DARK_COLOR = pid.HexColor(0xF1F1F9) + GRAPH_BACK_LIGHT_COLOR = ImageColor.getrgb("#FBFBFF") + GRAPH_BACK_DARK_COLOR = ImageColor.getrgb("#F1F1F9") HELP_PAGE_REF = '/glossary.html' @@ -698,23 +719,23 @@ class DisplayMappingResults(object): bootOffset = 50*fontZoom bootScaleFont=pid.Font(ttf="verdana",size=13*fontZoom,bold=0) - canvas.drawRect(canvas.size[0]-bootOffset,yZero-bootHeightThresh,canvas.size[0]-bootOffset-15*zoom,yZero,fillColor = pid.yellow) - canvas.drawLine(canvas.size[0]-bootOffset+4, yZero, canvas.size[0]-bootOffset, yZero, color=pid.black) - canvas.drawString('0%' ,canvas.size[0]-bootOffset+10,yZero+5,font=bootScaleFont,color=pid.black) + canvas.drawRect(canvas.size[0]-bootOffset,yZero-bootHeightThresh,canvas.size[0]-bootOffset-15*zoom,yZero,fillColor = YELLOW) + canvas.drawLine(canvas.size[0]-bootOffset+4, yZero, canvas.size[0]-bootOffset, yZero, color=BLACK) + canvas.drawString('0%' ,canvas.size[0]-bootOffset+10,yZero+5,font=bootScaleFont,color=BLACK) for item in bootScale: if item == 0: continue bootY = yZero-bootHeightThresh*item/highestPercent - canvas.drawLine(canvas.size[0]-bootOffset+4,bootY,canvas.size[0]-bootOffset,bootY,color=pid.black) - canvas.drawString('%2.1f'%item ,canvas.size[0]-bootOffset+10,bootY+5,font=bootScaleFont,color=pid.black) + canvas.drawLine(canvas.size[0]-bootOffset+4,bootY,canvas.size[0]-bootOffset,bootY,color=BLACK) + canvas.drawString('%2.1f'%item ,canvas.size[0]-bootOffset+10,bootY+5,font=bootScaleFont,color=BLACK) if self.legendChecked: startPosY = 30 nCol = 2 smallLabelFont = pid.Font(ttf="trebuc", size=12*fontZoom, bold=1) leftOffset = xLeftOffset+(nCol-1)*200 - canvas.drawRect(leftOffset,startPosY-6, leftOffset+12,startPosY+6, fillColor=pid.yellow) - canvas.drawString('Frequency of the Peak LRS',leftOffset+ 20, startPosY+5,font=smallLabelFont,color=pid.black) + canvas.drawRect(leftOffset,startPosY-6, leftOffset+12,startPosY+6, fillColor=YELLOW) + canvas.drawString('Frequency of the Peak LRS',leftOffset+ 20, startPosY+5,font=smallLabelFont,color=BLACK) def drawProbeSetPosition(self, canvas, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None): if len(self.traitList) != 1: @@ -784,7 +805,7 @@ class DisplayMappingResults(object): break if locPixel >= 0 and self.plotScale == 'physic': traitPixel = ((locPixel, yZero), (locPixel-7, yZero+14), (locPixel+7, yZero+14)) - canvas.drawPolygon(traitPixel, edgeColor=pid.black, fillColor=self.TRANSCRIPT_LOCATION_COLOR, closed=1) + canvas.drawPolygon(traitPixel, edgeColor=BLACK, fillColor=self.TRANSCRIPT_LOCATION_COLOR, closed=1) if self.legendChecked: startPosY = 15 @@ -794,7 +815,7 @@ class DisplayMappingResults(object): leftOffset = xLeftOffset else: leftOffset = xLeftOffset+(nCol-1)*200*fontZoom - canvas.drawPolygon(((leftOffset+7, startPosY-7), (leftOffset, startPosY+7), (leftOffset+14, startPosY+7)), edgeColor=pid.black, fillColor=self.TRANSCRIPT_LOCATION_COLOR, closed=1) + canvas.drawPolygon(((leftOffset+7, startPosY-7), (leftOffset, startPosY+7), (leftOffset+14, startPosY+7)), edgeColor=BLACK, fillColor=self.TRANSCRIPT_LOCATION_COLOR, closed=1) canvas.drawString("Sequence Site", (leftOffset+15), (startPosY+5), smallLabelFont, self.TOP_RIGHT_INFO_COLOR) def drawSNPTrackNew(self, canvas, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None): @@ -863,7 +884,7 @@ class DisplayMappingResults(object): nameWidths.append(nameWidth) canvas.drawRect(rightShift,yPaddingTop+kstep*15, rectWidth+rightShift,yPaddingTop+10+kstep*15, fillColor=thisLRSColor) - canvas.drawString(name,rectWidth+2+rightShift,yPaddingTop+10+kstep*15,font=colorFont,color=pid.black) + canvas.drawString(name,rectWidth+2+rightShift,yPaddingTop+10+kstep*15,font=colorFont,color=BLACK) if thisTrait.db: COORDS = "%d,%d,%d,%d" %(rectWidth+2+rightShift,yPaddingTop+kstep*15,rectWidth+2+rightShift+nameWidth,yPaddingTop+10+kstep*15,) HREF= "javascript:showDatabase3('%s','%s','%s','');" % (showLocusForm, thisTrait.db.name, thisTrait.name) @@ -884,21 +905,21 @@ class DisplayMappingResults(object): stepPosY = 12*fontZoom if self.manhattan_plot != True: canvas.drawLine(xLeftOffset,startPosY,xLeftOffset+32,startPosY,color=self.LRS_COLOR, width=2) - canvas.drawString(self.LRS_LOD, xLeftOffset+40,startPosY+5,font=labelFont,color=pid.black) + canvas.drawString(self.LRS_LOD, xLeftOffset+40,startPosY+5,font=labelFont,color=BLACK) startPosY += stepPosY if self.additiveChecked: startPosX = xLeftOffset canvas.drawLine(startPosX,startPosY,startPosX+17,startPosY,color=self.ADDITIVE_COLOR_POSITIVE, width=2) canvas.drawLine(startPosX+18,startPosY,startPosX+32,startPosY,color=self.ADDITIVE_COLOR_NEGATIVE, width=2) - canvas.drawString('Additive Effect',startPosX+40,startPosY+5,font=labelFont,color=pid.black) + canvas.drawString('Additive Effect',startPosX+40,startPosY+5,font=labelFont,color=BLACK) if self.genotype.type == 'intercross' and self.dominanceChecked: startPosX = xLeftOffset startPosY += stepPosY canvas.drawLine(startPosX,startPosY,startPosX+17,startPosY,color=self.DOMINANCE_COLOR_POSITIVE, width=4) canvas.drawLine(startPosX+18,startPosY,startPosX+35,startPosY,color=self.DOMINANCE_COLOR_NEGATIVE, width=4) - canvas.drawString('Dominance Effect',startPosX+42,startPosY+5,font=labelFont,color=pid.black) + canvas.drawString('Dominance Effect',startPosX+42,startPosY+5,font=labelFont,color=BLACK) if self.haplotypeAnalystChecked: startPosY += stepPosY @@ -907,18 +928,18 @@ class DisplayMappingResults(object): canvas.drawLine(startPosX+18,startPosY,startPosX+35,startPosY,color=self.HAPLOTYPE_NEGATIVE, width=4) canvas.drawLine(startPosX+36,startPosY,startPosX+53,startPosY,color=self.HAPLOTYPE_HETEROZYGOUS, width=4) canvas.drawLine(startPosX+54,startPosY,startPosX+67,startPosY,color=self.HAPLOTYPE_RECOMBINATION, width=4) - canvas.drawString('Haplotypes (Pat, Mat, Het, Unk)',startPosX+76,startPosY+5,font=labelFont,color=pid.black) + canvas.drawString('Haplotypes (Pat, Mat, Het, Unk)',startPosX+76,startPosY+5,font=labelFont,color=BLACK) if self.permChecked and self.nperm > 0: startPosY += stepPosY startPosX = xLeftOffset canvas.drawLine(startPosX, startPosY, startPosX + 32, startPosY, color=self.SIGNIFICANT_COLOR, width=self.SIGNIFICANT_WIDTH) canvas.drawLine(startPosX, startPosY + stepPosY, startPosX + 32, startPosY + stepPosY, color=self.SUGGESTIVE_COLOR, width=self.SUGGESTIVE_WIDTH) - canvas.drawString('Significant %s = %2.2f' % (self.LRS_LOD, self.significant),xLeftOffset+42,startPosY +5,font=labelFont,color=pid.black) - canvas.drawString('Suggestive %s = %2.2f' % (self.LRS_LOD, self.suggestive),xLeftOffset+42,startPosY + 5 +stepPosY,font=labelFont,color=pid.black) + canvas.drawString('Significant %s = %2.2f' % (self.LRS_LOD, self.significant),xLeftOffset+42,startPosY +5,font=labelFont,color=BLACK) + canvas.drawString('Suggestive %s = %2.2f' % (self.LRS_LOD, self.suggestive),xLeftOffset+42,startPosY + 5 +stepPosY,font=labelFont,color=BLACK) labelFont = pid.Font(ttf="verdana",size=12*fontZoom) - labelColor = pid.black + labelColor = BLACK if self.dataset.type == "Publish" or self.dataset.type == "Geno": dataset_label = self.dataset.fullname else: @@ -1042,19 +1063,19 @@ class DisplayMappingResults(object): densities=[1.0000000000000001e-05, 0.094094033555233408, 0.3306166377816987, 0.88246026851027781, 2.6690084029581951, 4.1, 61.0] if SNPdensity < densities[0]: - myColor = pid.black + myColor = BLACK elif SNPdensity < densities[1]: - myColor = pid.purple + myColor = PURPLE elif SNPdensity < densities[2]: - myColor = pid.darkblue + myColor = DARKBLUE elif SNPdensity < densities[3]: - myColor = pid.darkgreen + myColor = DARKGREEN elif SNPdensity < densities[4]: - myColor = pid.gold + myColor = GOLD elif SNPdensity < densities[5]: - myColor = pid.darkorange + myColor = DARKORANGE else: - myColor = pid.darkred + myColor = DARKRED outlineColor = myColor fillColor = myColor @@ -1086,14 +1107,14 @@ class DisplayMappingResults(object): elif (geneStartPix < xLeftOffset): geneStartPix = xLeftOffset; # clip the first in-range gene - outlineColor = pid.darkblue - fillColor = pid.darkblue + outlineColor = DARKBLUE + fillColor = DARKBLUE TITLE = "Gene: %s\nFrom %2.3f to %2.3f Mb (%s)" % (geneSymbol, float(txStart), float(txEnd), strand) # NL: 06-02-2011 Rob required to change this link for gene related HREF=geneNCBILink %geneSymbol else: - outlineColor = pid.orange - fillColor = pid.orange + outlineColor = ORANGE + fillColor = ORANGE TITLE = "Gene: %s" % geneSymbol #Draw Genes @@ -1287,7 +1308,7 @@ class DisplayMappingResults(object): drawit = 1 if drawit == 1: - myColor = pid.darkblue + myColor = DARKBLUE outlineColor = myColor fillColor = myColor @@ -1335,8 +1356,8 @@ class DisplayMappingResults(object): canvas.drawLine(drawStart, geneYLocation+7+2*ind*self.EACH_GENE_HEIGHT*zoom, drawEnd, geneYLocation+7+2*ind*self.EACH_GENE_HEIGHT*zoom, color = mylineColor, width=zoom*(self.EACH_GENE_HEIGHT+2)) - fillColor=pid.black - outlineColor=pid.black + fillColor=BLACK + outlineColor=BLACK if lastGene == 0: canvas.drawRect(geneStartPix, geneYLocation+2*ind*self.EACH_GENE_HEIGHT*zoom, geneEndPix, geneYLocation+2*ind*self.EACH_GENE_HEIGHT+ 2*self.EACH_GENE_HEIGHT*zoom, edgeColor = outlineColor, fillColor = fillColor) @@ -1355,7 +1376,7 @@ class DisplayMappingResults(object): if lastGene == 0: - canvas.drawString("%s" % (_chr[j].name), geneStartPix , geneYLocation+17+2*maxind*self.EACH_GENE_HEIGHT*zoom, font=pid.Font(ttf="verdana", size=12, bold=0), color=pid.black, angle=-90) + canvas.drawString("%s" % (_chr[j].name), geneStartPix , geneYLocation+17+2*maxind*self.EACH_GENE_HEIGHT*zoom, font=pid.Font(ttf="verdana", size=12, bold=0), color=BLACK, angle=-90) oldgeneEndPix = geneEndPix; oldgeno = _chr[j].genotype @@ -1384,8 +1405,8 @@ class DisplayMappingResults(object): expr = item.value # Place where font is hardcoded - canvas.drawString("%s" % (samplelist[j]), (xLeftOffset + plotWidth + 10) , geneYLocation+8+2*ind*self.EACH_GENE_HEIGHT*zoom, font=pid.Font(ttf="verdana", size=12, bold=0), color=pid.black) - canvas.drawString("%2.2f" % (expr), (xLeftOffset + plotWidth + 60) , geneYLocation+8+2*ind*self.EACH_GENE_HEIGHT*zoom, font=pid.Font(ttf="verdana", size=12, bold=0), color=pid.black) + canvas.drawString("%s" % (samplelist[j]), (xLeftOffset + plotWidth + 10) , geneYLocation+8+2*ind*self.EACH_GENE_HEIGHT*zoom, font=pid.Font(ttf="verdana", size=12, bold=0), color=BLACK) + canvas.drawString("%2.2f" % (expr), (xLeftOffset + plotWidth + 60) , geneYLocation+8+2*ind*self.EACH_GENE_HEIGHT*zoom, font=pid.Font(ttf="verdana", size=12, bold=0), color=BLACK) ## END HaplotypeAnalyst @@ -1487,14 +1508,14 @@ class DisplayMappingResults(object): chrFont = pid.Font(ttf="verdana", size=26*zoom, bold=1) traitFont = pid.Font(ttf="verdana", size=14, bold=0) chrX = xLeftOffset + plotWidth - 2 - canvas.stringWidth("Chr %s" % self.ChrList[self.selectedChr][0], font=chrFont) - canvas.drawString("Chr %s" % self.ChrList[self.selectedChr][0], chrX, ensemblPaddingTop-5, font=chrFont, color=pid.gray) + canvas.drawString("Chr %s" % self.ChrList[self.selectedChr][0], chrX, ensemblPaddingTop-5, font=chrFont, color=GRAY) # end of drawBrowserClickableRegions else: #draw the gray text chrFont = pid.Font(ttf="verdana", size=26*zoom, bold=1) traitFont = pid.Font(ttf="verdana", size=14, bold=0) chrX = xLeftOffset + (plotWidth - canvas.stringWidth("Chr %s" % currentChromosome, font=chrFont))/2 - canvas.drawString("Chr %s" % currentChromosome, chrX, 32, font=chrFont, color=pid.gray) + canvas.drawString("Chr %s" % currentChromosome, chrX, 32, font=chrFont, color=GRAY) # end of drawBrowserClickableRegions pass @@ -1517,8 +1538,8 @@ class DisplayMappingResults(object): MBLabelFont = pid.Font(ttf="verdana", size=15*zoom, bold=0) xMajorTickHeight = 10 * zoom # How high the tick extends below the axis xMinorTickHeight = 5*zoom - xAxisTickMarkColor = pid.black - xAxisLabelColor = pid.black + xAxisTickMarkColor = BLACK + xAxisLabelColor = BLACK fontHeight = 12*fontZoom # How tall the font that we're using is spacingFromLabelToAxis = 5 @@ -1565,14 +1586,14 @@ class DisplayMappingResults(object): else: distScale = 5 for j, tickdists in enumerate(range(distScale, int(ceil(distLen)), distScale)): - canvas.drawLine(startPosX + tickdists*plotXScale, yZero, startPosX + tickdists*plotXScale, yZero + 7, color=pid.black, width=1*zoom) + canvas.drawLine(startPosX + tickdists*plotXScale, yZero, startPosX + tickdists*plotXScale, yZero + 7, color=BLACK, width=1*zoom) if j % 2 == 0: - canvas.drawString(str(tickdists), startPosX+tickdists*plotXScale, yZero + 10*zoom, color=pid.black, font=MBLabelFont, angle=270) + canvas.drawString(str(tickdists), startPosX+tickdists*plotXScale, yZero + 10*zoom, color=BLACK, font=MBLabelFont, angle=270) startPosX += (self.ChrLengthDistList[i]+self.GraphInterval)*plotXScale megabaseLabelFont = pid.Font(ttf="verdana", size=18*zoom*1.5, bold=0) canvas.drawString("Megabases", xLeftOffset + (plotWidth - canvas.stringWidth("Megabases", font=megabaseLabelFont))/2, - strYLoc + canvas.fontHeight(MBLabelFont)+ 10*(zoom%2) + 10, font=megabaseLabelFont, color=pid.black) + strYLoc + canvas.fontHeight(MBLabelFont)+ 10*(zoom%2) + 10, font=megabaseLabelFont, color=BLACK) pass else: strYLoc = yZero + spacingFromLabelToAxis + canvas.fontHeight(MBLabelFont) + 8 @@ -1619,7 +1640,7 @@ class DisplayMappingResults(object): LRectWidth = 10 LRectHeight = 3 offsetA = -stepA - lineColor = pid.lightblue + lineColor = LIGHTBLUE startPosX = xLeftOffset for j, ChrInfo in enumerate(ChrAInfo): @@ -1642,11 +1663,11 @@ class DisplayMappingResults(object): yZero+25, color=lineColor) canvas.drawLine(xLeftOffset+offsetA,yZero+25,xLeftOffset+offsetA,\ yZero+40+Zorder*(LRectWidth+3),color=lineColor) - rectColor = pid.orange + rectColor = ORANGE else: canvas.drawLine(xLeftOffset+offsetA, yZero+40+Zorder*(LRectWidth+3)-3,\ xLeftOffset+offsetA, yZero+40+Zorder*(LRectWidth+3),color=lineColor) - rectColor = pid.deeppink + rectColor = DEEPPINK canvas.drawRect(xLeftOffset+offsetA, yZero+40+Zorder*(LRectWidth+3),\ xLeftOffset+offsetA-LRectHeight,yZero+40+Zorder*(LRectWidth+3)+LRectWidth,\ edgeColor=rectColor,fillColor=rectColor,edgeWidth = 0) @@ -1663,9 +1684,9 @@ class DisplayMappingResults(object): centimorganLabelFont = pid.Font(ttf="verdana", size=18*zoom*1.5, bold=0) canvas.drawString("Centimorgans", xLeftOffset + (plotWidth - canvas.stringWidth("Megabases", font=centimorganLabelFont))/2, - strYLoc + canvas.fontHeight(MBLabelFont)+ 10*(zoom%2) + 10, font=centimorganLabelFont, color=pid.black) + strYLoc + canvas.fontHeight(MBLabelFont)+ 10*(zoom%2) + 10, font=centimorganLabelFont, color=BLACK) - canvas.drawLine(xLeftOffset, yZero, xLeftOffset+plotWidth, yZero, color=pid.black, width=X_AXIS_THICKNESS) # Draw the X axis itself + canvas.drawLine(xLeftOffset, yZero, xLeftOffset+plotWidth, yZero, color=BLACK, width=X_AXIS_THICKNESS) # Draw the X axis itself def drawQTL(self, canvas, drawAreaHeight, gifmap, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None): @@ -1774,7 +1795,7 @@ class DisplayMappingResults(object): #draw the "LRS" or "LOD" string to the left of the axis canvas.drawString(self.LRS_LOD, xLeftOffset - max_lrs_width - 15*(zoom-1), \ - yZero - 150 - 300*(zoom - 1), font=LRSLODFont, color=pid.black, angle=90) + yZero - 150 - 300*(zoom - 1), font=LRSLODFont, color=BLACK, angle=90) for item in LRSAxisList: if LRS_LOD_Max == 0.0: @@ -1955,9 +1976,9 @@ class DisplayMappingResults(object): if self.manhattan_plot == True: if self.selectedChr == -1 and (previous_chr_as_int % 2 == 1): - point_color = pid.red + point_color = RED else: - point_color = pid.blue + point_color = BLUE final_x_pos = Xc-canvas.stringWidth("5",font=symbolFont)/2+1 if final_x_pos > (xLeftOffset + plotWidth): @@ -2121,13 +2142,13 @@ class DisplayMappingResults(object): #draw the shaded boxes and the sig/sug thick lines canvas.drawRect(startPosX, yTopOffset, startPosX + self.ChrLengthDistList[i]*plotXScale, \ - yBottom, edgeColor=pid.gainsboro,fillColor=theBackColor) + yBottom, edgeColor=GAINSBORO,fillColor=theBackColor) chrNameWidth = canvas.stringWidth(_chr.name, font=chrLabelFont) chrStartPix = startPosX + (self.ChrLengthDistList[i]*plotXScale -chrNameWidth)/2 chrEndPix = startPosX + (self.ChrLengthDistList[i]*plotXScale +chrNameWidth)/2 - canvas.drawString(_chr.name, chrStartPix, yTopOffset + 20 ,font = chrLabelFont,color=pid.black) + canvas.drawString(_chr.name, chrStartPix, yTopOffset + 20 ,font = chrLabelFont,color=BLACK) COORDS = "%d,%d,%d,%d" %(chrStartPix, yTopOffset, chrEndPix,yTopOffset +20) #add by NL 09-03-2010 @@ -2379,4 +2400,4 @@ class DisplayMappingResults(object): lCorr = lCorr[0] break except: raise #lCorr = None - return lCorr \ No newline at end of file + return lCorr -- cgit v1.2.3 From 49dfdc0c986901683f3e00e65f922e2318e0f330 Mon Sep 17 00:00:00 2001 From: Muriithi Frederick Muriuki Date: Fri, 15 Feb 2019 08:41:28 +0300 Subject: Migrate code from Piddle to Pillow * wqflask/wqflask/marker_regression/display_mapping_results.py: Add font files (DisplayMappingResults): Update the code from the Piddle way of things to the Pillow way of things, for example, replace: - pid.drawRect(...) with im_drawer.rectangle(...) - pid.drawString(...) with im_drawer.text(...) - pid.drawPolygon(...) with im_drawer.polygon(...) etc. * wqflask/utility/Plot.py: Migrate code from the older, unsupported Piddle to the newer Pillow library. --- wqflask/utility/Plot.py | 87 ++- .../marker_regression/display_mapping_results.py | 757 ++++++++++++++++----- 2 files changed, 637 insertions(+), 207 deletions(-) (limited to 'wqflask') diff --git a/wqflask/utility/Plot.py b/wqflask/utility/Plot.py index 9bc84d22..c557bcc6 100644 --- a/wqflask/utility/Plot.py +++ b/wqflask/utility/Plot.py @@ -26,7 +26,7 @@ from __future__ import print_function -import piddle as pid +from PIL import (Image, ImageColor, ImageDraw, ImageFont) from pprint import pformat as pf from math import * @@ -42,6 +42,17 @@ from base import webqtlConfig import utility.logger logger = utility.logger.getLogger(__name__ ) +# ---- Define common colours ---- # +BLUE = ImageColor.getrgb("blue") +BLACK = ImageColor.getrgb("black") +# ---- END: Define common colours ---- # + +# ---- FONT FILES ---- # +VERDANA_FILE = "fonts/ttf/verdana.ttf" +COUR_FILE = "fonts/ttf/courbd.ttf" +TAHOMA_FILE = "fonts/ttf/tahoma.ttf" +# ---- END: FONT FILES ---- # + def cformat(d, rank=0): 'custom string format' strD = "%2.6f" % d @@ -114,7 +125,8 @@ def find_outliers(vals): # parameter: data is either object returned by reaper permutation function (called by MarkerRegressionPage.py) # or the first object returned by direct (pair-scan) permu function (called by DirectPlotPage.py) -def plotBar(canvas, data, barColor=pid.blue, axesColor=pid.black, labelColor=pid.black, XLabel=None, YLabel=None, title=None, offset= (60, 20, 40, 40), zoom = 1): +def plotBar(canvas, data, barColor=BLUE, axesColor=BLACK, labelColor=BLACK, XLabel=None, YLabel=None, title=None, offset= (60, 20, 40, 40), zoom = 1): + im_drawer = ImageDraw.Draw(canvas) xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset plotWidth = canvas.size[0] - xLeftOffset - xRightOffset @@ -161,43 +173,67 @@ def plotBar(canvas, data, barColor=pid.blue, axesColor=pid.black, labelColor=pid if count: xc = (dataXY[i]-xLow)*xScale+xLeftOffset yc =-(count-yLow)*yScale+yTopOffset+plotHeight - canvas.drawRect(xc+2,yc,xc+barWidth-2,yTopOffset+plotHeight,edgeColor=barColor,fillColor=barColor) + im_drawer.rectangle( + xy=((xc+2,yc),(xc+barWidth-2,yTopOffset+plotHeight)), + outline=barColor, fill=barColor) #draw drawing region - canvas.drawRect(xLeftOffset, yTopOffset, xLeftOffset+plotWidth, yTopOffset+plotHeight) + im_drawer.rectangle( + xy=((xLeftOffset, yTopOffset), (xLeftOffset+plotWidth, yTopOffset+plotHeight)) + ) #draw scale - scaleFont=pid.Font(ttf="cour",size=11,bold=1) + scaleFont=ImageFont.truetype(font=COUR_FILE,size=11) x=xLow for i in range(int(stepX)+1): xc=xLeftOffset+(x-xLow)*xScale - canvas.drawLine(xc,yTopOffset+plotHeight,xc,yTopOffset+plotHeight+5, color=axesColor) + im_drawer.line( + xy=((xc,yTopOffset+plotHeight),(xc,yTopOffset+plotHeight+5)), + fill=axesColor) strX = cformat(d=x, rank=0) - canvas.drawString(strX,xc-canvas.stringWidth(strX,font=scaleFont)/2,yTopOffset+plotHeight+14,font=scaleFont) + im_drawer.text( + text=strX, + xy=(xc-im_drawer.textsize(strX,font=scaleFont)[0]/2, + yTopOffset+plotHeight+14),font=scaleFont) x+= (xTop - xLow)/stepX y=yLow for i in range(int(stepY)+1): yc=yTopOffset+plotHeight-(y-yLow)*yScale - canvas.drawLine(xLeftOffset,yc,xLeftOffset-5,yc, color=axesColor) + im_drawer.line(xy=((xLeftOffset,yc),(xLeftOffset-5,yc)), fill=axesColor) strY = "%d" %y - canvas.drawString(strY,xLeftOffset-canvas.stringWidth(strY,font=scaleFont)-6,yc+5,font=scaleFont) + im_drawer.text( + text=strY, + xy=(xLeftOffset-im_drawer.textsize(strY,font=scaleFont)[0]-6,yc+5), + font=scaleFont) y+= (yTop - yLow)/stepY #draw label - labelFont=pid.Font(ttf="tahoma",size=17,bold=0) + labelFont=ImageFont.truetype(font=TAHOMA_FILE,size=17) if XLabel: - canvas.drawString(XLabel,xLeftOffset+(plotWidth-canvas.stringWidth(XLabel,font=labelFont))/2.0, - yTopOffset+plotHeight+yBottomOffset-10,font=labelFont,color=labelColor) + im_drawer.text( + text=XLabel, + xy=(xLeftOffset+( + plotWidth-im_drawer.textsize(XLabel,font=labelFont)[0])/2.0, + yTopOffset+plotHeight+yBottomOffset-10), + font=labelFont,fill=labelColor) if YLabel: - canvas.drawString(YLabel, 19, yTopOffset+plotHeight-(plotHeight-canvas.stringWidth(YLabel,font=labelFont))/2.0, - font=labelFont,color=labelColor,angle=90) - - labelFont=pid.Font(ttf="verdana",size=16,bold=0) + im_drawer.text( + text=YLabel, + xy=(19, + yTopOffset+plotHeight-(plotHeight-im_drawer.textsize( + YLabel,font=labelFont)[0])/2.0), + font=labelFont,fill=labelColor,angle=90) + + labelFont=ImageFont.truetype(font=VERDANA_FILE,size=16) if title: - canvas.drawString(title,xLeftOffset+(plotWidth-canvas.stringWidth(title,font=labelFont))/2.0, - 20,font=labelFont,color=labelColor) + im_drawer.text( + text=title, + xy=(xLeftOffset+(plotWidth-im_drawer.textsize( + title,font=labelFont)[0])/2.0, + 20), + font=labelFont,fill=labelColor) # This function determines the scale of the plot def detScaleOld(min,max): @@ -265,16 +301,21 @@ def greenfunc(x): def colorSpectrum(n=100): multiple = 10 if n == 1: - return [pid.Color(1,0,0)] + return [ImageColor.getrgb("rgb(100%,0%,0%)")] elif n == 2: - return [pid.Color(1,0,0),pid.Color(0,0,1)] + return [ImageColor.getrgb("100%,0%,0%)"), + ImageColor.getrgb("rgb(0%,0%,100%)")] elif n == 3: - return [pid.Color(1,0,0),pid.Color(0,1,0),pid.Color(0,0,1)] + return [ImageColor.getrgb("rgb(100%,0%,0%)"), + ImageColor.getrgb("rgb(0%,100%,0%)"), + ImageColor.getrgb("rgb(0%,0%,100%)")] N = n*multiple out = [None]*N; for i in range(N): x = float(i)/N - out[i] = pid.Color(redfunc(x), greenfunc(x), bluefunc(x)); + out[i] = ImageColor.getrgb("rgb({}%,{}%,{}%".format( + *[int(i*100) for i in ( + redfunc(x), greenfunc(x), bluefunc(x))])) out2 = [out[0]] step = N/float(n-1) j = 0 @@ -290,4 +331,4 @@ def _test(): if __name__=="__main__": - _test() \ No newline at end of file + _test() diff --git a/wqflask/wqflask/marker_regression/display_mapping_results.py b/wqflask/wqflask/marker_regression/display_mapping_results.py index 25846099..39067fc5 100644 --- a/wqflask/wqflask/marker_regression/display_mapping_results.py +++ b/wqflask/wqflask/marker_regression/display_mapping_results.py @@ -27,7 +27,7 @@ import datetime import string from math import * -from PIL import (ImageColor) +from PIL import (Image,ImageDraw,ImageFont,ImageColor) import sys,os import cPickle import httplib @@ -70,6 +70,13 @@ DARKVIOLET = ImageColor.getrgb("darkviolet") MEDIUMPURPLE = ImageColor.getrgb("mediumpurple") # ---- END: Define common colours ---- # +# ---- FONT FILES ---- # +VERDANA_FILE = "fonts/ttf/verdana.ttf" +TREBUC_FILE = "fonts/ttf/trebucbd.ttf" +FNT_BS_FILE = "fonts/ttf/fnt_bs.ttf" +ARIAL_FILE = "fonts/ttf/arial.ttf" +# ---- END: FONT FILES ---- # + ######################################### # Inteval Mapping Plot Page ######################################### @@ -487,21 +494,28 @@ class DisplayMappingResults(object): # Plots goes here ################################################################ showLocusForm = "" - intCanvas = pid.PILCanvas(size=(self.graphWidth, self.graphHeight)) + intCanvas = Image.new("RGBA", size=(self.graphWidth, self.graphHeight)) with Bench("Drawing Plot"): gifmap = self.plotIntMapping(intCanvas, startMb = self.startMb, endMb = self.endMb, showLocusForm= showLocusForm) self.gifmap = gifmap.__str__() self.filename= webqtlUtil.genRandStr("Itvl_") - intCanvas.save(os.path.join(webqtlConfig.GENERATED_IMAGE_DIR, self.filename), format='png') + intCanvas.save( + "{}.png".format( + os.path.join(webqtlConfig.GENERATED_IMAGE_DIR, self.filename)), + format='png') intImg=HT.Image('/image/'+self.filename+'.png', border=0, usemap='#WebQTLImageMap') #Scales plot differently for high resolution if self.draw2X: - intCanvasX2 = pid.PILCanvas(size=(self.graphWidth*2,self.graphHeight*2)) + intCanvasX2 = Image.new("RGBA", size=(self.graphWidth*2,self.graphHeight*2)) gifmapX2 = self.plotIntMapping(intCanvasX2, startMb = self.startMb, endMb = self.endMb, showLocusForm= showLocusForm, zoom=2) - intCanvasX2.save(os.path.join(webqtlConfig.GENERATED_IMAGE_DIR, self.filename+"X2"), format='png') + intCanvasX2.save( + "{}.png".format( + os.path.join(webqtlConfig.GENERATED_IMAGE_DIR, + self.filename+"X2")), + format='png') ################################################################ # Outputs goes here @@ -529,6 +543,7 @@ class DisplayMappingResults(object): btminfo.append(HT.BR(), 'Mapping using genotype data as a trait will result in infinity LRS at one locus. In order to display the result properly, all LRSs higher than 100 are capped at 100.') def plotIntMapping(self, canvas, offset= (80, 120, 20, 100), zoom = 1, startMb = None, endMb = None, showLocusForm = ""): + im_drawer = ImageDraw.Draw(canvas) #calculating margins xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset if self.multipleInterval: @@ -622,6 +637,7 @@ class DisplayMappingResults(object): return gifmap def drawBootStrapResult(self, canvas, nboot, drawAreaHeight, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None): + im_drawer = ImageDraw.Draw(canvas) xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset plotWidth = canvas.size[0] - xLeftOffset - xRightOffset plotHeight = canvas.size[1] - yTopOffset - yBottomOffset @@ -708,8 +724,10 @@ class DisplayMappingResults(object): if item[1] > xLeftOffset+plotWidth: item[1] = xLeftOffset+plotWidth if item[0] != item[1]: - canvas.drawRect(item[0], yZero, item[1], yZero - item[2]*bootHeightThresh/maxBootCount, - fillColor=self.BOOTSTRAP_BOX_COLOR) + im_drawer.rectangle( + xy=((item[0], yZero), + (item[1], yZero - item[2]*bootHeightThresh/maxBootCount)), + fill=self.BOOTSTRAP_BOX_COLOR) ###draw boot scale highestPercent = (maxBootCount*100.0)/nboot @@ -718,26 +736,43 @@ class DisplayMappingResults(object): bootScale = bootScale[:-1] + [highestPercent] bootOffset = 50*fontZoom - bootScaleFont=pid.Font(ttf="verdana",size=13*fontZoom,bold=0) - canvas.drawRect(canvas.size[0]-bootOffset,yZero-bootHeightThresh,canvas.size[0]-bootOffset-15*zoom,yZero,fillColor = YELLOW) - canvas.drawLine(canvas.size[0]-bootOffset+4, yZero, canvas.size[0]-bootOffset, yZero, color=BLACK) - canvas.drawString('0%' ,canvas.size[0]-bootOffset+10,yZero+5,font=bootScaleFont,color=BLACK) + bootScaleFont=ImageFont.truetype(font=VERDANA_FILE,size=13*fontZoom) + im_drawer.rectangle( + xy=((canvas.size[0]-bootOffset, yZero-bootHeightThresh), + (canvas.size[0]-bootOffset-15*zoom,yZero)), + fill = YELLOW) + im_drawer.line( + xy=((canvas.size[0]-bootOffset+4, yZero), + (canvas.size[0]-bootOffset, yZero)), + fill=BLACK) + im_drawer.text(xy=(canvas.size[0]-bootOffset+10,yZero+5), text='0%', + font=bootScaleFont, fill=BLACK) + for item in bootScale: if item == 0: continue bootY = yZero-bootHeightThresh*item/highestPercent - canvas.drawLine(canvas.size[0]-bootOffset+4,bootY,canvas.size[0]-bootOffset,bootY,color=BLACK) - canvas.drawString('%2.1f'%item ,canvas.size[0]-bootOffset+10,bootY+5,font=bootScaleFont,color=BLACK) + im_drawer.line( + xy=((canvas.size[0]-bootOffset+4,bootY), + (canvas.size[0]-bootOffset,bootY)), + fill=BLACK) + im_drawer.text(xy=(canvas.size[0]-bootOffset+10,bootY+5), + text='%2.1f'%item, font=bootScaleFont, color=BLACK) if self.legendChecked: startPosY = 30 nCol = 2 - smallLabelFont = pid.Font(ttf="trebuc", size=12*fontZoom, bold=1) + smallLabelFont = ImageFont.truetype(font=TREBUC_FILE, size=12*fontZoom) leftOffset = xLeftOffset+(nCol-1)*200 - canvas.drawRect(leftOffset,startPosY-6, leftOffset+12,startPosY+6, fillColor=YELLOW) - canvas.drawString('Frequency of the Peak LRS',leftOffset+ 20, startPosY+5,font=smallLabelFont,color=BLACK) + im_drawer.rectangle( + xy=((leftOffset,startPosY-6), (leftOffset+12,startPosY+6)), + fill=YELLOW) + im_drawer.text(xy=(leftOffset+ 20, startPosY+5), + text='Frequency of the Peak LRS', + font=smallLabelFont, color=BLACK) def drawProbeSetPosition(self, canvas, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None): + im_drawer = ImageDraw.Draw(canvas) if len(self.traitList) != 1: return @@ -805,12 +840,15 @@ class DisplayMappingResults(object): break if locPixel >= 0 and self.plotScale == 'physic': traitPixel = ((locPixel, yZero), (locPixel-7, yZero+14), (locPixel+7, yZero+14)) - canvas.drawPolygon(traitPixel, edgeColor=BLACK, fillColor=self.TRANSCRIPT_LOCATION_COLOR, closed=1) + im_drawer.polygon( + xy=traitPixel, outline=BLACK, + fill=self.TRANSCRIPT_LOCATION_COLOR#, closed=1 + ) if self.legendChecked: startPosY = 15 nCol = 2 - smallLabelFont = pid.Font(ttf="trebuc", size=12*fontZoom, bold=1) + smallLabelFont = ImageFont.truetype(font=TREBUC_FILE, size=12*fontZoom) if self.manhattan_plot: leftOffset = xLeftOffset else: @@ -819,6 +857,7 @@ class DisplayMappingResults(object): canvas.drawString("Sequence Site", (leftOffset+15), (startPosY+5), smallLabelFont, self.TOP_RIGHT_INFO_COLOR) def drawSNPTrackNew(self, canvas, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None): + im_drawer = ImageDraw.Draw(canvas) if self.plotScale != 'physic' or self.selectedChr == -1 or not self.diffCol: return @@ -856,12 +895,15 @@ class DisplayMappingResults(object): if maxCount>0: for i in range(xLeftOffset, xLeftOffset + plotWidth): snpDensity = float(SNPCounts[i-xLeftOffset]*SNP_HEIGHT_MODIFIER/maxCount) - canvas.drawLine(i, drawSNPLocationY+(snpDensity)*zoom, i, drawSNPLocationY-(snpDensity)*zoom, color=self.SNP_COLOR, width=1) + im_drawer.line( + xy=((i, drawSNPLocationY+(snpDensity)*zoom), + (i, drawSNPLocationY-(snpDensity)*zoom)), + fill=self.SNP_COLOR, width=1) def drawMultiTraitName(self, fd, canvas, gifmap, showLocusForm, offset= (40, 120, 80, 10), zoom = 1): nameWidths = [] yPaddingTop = 10 - colorFont=pid.Font(ttf="trebuc",size=12,bold=1) + colorFont=ImageFont.truetype(font=TREBUC_FILE,size=12) if len(self.qtlresults) >20 and self.selectedChr > -1: rightShift = 20 rightShiftStep = 60 @@ -880,11 +922,16 @@ class DisplayMappingResults(object): rightShift += rightShiftStep name = thisTrait.displayName() - nameWidth = canvas.stringWidth(name,font=colorFont) + nameWidth, nameHeight = im_drawer.textsize(name,font=colorFont) nameWidths.append(nameWidth) - canvas.drawRect(rightShift,yPaddingTop+kstep*15, rectWidth+rightShift,yPaddingTop+10+kstep*15, fillColor=thisLRSColor) - canvas.drawString(name,rectWidth+2+rightShift,yPaddingTop+10+kstep*15,font=colorFont,color=BLACK) + im_drawer.rectangle( + xy=((rightShift,yPaddingTop+kstep*15), + (rectWidth+rightShift,yPaddingTop+10+kstep*15)), + fill=thisLRSColor) + im_drawer.text( + text=name,xy=(rectWidth+2+rightShift,yPaddingTop+10+kstep*15), + font=colorFont,fill=BLACK) if thisTrait.db: COORDS = "%d,%d,%d,%d" %(rectWidth+2+rightShift,yPaddingTop+kstep*15,rectWidth+2+rightShift+nameWidth,yPaddingTop+10+kstep*15,) HREF= "javascript:showDatabase3('%s','%s','%s','');" % (showLocusForm, thisTrait.db.name, thisTrait.name) @@ -892,6 +939,7 @@ class DisplayMappingResults(object): gifmap.areas.append(Areas) def drawLegendPanel(self, canvas, offset= (40, 120, 80, 10), zoom = 1): + im_drawer = ImageDraw.Draw(canvas) xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset plotWidth = canvas.size[0] - xLeftOffset - xRightOffset plotHeight = canvas.size[1] - yTopOffset - yBottomOffset @@ -900,45 +948,80 @@ class DisplayMappingResults(object): if zoom == 2: fontZoom = 1.5 - labelFont=pid.Font(ttf="trebuc",size=12*fontZoom, bold=1) + labelFont=ImageFont.truetype(font=TREBUC_FILE,size=12*fontZoom) startPosY = 15 stepPosY = 12*fontZoom if self.manhattan_plot != True: - canvas.drawLine(xLeftOffset,startPosY,xLeftOffset+32,startPosY,color=self.LRS_COLOR, width=2) - canvas.drawString(self.LRS_LOD, xLeftOffset+40,startPosY+5,font=labelFont,color=BLACK) + im_drawer.line( + xy=((xLeftOffset,startPosY),(xLeftOffset+32,startPosY)), + fill=self.LRS_COLOR, width=2) + im_drawer.text( + text=self.LRS_LOD, xy=(xLeftOffset+40,startPosY+5), + font=labelFont,fill=BLACK) startPosY += stepPosY if self.additiveChecked: startPosX = xLeftOffset - canvas.drawLine(startPosX,startPosY,startPosX+17,startPosY,color=self.ADDITIVE_COLOR_POSITIVE, width=2) - canvas.drawLine(startPosX+18,startPosY,startPosX+32,startPosY,color=self.ADDITIVE_COLOR_NEGATIVE, width=2) - canvas.drawString('Additive Effect',startPosX+40,startPosY+5,font=labelFont,color=BLACK) + im_drawer.line( + xy=((startPosX,startPosY),(startPosX+17,startPosY)), + fill=self.ADDITIVE_COLOR_POSITIVE, width=2) + im_drawer.line( + xy=((startPosX+18,startPosY),(startPosX+32,startPosY)), + fill=self.ADDITIVE_COLOR_NEGATIVE, width=2) + im_drawer.text( + text='Additive Effect',xy=(startPosX+40,startPosY+5), + font=labelFont,fill=BLACK) if self.genotype.type == 'intercross' and self.dominanceChecked: startPosX = xLeftOffset startPosY += stepPosY - canvas.drawLine(startPosX,startPosY,startPosX+17,startPosY,color=self.DOMINANCE_COLOR_POSITIVE, width=4) - canvas.drawLine(startPosX+18,startPosY,startPosX+35,startPosY,color=self.DOMINANCE_COLOR_NEGATIVE, width=4) - canvas.drawString('Dominance Effect',startPosX+42,startPosY+5,font=labelFont,color=BLACK) + im_drawer.line( + xy=((startPosX,startPosY),(startPosX+17,startPosY)), + fill=self.DOMINANCE_COLOR_POSITIVE, width=4) + im_drawer.line( + xy=((startPosX+18,startPosY),(startPosX+35,startPosY)), + fill=self.DOMINANCE_COLOR_NEGATIVE, width=4) + im_drawer.text( + text='Dominance Effect', xy=(startPosX+42,startPosY+5), + font=labelFont,fill=BLACK) if self.haplotypeAnalystChecked: startPosY += stepPosY startPosX = xLeftOffset - canvas.drawLine(startPosX,startPosY,startPosX+17,startPosY,color=self.HAPLOTYPE_POSITIVE, width=4) - canvas.drawLine(startPosX+18,startPosY,startPosX+35,startPosY,color=self.HAPLOTYPE_NEGATIVE, width=4) - canvas.drawLine(startPosX+36,startPosY,startPosX+53,startPosY,color=self.HAPLOTYPE_HETEROZYGOUS, width=4) - canvas.drawLine(startPosX+54,startPosY,startPosX+67,startPosY,color=self.HAPLOTYPE_RECOMBINATION, width=4) - canvas.drawString('Haplotypes (Pat, Mat, Het, Unk)',startPosX+76,startPosY+5,font=labelFont,color=BLACK) + im_drawer.line( + xy=((startPosX,startPosY),(startPosX+17,startPosY)), + fill=self.HAPLOTYPE_POSITIVE, width=4) + im_drawer.line( + xy=((startPosX+18,startPosY),(startPosX+35,startPosY)), + fill=self.HAPLOTYPE_NEGATIVE, width=4) + im_drawer.line( + xy=((startPosX+36,startPosY),(startPosX+53,startPosY)), + fill=self.HAPLOTYPE_HETEROZYGOUS, width=4) + im_drawer.line( + xy=((startPosX+54,startPosY),(startPosX+67,startPosY)), + fill=self.HAPLOTYPE_RECOMBINATION, width=4) + im_drawer.text( + text='Haplotypes (Pat, Mat, Het, Unk)', + xy=(startPosX+76,startPosY+5),font=labelFont,fill=BLACK) if self.permChecked and self.nperm > 0: startPosY += stepPosY startPosX = xLeftOffset - canvas.drawLine(startPosX, startPosY, startPosX + 32, startPosY, color=self.SIGNIFICANT_COLOR, width=self.SIGNIFICANT_WIDTH) - canvas.drawLine(startPosX, startPosY + stepPosY, startPosX + 32, startPosY + stepPosY, color=self.SUGGESTIVE_COLOR, width=self.SUGGESTIVE_WIDTH) - canvas.drawString('Significant %s = %2.2f' % (self.LRS_LOD, self.significant),xLeftOffset+42,startPosY +5,font=labelFont,color=BLACK) - canvas.drawString('Suggestive %s = %2.2f' % (self.LRS_LOD, self.suggestive),xLeftOffset+42,startPosY + 5 +stepPosY,font=labelFont,color=BLACK) - - labelFont = pid.Font(ttf="verdana",size=12*fontZoom) + im_drawer.line( + xy=((startPosX, startPosY),( startPosX + 32, startPosY)), + fill=self.SIGNIFICANT_COLOR, width=self.SIGNIFICANT_WIDTH) + im_drawer.line( + xy=((startPosX, startPosY + stepPosY),( startPosX + 32, startPosY + stepPosY)), + fill=self.SUGGESTIVE_COLOR, width=self.SUGGESTIVE_WIDTH) + im_drawer.text( + text='Significant %s = %2.2f' % (self.LRS_LOD,self.significant), + xy=(xLeftOffset+42,startPosY +5),font=labelFont,fill=BLACK) + im_drawer.text( + text='Suggestive %s = %2.2f' % (self.LRS_LOD, self.suggestive), + xy=(xLeftOffset+42,startPosY + 5 +stepPosY),font=labelFont, + fill=BLACK) + + labelFont = ImageFont.truetype(font=VERDANA_FILE,size=12*fontZoom) labelColor = BLACK if self.dataset.type == "Publish" or self.dataset.type == "Geno": dataset_label = self.dataset.fullname @@ -1000,20 +1083,32 @@ class DisplayMappingResults(object): identification += "Trait: %s" % (self.this_trait.name) identification += " with %s samples" % (self.n_samples) - d = 4+ max(canvas.stringWidth(identification, font=labelFont), canvas.stringWidth(string1, font=labelFont), canvas.stringWidth(string2, font=labelFont)) - canvas.drawString(identification,canvas.size[0] - xRightOffset-d,20*fontZoom,font=labelFont,color=labelColor) - else: - d = 4+ max(canvas.stringWidth(string1, font=labelFont), canvas.stringWidth(string2, font=labelFont)) - canvas.drawString(string1,canvas.size[0] - xRightOffset-d,35*fontZoom,font=labelFont,color=labelColor) - canvas.drawString(string2,canvas.size[0] - xRightOffset-d,50*fontZoom,font=labelFont,color=labelColor) - canvas.drawString(string3,canvas.size[0] - xRightOffset-d,65*fontZoom,font=labelFont,color=labelColor) - if string4 != '': - canvas.drawString(string4,canvas.size[0] - xRightOffset-d,80*fontZoom,font=labelFont,color=labelColor) - canvas.drawString("Created at: " + str(datetime.datetime.now()).split('.')[0], canvas.size[0] - xRightOffset-d,95*fontZoom,font=labelFont,color=labelColor) + d = 4+ max( + im_drawer.textsize(identification, font=labelFont)[0], + im_drawer.textsize(string1, font=labelFont)[0], + im_drawer.textsize(string2, font=labelFont)[0]) + im_drawer.text( + text=identification, + xy=(canvas.size[0] - xRightOffset-d,20*fontZoom),font=labelFont, + fill=labelColor) else: - canvas.drawString("Created at: " + str(datetime.datetime.now()).split('.')[0], canvas.size[0] - xRightOffset-d,80*fontZoom,font=labelFont,color=labelColor) + d = 4+ max( + im_drawer.textsize(string1, font=labelFont)[0], + im_drawer.textsize(string2, font=labelFont)[0]) + im_drawer.text( + text=string1,xy=(canvas.size[0] - xRightOffset-d,35*fontZoom), + font=labelFont,fill=labelColor) + im_drawer.text( + text=string2,xy=(canvas.size[0] - xRightOffset-d,50*fontZoom), + font=labelFont,fill=labelColor) + if string3 != '': + im_drawer.text( + text=string3,xy=(canvas.size[0] - xRightOffset-d,65*fontZoom), + font=labelFont,fill=labelColor) + def drawGeneBand(self, canvas, gifmap, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None): + im_drawer = ImageDraw.Draw(canvas) if self.plotScale != 'physic' or self.selectedChr == -1 or not self.geneCol: return @@ -1126,11 +1221,15 @@ class DisplayMappingResults(object): #draw the detail view if self.endMb - self.startMb <= self.DRAW_DETAIL_MB and geneEndPix - geneStartPix > self.EACH_GENE_ARROW_SPACING * 3: - utrColor = pid.Color(0.66, 0.66, 0.66) - arrowColor = pid.Color(0.7, 0.7, 0.7) + utrColor = ImageColor.getrgb("rgb(66%, 66%, 66%)") + arrowColor = ImageColor.getrgb("rgb(70%, 70%, 70%)") #draw the line that runs the entire length of the gene - canvas.drawLine(geneStartPix, geneYLocation + self.EACH_GENE_HEIGHT/2*zoom, geneEndPix, geneYLocation + self.EACH_GENE_HEIGHT/2*zoom, color=outlineColor, width=1) + im_drawer.line( + xy=( + (geneStartPix, geneYLocation + self.EACH_GENE_HEIGHT/2*zoom), + ( geneEndPix, geneYLocation + self.EACH_GENE_HEIGHT/2*zoom)), + fill=outlineColor, width=1) #draw the arrows if geneEndPix - geneStartPix < 1: @@ -1141,11 +1240,30 @@ class DisplayMappingResults(object): if (xCoord % self.EACH_GENE_ARROW_SPACING == 0 and xCoord + self.EACH_GENE_ARROW_SPACING < geneEndPix-geneStartPix) or xCoord == 0: if strand == "+": - canvas.drawLine(geneStartPix + xCoord, geneYLocation, geneStartPix + xCoord + self.EACH_GENE_ARROW_WIDTH, geneYLocation +(self.EACH_GENE_HEIGHT / 2)*zoom, color=arrowColor, width=1) - canvas.drawLine(geneStartPix + xCoord, geneYLocation + self.EACH_GENE_HEIGHT*zoom, geneStartPix + xCoord+self.EACH_GENE_ARROW_WIDTH, geneYLocation + (self.EACH_GENE_HEIGHT / 2) * zoom, color=arrowColor, width=1) + im_drawer.line( + xy=((geneStartPix + xCoord, geneYLocation), + (geneStartPix + xCoord + self.EACH_GENE_ARROW_WIDTH, + geneYLocation +(self.EACH_GENE_HEIGHT / 2)*zoom)), + fill=arrowColor, width=1) + im_drawer.line( + xy=((geneStartPix + xCoord, + geneYLocation + self.EACH_GENE_HEIGHT*zoom), + (geneStartPix + xCoord+self.EACH_GENE_ARROW_WIDTH, + geneYLocation + (self.EACH_GENE_HEIGHT / 2) * zoom)), + fill=arrowColor, width=1) else: - canvas.drawLine(geneStartPix + xCoord + self.EACH_GENE_ARROW_WIDTH, geneYLocation, geneStartPix + xCoord, geneYLocation +(self.EACH_GENE_HEIGHT / 2)*zoom, color=arrowColor, width=1) - canvas.drawLine(geneStartPix + xCoord + self.EACH_GENE_ARROW_WIDTH, geneYLocation + self.EACH_GENE_HEIGHT*zoom, geneStartPix + xCoord, geneYLocation + (self.EACH_GENE_HEIGHT / 2)*zoom, color=arrowColor, width=1) + im_drawer.line( + xy=((geneStartPix + xCoord + self.EACH_GENE_ARROW_WIDTH, + geneYLocation), + ( geneStartPix + xCoord, + geneYLocation +(self.EACH_GENE_HEIGHT / 2)*zoom)), + fill=arrowColor, width=1) + im_drawer.line( + xy=((geneStartPix + xCoord + self.EACH_GENE_ARROW_WIDTH, + geneYLocation + self.EACH_GENE_HEIGHT*zoom), + ( geneStartPix + xCoord, + geneYLocation + (self.EACH_GENE_HEIGHT / 2)*zoom)), + fill=arrowColor, width=1) #draw the blocks for the exon regions for i in range(0, len(exonStarts)): @@ -1159,7 +1277,10 @@ class DisplayMappingResults(object): exonEndPix = xLeftOffset + plotWidth if (exonStartPix > xLeftOffset + plotWidth): exonStartPix = xLeftOffset + plotWidth - canvas.drawRect(exonStartPix, geneYLocation, exonEndPix, (geneYLocation + self.EACH_GENE_HEIGHT*zoom), edgeColor = outlineColor, fillColor = fillColor) + im_drawer.rectangle( + xy=((exonStartPix, geneYLocation), + (exonEndPix, (geneYLocation + self.EACH_GENE_HEIGHT*zoom))), + outline = outlineColor, fill = fillColor) #draw gray blocks for 3' and 5' UTR blocks if cdsStart and cdsEnd: @@ -1173,14 +1294,16 @@ class DisplayMappingResults(object): utrEndPix = xLeftOffset + plotWidth if (utrStartPix > xLeftOffset + plotWidth): utrStartPix = xLeftOffset + plotWidth - #canvas.drawRect(utrStartPix, geneYLocation, utrEndPix, (geneYLocation+self.EACH_GENE_HEIGHT*zoom), edgeColor=utrColor, fillColor =utrColor) if self.endMb - self.startMb <= self.DRAW_UTR_LABELS_MB: if strand == "-": labelText = "3'" else: labelText = "5'" - canvas.drawString(labelText, utrStartPix-9, geneYLocation+self.EACH_GENE_HEIGHT, pid.Font(face="helvetica", size=2)) + im_drawer.text( + text=labelText, + xy=(utrStartPix-9, geneYLocation+self.EACH_GENE_HEIGHT), + font=ImageFont.truetype(font=ARIAL_FILE, size=2)) #the second UTR region @@ -1194,18 +1317,23 @@ class DisplayMappingResults(object): utrEndPix = xLeftOffset + plotWidth if (utrStartPix > xLeftOffset + plotWidth): utrStartPix = xLeftOffset + plotWidth - #canvas.drawRect(utrStartPix, geneYLocation, utrEndPix, (geneYLocation+self.EACH_GENE_HEIGHT*zoom), edgeColor=utrColor, fillColor =utrColor) if self.endMb - self.startMb <= self.DRAW_UTR_LABELS_MB: if strand == "-": labelText = "5'" else: labelText = "3'" - canvas.drawString(labelText, utrEndPix+2, geneYLocation+self.EACH_GENE_HEIGHT, pid.Font(face="helvetica", size=2)) + im_drawer.text( + text=labelText, + xy=(utrEndPix+2,geneYLocation+self.EACH_GENE_HEIGHT), + font=ImageFont.truetype(font=ARIAL_FILE, size=2)) #draw the genes as rectangles else: - canvas.drawRect(geneStartPix, geneYLocation, geneEndPix, (geneYLocation + self.EACH_GENE_HEIGHT*zoom), edgeColor = outlineColor, fillColor = fillColor) + im_drawer.rectangle( + xy=((geneStartPix, geneYLocation), + (geneEndPix, (geneYLocation + self.EACH_GENE_HEIGHT*zoom))), + outline= outlineColor, fill = fillColor) COORDS = "%d, %d, %d, %d" %(geneStartPix, geneYLocation, geneEndPix, (geneYLocation + self.EACH_GENE_HEIGHT)) # NL: 06-02-2011 Rob required to display NCBI info in a new window @@ -1354,12 +1482,22 @@ class DisplayMappingResults(object): else: mylineColor = self.HAPLOTYPE_RECOMBINATION # XZ: Unknown - canvas.drawLine(drawStart, geneYLocation+7+2*ind*self.EACH_GENE_HEIGHT*zoom, drawEnd, geneYLocation+7+2*ind*self.EACH_GENE_HEIGHT*zoom, color = mylineColor, width=zoom*(self.EACH_GENE_HEIGHT+2)) + im_drawer.line( + xy=((drawStart, + geneYLocation+7+2*ind*self.EACH_GENE_HEIGHT*zoom), + (drawEnd, + geneYLocation+7+2*ind*self.EACH_GENE_HEIGHT*zoom)), + fill= mylineColor, width=zoom*(self.EACH_GENE_HEIGHT+2)) fillColor=BLACK outlineColor=BLACK if lastGene == 0: - canvas.drawRect(geneStartPix, geneYLocation+2*ind*self.EACH_GENE_HEIGHT*zoom, geneEndPix, geneYLocation+2*ind*self.EACH_GENE_HEIGHT+ 2*self.EACH_GENE_HEIGHT*zoom, edgeColor = outlineColor, fillColor = fillColor) + im_drawer.rectangle( + xy=((geneStartPix, + geneYLocation+2*ind*self.EACH_GENE_HEIGHT*zoom), + (geneEndPix, + geneYLocation+2*ind*self.EACH_GENE_HEIGHT+ 2*self.EACH_GENE_HEIGHT*zoom)), + outline=outlineColor, fill=fillColor) COORDS = "%d, %d, %d, %d" %(geneStartPix, geneYLocation+ind*self.EACH_GENE_HEIGHT, geneEndPix+1, (geneYLocation + ind*self.EACH_GENE_HEIGHT)) @@ -1372,11 +1510,21 @@ class DisplayMappingResults(object): if (plotRight < (xLeftOffset + plotWidth - 3)) and (lastGene == 0): drawEnd = xLeftOffset + plotWidth - 6 mylineColor = self.HAPLOTYPE_RECOMBINATION - canvas.drawLine(plotRight, geneYLocation+7+2*ind*self.EACH_GENE_HEIGHT*zoom, drawEnd, geneYLocation+7+2*ind*self.EACH_GENE_HEIGHT*zoom, color = mylineColor, width=zoom*(self.EACH_GENE_HEIGHT+2)) + im_drawer.line( + xy=((plotRight, + geneYLocation+7+2*ind*self.EACH_GENE_HEIGHT*zoom), + (drawEnd, + geneYLocation+7+2*ind*self.EACH_GENE_HEIGHT*zoom)), + fill= mylineColor, width=zoom*(self.EACH_GENE_HEIGHT+2)) if lastGene == 0: - canvas.drawString("%s" % (_chr[j].name), geneStartPix , geneYLocation+17+2*maxind*self.EACH_GENE_HEIGHT*zoom, font=pid.Font(ttf="verdana", size=12, bold=0), color=BLACK, angle=-90) + im_drawer.text( + text="%s" % (_chr[j].name), + xy=(geneStartPix, + geneYLocation+17+2*maxind*self.EACH_GENE_HEIGHT*zoom), + font=ImageFont.truetype(font=VERDANA_FILE, size=12), + fill=BLACK, angle=-90) oldgeneEndPix = geneEndPix; oldgeno = _chr[j].genotype @@ -1405,12 +1553,23 @@ class DisplayMappingResults(object): expr = item.value # Place where font is hardcoded - canvas.drawString("%s" % (samplelist[j]), (xLeftOffset + plotWidth + 10) , geneYLocation+8+2*ind*self.EACH_GENE_HEIGHT*zoom, font=pid.Font(ttf="verdana", size=12, bold=0), color=BLACK) - canvas.drawString("%2.2f" % (expr), (xLeftOffset + plotWidth + 60) , geneYLocation+8+2*ind*self.EACH_GENE_HEIGHT*zoom, font=pid.Font(ttf="verdana", size=12, bold=0), color=BLACK) + im_drawer.text( + text="%s" % (samplelist[j]), + xy=((xLeftOffset + plotWidth + 10), + geneYLocation+8+2*ind*self.EACH_GENE_HEIGHT*zoom), + font=ImageFont.truetype(font=VERDANA_FILE, size=12), + fill=BLACK) + im_drawer.text( + text="%2.2f" % (expr), + xy=((xLeftOffset + plotWidth + 60), + geneYLocation+8+2*ind*self.EACH_GENE_HEIGHT*zoom), + font=ImageFont.truetype(font=VERDANA_FILE, size=12), + fill=BLACK) ## END HaplotypeAnalyst def drawClickBand(self, canvas, gifmap, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None): + im_drawer = ImageDraw.Draw(canvas) if self.plotScale != 'physic' or self.selectedChr == -1: return @@ -1426,7 +1585,7 @@ class DisplayMappingResults(object): # but it makes the HTML huge, and takes forever to render the page in the first place) # Draw the bands that you can click on to go to UCSC / Ensembl MAX_CLICKABLE_REGION_DIVISIONS = 100 - clickableRegionLabelFont=pid.Font(ttf="verdana", size=9, bold=0) + clickableRegionLabelFont=ImageFont.truetype(font=VERDANA_FILE, size=9) pixelStep = max(5, int(float(plotWidth)/MAX_CLICKABLE_REGION_DIVISIONS)) # pixelStep: every N pixels, we make a new clickable area for the user to go to that area of the genome. @@ -1463,8 +1622,14 @@ class DisplayMappingResults(object): WEBQTL_TITLE = "Click to view this section of the genome in WebQTL" gifmap.areas.append(HT.Area(shape='rect',coords=WEBQTL_COORDS,href=WEBQTL_HREF, title=WEBQTL_TITLE)) - canvas.drawRect(xBrowse1, paddingTop, xBrowse2, (paddingTop + self.BAND_HEIGHT), edgeColor=self.CLICKABLE_WEBQTL_REGION_COLOR, fillColor=self.CLICKABLE_WEBQTL_REGION_COLOR) - canvas.drawLine(xBrowse1, paddingTop, xBrowse1, (paddingTop + self.BAND_HEIGHT), color=self.CLICKABLE_WEBQTL_REGION_OUTLINE_COLOR) + im_drawer.rectangle( + xy=((xBrowse1, paddingTop), + (xBrowse2, (paddingTop + self.BAND_HEIGHT))), + outline=self.CLICKABLE_WEBQTL_REGION_COLOR, + fill=self.CLICKABLE_WEBQTL_REGION_COLOR) + im_drawer.line( + xy=((xBrowse1, paddingTop),( xBrowse1, (paddingTop + self.BAND_HEIGHT))), + fill=self.CLICKABLE_WEBQTL_REGION_OUTLINE_COLOR) if self.dataset.group.species == "mouse" or self.dataset.group.species == "rat": PHENOGEN_COORDS = "%d, %d, %d, %d" % (xBrowse1, phenogenPaddingTop, xBrowse2, (phenogenPaddingTop+self.BAND_HEIGHT)) @@ -1474,8 +1639,14 @@ class DisplayMappingResults(object): PHENOGEN_HREF = "https://phenogen.org/gene.jsp?speciesCB=Mm&auto=Y&geneTxt=chr%s:%d-%d&genomeVer=mm10" % (self.selectedChr, max(0, calBase-flankingWidthInBases), calBase+flankingWidthInBases) PHENOGEN_TITLE = "Click to view this section of the genome in PhenoGen" gifmap.areas.append(HT.Area(shape='rect',coords=PHENOGEN_COORDS,href=PHENOGEN_HREF, title=PHENOGEN_TITLE)) - canvas.drawRect(xBrowse1, phenogenPaddingTop, xBrowse2, (phenogenPaddingTop+self.BAND_HEIGHT), edgeColor=self.CLICKABLE_PHENOGEN_REGION_COLOR, fillColor=self.CLICKABLE_PHENOGEN_REGION_COLOR) - canvas.drawLine(xBrowse1, phenogenPaddingTop, xBrowse1, (phenogenPaddingTop+self.BAND_HEIGHT), color=self.CLICKABLE_PHENOGEN_REGION_OUTLINE_COLOR) + im_drawer.rectangle( + xy=((xBrowse1, phenogenPaddingTop), + (xBrowse2, (phenogenPaddingTop+self.BAND_HEIGHT))), + outline=self.CLICKABLE_PHENOGEN_REGION_COLOR, + fill=self.CLICKABLE_PHENOGEN_REGION_COLOR) + im_drawer.line( + xy=((xBrowse1, phenogenPaddingTop),( xBrowse1, (phenogenPaddingTop+self.BAND_HEIGHT))), + fill=self.CLICKABLE_PHENOGEN_REGION_OUTLINE_COLOR) UCSC_COORDS = "%d, %d, %d, %d" %(xBrowse1, ucscPaddingTop, xBrowse2, (ucscPaddingTop+self.BAND_HEIGHT)) if self.dataset.group.species == "mouse": @@ -1484,8 +1655,15 @@ class DisplayMappingResults(object): UCSC_HREF = "http://genome.ucsc.edu/cgi-bin/hgTracks?db=%s&position=chr%s:%d-%d" % (self._ucscDb, self.selectedChr, max(0, calBase-flankingWidthInBases), calBase+flankingWidthInBases) UCSC_TITLE = "Click to view this section of the genome in the UCSC Genome Browser" gifmap.areas.append(HT.Area(shape='rect',coords=UCSC_COORDS,href=UCSC_HREF, title=UCSC_TITLE)) - canvas.drawRect(xBrowse1, ucscPaddingTop, xBrowse2, (ucscPaddingTop+self.BAND_HEIGHT), edgeColor=self.CLICKABLE_UCSC_REGION_COLOR, fillColor=self.CLICKABLE_UCSC_REGION_COLOR) - canvas.drawLine(xBrowse1, ucscPaddingTop, xBrowse1, (ucscPaddingTop+self.BAND_HEIGHT), color=self.CLICKABLE_UCSC_REGION_OUTLINE_COLOR) + im_drawer.rectangle( + xy=((xBrowse1, ucscPaddingTop), + (xBrowse2, (ucscPaddingTop+self.BAND_HEIGHT))), + outline=self.CLICKABLE_UCSC_REGION_COLOR, + fill=self.CLICKABLE_UCSC_REGION_COLOR) + im_drawer.line( + xy=((xBrowse1, ucscPaddingTop), + (xBrowse1, (ucscPaddingTop+self.BAND_HEIGHT))), + fill=self.CLICKABLE_UCSC_REGION_OUTLINE_COLOR) ENSEMBL_COORDS = "%d, %d, %d, %d" %(xBrowse1, ensemblPaddingTop, xBrowse2, (ensemblPaddingTop+self.BAND_HEIGHT)) if self.dataset.group.species == "mouse": @@ -1494,32 +1672,59 @@ class DisplayMappingResults(object): ENSEMBL_HREF = "http://www.ensembl.org/Rattus_norvegicus/contigview?chr=%s&start=%d&end=%d" % (self.selectedChr, max(0, calBase-flankingWidthInBases), calBase+flankingWidthInBases) ENSEMBL_TITLE = "Click to view this section of the genome in the Ensembl Genome Browser" gifmap.areas.append(HT.Area(shape='rect',coords=ENSEMBL_COORDS,href=ENSEMBL_HREF, title=ENSEMBL_TITLE)) - canvas.drawRect(xBrowse1, ensemblPaddingTop, xBrowse2, (ensemblPaddingTop+self.BAND_HEIGHT), edgeColor=self.CLICKABLE_ENSEMBL_REGION_COLOR, fillColor=self.CLICKABLE_ENSEMBL_REGION_COLOR) - canvas.drawLine(xBrowse1, ensemblPaddingTop, xBrowse1, (ensemblPaddingTop+self.BAND_HEIGHT), color=self.CLICKABLE_ENSEMBL_REGION_OUTLINE_COLOR) + im_drawer.rectangle( + xy=((xBrowse1, ensemblPaddingTop), + (xBrowse2, (ensemblPaddingTop+self.BAND_HEIGHT))), + outline=self.CLICKABLE_ENSEMBL_REGION_COLOR, + fill=self.CLICKABLE_ENSEMBL_REGION_COLOR) + im_drawer.line( + xy=((xBrowse1, ensemblPaddingTop), + (xBrowse1, (ensemblPaddingTop+self.BAND_HEIGHT))), + fill=self.CLICKABLE_ENSEMBL_REGION_OUTLINE_COLOR) # end for - canvas.drawString("Click to view the corresponding section of the genome in an 8x expanded WebQTL map", (xLeftOffset + 10), paddingTop + self.BAND_HEIGHT/2, font=clickableRegionLabelFont, color=self.CLICKABLE_WEBQTL_TEXT_COLOR) + im_drawer.text( + text="Click to view the corresponding section of the genome in an 8x expanded WebQTL map", + xy=((xLeftOffset + 10), paddingTop + self.BAND_HEIGHT/2), + font=clickableRegionLabelFont, + fill=self.CLICKABLE_WEBQTL_TEXT_COLOR) if self.dataset.group.species == "mouse" or self.dataset.group.species == "rat": - canvas.drawString("Click to view the corresponding section of the genome in PhenoGen", (xLeftOffset + 10), phenogenPaddingTop + self.BAND_HEIGHT/2, font=clickableRegionLabelFont, color=self.CLICKABLE_PHENOGEN_TEXT_COLOR) - canvas.drawString("Click to view the corresponding section of the genome in the UCSC Genome Browser", (xLeftOffset + 10), ucscPaddingTop + self.BAND_HEIGHT/2, font=clickableRegionLabelFont, color=self.CLICKABLE_UCSC_TEXT_COLOR) - canvas.drawString("Click to view the corresponding section of the genome in the Ensembl Genome Browser", (xLeftOffset+10), ensemblPaddingTop + self.BAND_HEIGHT/2, font=clickableRegionLabelFont, color=self.CLICKABLE_ENSEMBL_TEXT_COLOR) + im_drawer.text( + text="Click to view the corresponding section of the genome in PhenoGen", + xy=((xLeftOffset + 10), phenogenPaddingTop + self.BAND_HEIGHT/2), + font=clickableRegionLabelFont, fill=self.CLICKABLE_PHENOGEN_TEXT_COLOR) + im_drawer.text( + text="Click to view the corresponding section of the genome in the UCSC Genome Browser", + xy=((xLeftOffset + 10), ucscPaddingTop + self.BAND_HEIGHT/2), + font=clickableRegionLabelFont, fill=self.CLICKABLE_UCSC_TEXT_COLOR) + im_drawer.text( + text="Click to view the corresponding section of the genome in the Ensembl Genome Browser", + xy=((xLeftOffset+10), ensemblPaddingTop + self.BAND_HEIGHT/2), + font=clickableRegionLabelFont, fill=self.CLICKABLE_ENSEMBL_TEXT_COLOR) #draw the gray text - chrFont = pid.Font(ttf="verdana", size=26*zoom, bold=1) - traitFont = pid.Font(ttf="verdana", size=14, bold=0) - chrX = xLeftOffset + plotWidth - 2 - canvas.stringWidth("Chr %s" % self.ChrList[self.selectedChr][0], font=chrFont) - canvas.drawString("Chr %s" % self.ChrList[self.selectedChr][0], chrX, ensemblPaddingTop-5, font=chrFont, color=GRAY) + chrFont = ImageFont.truetype(font=VERDANA_FILE, size=26*zoom) + traitFont = ImageFont.truetype(font=VERDANA_FILE, size=14) + chrX = xLeftOffset + plotWidth - 2 - im_drawer.textsize( + "Chr %s" % self.ChrList[self.selectedChr][0], font=chrFont)[0] + im_drawer.text( + text="Chr %s" % self.ChrList[self.selectedChr][0], + xy=(chrX, ensemblPaddingTop-5), font=chrFont, fill=GRAY) # end of drawBrowserClickableRegions else: #draw the gray text - chrFont = pid.Font(ttf="verdana", size=26*zoom, bold=1) - traitFont = pid.Font(ttf="verdana", size=14, bold=0) - chrX = xLeftOffset + (plotWidth - canvas.stringWidth("Chr %s" % currentChromosome, font=chrFont))/2 - canvas.drawString("Chr %s" % currentChromosome, chrX, 32, font=chrFont, color=GRAY) + chrFont = ImageFont.truetype(font=VERDANA_FILE, size=26*zoom) + traitFont = ImageFont.truetype(font=VERDANA_FILE, size=14) + chrX = xLeftOffset + (plotWidth - im_drawer.textsize( + "Chr %s" % currentChromosome, font=chrFont)[0])/2 + im_drawer.text( + text="Chr %s" % currentChromosome, xy=(chrX, 32), font=chrFont, + fill=GRAY) # end of drawBrowserClickableRegions pass def drawXAxis(self, canvas, drawAreaHeight, gifmap, plotXScale, showLocusForm, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None): + im_drawer = ImageDraw.Draw(canvas) xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset plotWidth = canvas.size[0] - xLeftOffset - xRightOffset plotHeight = canvas.size[1] - yTopOffset - yBottomOffset @@ -1535,7 +1740,7 @@ class DisplayMappingResults(object): X_AXIS_THICKNESS = 1*zoom # ======= Alex: Draw the X-axis labels (megabase location) - MBLabelFont = pid.Font(ttf="verdana", size=15*zoom, bold=0) + MBLabelFont = ImageFont.truetype(font=VERDANA_FILE, size=15*zoom) xMajorTickHeight = 10 * zoom # How high the tick extends below the axis xMinorTickHeight = 5*zoom xAxisTickMarkColor = BLACK @@ -1544,7 +1749,7 @@ class DisplayMappingResults(object): spacingFromLabelToAxis = 5 if self.plotScale == 'physic': - strYLoc = yZero + spacingFromLabelToAxis + canvas.fontHeight(MBLabelFont) + strYLoc = yZero + spacingFromLabelToAxis + MBLabelFont.font.height ###Physical single chromosome view if self.selectedChr > -1: XScale = Plot.detScale(startMb, endMb) @@ -1565,13 +1770,21 @@ class DisplayMappingResults(object): continue Xc = xLeftOffset + plotXScale*(_Mb - startMb) if counter % NUM_MINOR_TICKS == 0: # Draw a MAJOR mark, not just a minor tick mark - canvas.drawLine(Xc, yZero, Xc, yZero+xMajorTickHeight, color=xAxisTickMarkColor, width=X_MAJOR_TICK_THICKNESS) # Draw the MAJOR tick mark + im_drawer.line(xy=((Xc,yZero), + (Xc,yZero+xMajorTickHeight)), + fill=xAxisTickMarkColor, + width=X_MAJOR_TICK_THICKNESS) # Draw the MAJOR tick mark labelStr = str(formatStr % _Mb) # What Mbase location to put on the label - strWidth = canvas.stringWidth(labelStr, font=MBLabelFont) + strWidth, strHeight = im_drawer.textsize(labelStr, font=MBLabelFont) drawStringXc = (Xc - (strWidth / 2.0)) - canvas.drawString(labelStr, drawStringXc, strYLoc, font=MBLabelFont, color=xAxisLabelColor, angle=0) + im_drawer.text(xy=(drawStringXc, strYLoc), + text=labelStr, font=MBLabelFont, + fill=xAxisLabelColor) else: - canvas.drawLine(Xc, yZero, Xc, yZero+xMinorTickHeight, color=xAxisTickMarkColor, width=X_MINOR_TICK_THICKNESS) # Draw the MINOR tick mark + im_drawer.line(xy=((Xc,yZero), + (Xc,yZero+xMinorTickHeight)), + fill=xAxisTickMarkColor, + width=X_MINOR_TICK_THICKNESS) # Draw the MINOR tick mark ###Physical genome wide view else: @@ -1586,17 +1799,27 @@ class DisplayMappingResults(object): else: distScale = 5 for j, tickdists in enumerate(range(distScale, int(ceil(distLen)), distScale)): - canvas.drawLine(startPosX + tickdists*plotXScale, yZero, startPosX + tickdists*plotXScale, yZero + 7, color=BLACK, width=1*zoom) + im_drawer.line( + xy=((startPosX+tickdists*plotXScale, yZero), + (startPosX+tickdists*plotXScale, yZero + 7)), + fill=BLACK, width=1*zoom) if j % 2 == 0: - canvas.drawString(str(tickdists), startPosX+tickdists*plotXScale, yZero + 10*zoom, color=BLACK, font=MBLabelFont, angle=270) + im_drawer.text( + xy=(startPosX+tickdists*plotXScale, yZero+10*zoom), + text=str(tickdists), fill=BLACK, font=MBLabelFont, angle=270) startPosX += (self.ChrLengthDistList[i]+self.GraphInterval)*plotXScale - megabaseLabelFont = pid.Font(ttf="verdana", size=18*zoom*1.5, bold=0) - canvas.drawString("Megabases", xLeftOffset + (plotWidth - canvas.stringWidth("Megabases", font=megabaseLabelFont))/2, - strYLoc + canvas.fontHeight(MBLabelFont)+ 10*(zoom%2) + 10, font=megabaseLabelFont, color=BLACK) + megabaseLabelFont = ImageFont.truetype(font=VERDANA_FILE, size=int(18*zoom*1.5)) + im_drawer.text( + text="Megabases", + xy=( + xLeftOffset+(plotWidth-im_drawer.textsize( + "Megabases",font=megabaseLabelFont)[0])/2, + strYLoc+MBLabelFont.font.height+10*(zoom%2)+ 10), + font=megabaseLabelFont, fill=BLACK) pass else: - strYLoc = yZero + spacingFromLabelToAxis + canvas.fontHeight(MBLabelFont) + 8 + strYLoc = yZero + spacingFromLabelToAxis + MBLabelFont.font.height + 8 ChrAInfo = [] preLpos = -1 distinctCount = 0.0 @@ -1659,18 +1882,26 @@ class DisplayMappingResults(object): else: Zorder = 0 if differ: - canvas.drawLine(startPosX+Lpos,yZero,xLeftOffset+offsetA,\ - yZero+25, color=lineColor) - canvas.drawLine(xLeftOffset+offsetA,yZero+25,xLeftOffset+offsetA,\ - yZero+40+Zorder*(LRectWidth+3),color=lineColor) + im_drawer.line( + xy=((startPosX+Lpos,yZero),(xLeftOffset+offsetA,\ + yZero+25)), + fill=lineColor) + im_drawer.line( + xy=((xLeftOffset+offsetA,yZero+25),(xLeftOffset+offsetA,\ + yZero+40+Zorder*(LRectWidth+3))), + fill=lineColor) rectColor = ORANGE else: - canvas.drawLine(xLeftOffset+offsetA, yZero+40+Zorder*(LRectWidth+3)-3,\ - xLeftOffset+offsetA, yZero+40+Zorder*(LRectWidth+3),color=lineColor) + im_drawer.line( + xy=((xLeftOffset+offsetA, yZero+40+Zorder*(LRectWidth+3)-3),(\ + xLeftOffset+offsetA, yZero+40+Zorder*(LRectWidth+3))), + fill=lineColor) rectColor = DEEPPINK - canvas.drawRect(xLeftOffset+offsetA, yZero+40+Zorder*(LRectWidth+3),\ - xLeftOffset+offsetA-LRectHeight,yZero+40+Zorder*(LRectWidth+3)+LRectWidth,\ - edgeColor=rectColor,fillColor=rectColor,edgeWidth = 0) + im_drawer.rectangle( + xy=((xLeftOffset+offsetA, yZero+40+Zorder*(LRectWidth+3)), + (xLeftOffset+offsetA-LRectHeight, + yZero+40+Zorder*(LRectWidth+3)+LRectWidth)), + outline=rectColor,fill=rectColor,width = 0) COORDS="%d,%d,%d,%d"%(xLeftOffset+offsetA-LRectHeight, yZero+40+Zorder*(LRectWidth+3),\ xLeftOffset+offsetA,yZero+40+Zorder*(LRectWidth+3)+LRectWidth) HREF="/show_trait?trait_id=%s&dataset=%s" % (Lname, self.dataset.group.name+"Geno") @@ -1679,17 +1910,25 @@ class DisplayMappingResults(object): gifmap.areas.append(Areas) ##piddle bug if j == 0: - canvas.drawLine(startPosX,yZero,startPosX,yZero+40, color=lineColor) + im_drawer.line( + xy=((startPosX,yZero),(startPosX,yZero+40)), + fill=lineColor) startPosX += (self.ChrLengthDistList[j]+self.GraphInterval)*plotXScale - centimorganLabelFont = pid.Font(ttf="verdana", size=18*zoom*1.5, bold=0) - canvas.drawString("Centimorgans", xLeftOffset + (plotWidth - canvas.stringWidth("Megabases", font=centimorganLabelFont))/2, - strYLoc + canvas.fontHeight(MBLabelFont)+ 10*(zoom%2) + 10, font=centimorganLabelFont, color=BLACK) + centimorganLabelFont = ImageFont.truetype(font=VERDANA_FILE, size=18*zoom*1.5) + im_drawer.text( + text="Centimorgans", + xy=(xLeftOffset+(plotWidth-im_drawer.textsize( + "Megabases", font=centimorganLabelFont)[0])/2, + strYLoc + MBLabelFont.font.height+ 10*(zoom%2) + 10), + font=centimorganLabelFont, fill=BLACK) - canvas.drawLine(xLeftOffset, yZero, xLeftOffset+plotWidth, yZero, color=BLACK, width=X_AXIS_THICKNESS) # Draw the X axis itself + im_drawer.line(xy=((xLeftOffset,yZero), (xLeftOffset+plotWidth,yZero)), + fill=BLACK, width=X_AXIS_THICKNESS) # Draw the X axis itself def drawQTL(self, canvas, drawAreaHeight, gifmap, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None): + im_drawer = ImageDraw.Draw(canvas) xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset plotWidth = canvas.size[0] - xLeftOffset - xRightOffset plotHeight = canvas.size[1] - yTopOffset - yBottomOffset @@ -1787,29 +2026,40 @@ class DisplayMappingResults(object): else: all_int = False break - - if all_int: - max_lrs_width = canvas.stringWidth("%d" % LRS_LOD_Max, font=LRSScaleFont) + 40 - else: - max_lrs_width = canvas.stringWidth("%2.1f" % LRS_LOD_Max, font=LRSScaleFont) + 30 + # TODO(PIL): Convert from PIL + # if all_int: + # max_lrs_width = canvas.stringWidth("%d" % LRS_LOD_Max, font=LRSScaleFont) + 40 + # else: + # max_lrs_width = canvas.stringWidth("%2.1f" % LRS_LOD_Max, font=LRSScaleFont) + 30 #draw the "LRS" or "LOD" string to the left of the axis - canvas.drawString(self.LRS_LOD, xLeftOffset - max_lrs_width - 15*(zoom-1), \ - yZero - 150 - 300*(zoom - 1), font=LRSLODFont, color=BLACK, angle=90) + LRSScaleFont=ImageFont.truetype(font=VERDANA_FILE, size=16*zoom) + LRSLODFont=ImageFont.truetype(font=VERDANA_FILE, size=int(18*zoom*1.5)) + yZero = yTopOffset + plotHeight + + im_drawer.text( + text=self.LRS_LOD, + xy=(xLeftOffset - im_drawer.textsize("999.99", font=LRSScaleFont)[0] - 15*(zoom-1), + yZero - 150 - 300*(zoom - 1)), + font=LRSLODFont, fill=BLACK, angle=90) for item in LRSAxisList: if LRS_LOD_Max == 0.0: LRS_LOD_Max = 0.000001 yTopOffset + 30*(zoom - 1) yLRS = yZero - (item/LRS_LOD_Max) * LRSHeightThresh - #yLRS = yZero - (item/LRSAxisList[-1]) * LRSHeightThresh - canvas.drawLine(xLeftOffset, yLRS, xLeftOffset - 4, yLRS, color=self.LRS_COLOR, width=1*zoom) + im_drawer.line(xy=((xLeftOffset,yLRS), (xLeftOffset-4,yLRS)), + fill=self.LRS_COLOR, width=1*zoom) if all_int: scaleStr = "%d" % item else: scaleStr = "%2.1f" % item #Draw the LRS/LOD Y axis label - canvas.drawString(scaleStr, xLeftOffset-4-canvas.stringWidth(scaleStr, font=LRSScaleFont)-5, yLRS+3, font=LRSScaleFont, color=self.LRS_COLOR) + im_drawer.text( + text=scaleStr, + xy=(xLeftOffset-4-im_drawer.textsize(scaleStr, font=LRSScaleFont)[0]-5, + yLRS+3), + font=LRSScaleFont, fill=self.LRS_COLOR) if self.permChecked and self.nperm > 0 and not self.multipleInterval: significantY = yZero - self.significant*LRSHeightThresh/LRS_LOD_Max @@ -1824,10 +2074,19 @@ class DisplayMappingResults(object): #ZS: I don't know if what I did here with this inner function is clever or overly complicated, but it's the only way I could think of to avoid duplicating the code inside this function def add_suggestive_significant_lines_and_legend(start_pos_x, chr_length_dist): rightEdge = int(start_pos_x + chr_length_dist*plotXScale - self.SUGGESTIVE_WIDTH/1.5) - canvas.drawLine(start_pos_x+self.SUGGESTIVE_WIDTH/1.5, suggestiveY, rightEdge, suggestiveY, color=self.SUGGESTIVE_COLOR, - width=self.SUGGESTIVE_WIDTH*zoom, clipX=(xLeftOffset, xLeftOffset + plotWidth-2)) - canvas.drawLine(start_pos_x+self.SUGGESTIVE_WIDTH/1.5, significantY, rightEdge, significantY, color=self.SIGNIFICANT_COLOR, - width=self.SIGNIFICANT_WIDTH*zoom, clipX=(xLeftOffset, xLeftOffset + plotWidth-2)) + im_drawer.line( + xy=((start_pos_x+self.SUGGESTIVE_WIDTH/1.5, suggestiveY), + (rightEdge, suggestiveY)), + fill=self.SUGGESTIVE_COLOR, width=self.SUGGESTIVE_WIDTH*zoom + #,clipX=(xLeftOffset, xLeftOffset + plotWidth-2) + ) + im_drawer.line( + xy=((start_pos_x+self.SUGGESTIVE_WIDTH/1.5, significantY), + (rightEdge, significantY)), + fill=self.SIGNIFICANT_COLOR, + width=self.SIGNIFICANT_WIDTH*zoom + #, clipX=(xLeftOffset, xLeftOffset + plotWidth-2) + ) sugg_coords = "%d, %d, %d, %d" % (start_pos_x, suggestiveY-2, rightEdge + 2*zoom, suggestiveY+2) sig_coords = "%d, %d, %d, %d" % (start_pos_x, significantY-2, rightEdge + 2*zoom, significantY+2) if self.LRS_LOD == 'LRS': @@ -1868,7 +2127,7 @@ class DisplayMappingResults(object): AdditiveCoordXY = [] DominanceCoordXY = [] - symbolFont = pid.Font(ttf="fnt_bs", size=5,bold=0) #ZS: For Manhattan Plot + symbolFont = ImageFont.truetype(font=FNT_BS_FILE, size=5) #ZS: For Manhattan Plot previous_chr = 1 previous_chr_as_int = 0 @@ -1880,7 +2139,12 @@ class DisplayMappingResults(object): thisLRSColor = self.colorCollection[0] if qtlresult['chr'] != previous_chr and self.selectedChr == -1: if self.manhattan_plot != True: - canvas.drawPolygon(LRSCoordXY,edgeColor=thisLRSColor,closed=0, edgeWidth=lrsEdgeWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)) + im_drawer.polygon( + xy=LRSCoordXY, + outline=thisLRSColor + # , closed=0, edgeWidth=lrsEdgeWidth, + # clipX=(xLeftOffset, xLeftOffset + plotWidth) + ) if not self.multipleInterval and self.additiveChecked: plusColor = self.ADDITIVE_COLOR_POSITIVE @@ -1895,22 +2159,58 @@ class DisplayMappingResults(object): else: Xcm = (yZero-Yc0)/((Yc-Yc0)/(Xc-Xc0)) +Xc0 if Yc0 < yZero: - canvas.drawLine(Xc0, Yc0, Xcm, yZero, color=plusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)) - canvas.drawLine(Xcm, yZero, Xc, yZero-(Yc-yZero), color=minusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)) + im_drawer.line( + xy=((Xc0, Yc0), (Xcm, yZero)), + fill=plusColor, width=lineWidth + #, clipX=(xLeftOffset, xLeftOffset + plotWidth) + ) + im_drawer.line( + xy=((Xcm, yZero), (Xc, yZero-(Yc-yZero))), + fill=minusColor, width=lineWidth + #, clipX=(xLeftOffset, xLeftOffset + plotWidth) + ) else: - canvas.drawLine(Xc0, yZero - (Yc0-yZero), Xcm, yZero, color=minusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)) - canvas.drawLine(Xcm, yZero, Xc, Yc, color=plusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)) + im_drawer.line( + xy=((Xc0, yZero-(Yc0-yZero)), + (Xcm, yZero)), + fill=minusColor, width=lineWidth + #, clipX=(xLeftOffset, xLeftOffset + plotWidth) + ) + im_drawer.line( + xy=((Xcm, yZero), (Xc, Yc)), + fill=plusColor, width=lineWidth + #, clipX=(xLeftOffset, xLeftOffset + plotWidth) + ) elif (Yc0-yZero)*(Yc-yZero) > 0: if Yc < yZero: - canvas.drawLine(Xc0, Yc0, Xc, Yc, color=plusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)) + im_drawer.line( + xy=((Xc0, Yc0), (Xc, Yc)), + fill=plusColor, + width=lineWidth + #, clipX=(xLeftOffset, xLeftOffset + plotWidth) + ) else: - canvas.drawLine(Xc0, yZero - (Yc0-yZero), Xc, yZero - (Yc-yZero), color=minusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)) + im_drawer.line( + xy=((Xc0, yZero - (Yc0-yZero)), + (Xc, yZero - (Yc-yZero))), + fill=minusColor, width=lineWidth + #, clipX=(xLeftOffset, xLeftOffset + plotWidth) + ) else: minYc = min(Yc-yZero, Yc0-yZero) if minYc < 0: - canvas.drawLine(Xc0, Yc0, Xc, Yc, color=plusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)) + im_drawer.line( + xy=((Xc0, Yc0), (Xc, Yc)), + fill=plusColor, width=lineWidth + #, clipX=(xLeftOffset, xLeftOffset + plotWidth) + ) else: - canvas.drawLine(Xc0, yZero - (Yc0-yZero), Xc, yZero - (Yc-yZero), color=minusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)) + im_drawer.line( + xy=((Xc0, yZero - (Yc0-yZero)), + (Xc, yZero - (Yc-yZero))), + fill=minusColor, width=lineWidth + #, clipX=(xLeftOffset, xLeftOffset + plotWidth) + ) LRSCoordXY = [] AdditiveCoordXY = [] @@ -1979,15 +2279,12 @@ class DisplayMappingResults(object): point_color = RED else: point_color = BLUE - - final_x_pos = Xc-canvas.stringWidth("5",font=symbolFont)/2+1 - if final_x_pos > (xLeftOffset + plotWidth): - continue - #break ZS: This is temporary until issue with sorting for GEMMA is fixed - elif final_x_pos < xLeftOffset: - continue - else: - canvas.drawString("5", final_x_pos,Yc+2,color=point_color, font=symbolFont) + im_drawer.text( + text="5", + xy=( + Xc-im_drawer.textsize("5",font=symbolFont)[0]/2+1, + Yc+2), + fill=point_color, font=symbolFont) else: LRSCoordXY.append((Xc, Yc)) @@ -2000,7 +2297,11 @@ class DisplayMappingResults(object): m += 1 if self.manhattan_plot != True: - canvas.drawPolygon(LRSCoordXY,edgeColor=thisLRSColor,closed=0, edgeWidth=lrsEdgeWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)) + im_drawer.polygon( + xy=LRSCoordXY, + outline=thisLRSColor + #, closed=0, edgeWidth=lrsEdgeWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth) + ) if not self.multipleInterval and self.additiveChecked: plusColor = self.ADDITIVE_COLOR_POSITIVE @@ -2015,22 +2316,57 @@ class DisplayMappingResults(object): else: Xcm = (yZero-Yc0)/((Yc-Yc0)/(Xc-Xc0)) +Xc0 if Yc0 < yZero: - canvas.drawLine(Xc0, Yc0, Xcm, yZero, color=plusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)) - canvas.drawLine(Xcm, yZero, Xc, yZero-(Yc-yZero), color=minusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)) + im_drawer.line( + xy=((Xc0, Yc0), (Xcm, yZero)), + fill=plusColor, width=lineWidth + #, clipX=(xLeftOffset, xLeftOffset + plotWidth) + ) + im_drawer.line( + xy=((Xcm, yZero), (Xc, yZero-(Yc-yZero))), + fill=minusColor, width=lineWidth + #, clipX=(xLeftOffset, xLeftOffset + plotWidth) + ) else: - canvas.drawLine(Xc0, yZero - (Yc0-yZero), Xcm, yZero, color=minusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)) - canvas.drawLine(Xcm, yZero, Xc, Yc, color=plusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)) + im_drawer.line( + xy=((Xc0, yZero - (Yc0-yZero)), + (Xcm, yZero)), + fill=minusColor, width=lineWidth + #, clipX=(xLeftOffset, xLeftOffset + plotWidth) + ) + im_drawer.line( + xy=((Xcm, yZero), (Xc, Yc)), + fill=plusColor, width=lineWidth + #, clipX=(xLeftOffset, xLeftOffset + plotWidth) + ) elif (Yc0-yZero)*(Yc-yZero) > 0: if Yc < yZero: - canvas.drawLine(Xc0, Yc0, Xc, Yc, color=plusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)) + im_drawer.line( + xy=((Xc0, Yc0), (Xc, Yc)), fill=plusColor, + width=lineWidth + #, clipX=(xLeftOffset, xLeftOffset + plotWidth) + ) else: - canvas.drawLine(Xc0, yZero - (Yc0-yZero), Xc, yZero - (Yc-yZero), color=minusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)) + im_drawer.line( + xy=((Xc0,yZero-(Yc0-yZero)), + (Xc,yZero-(Yc-yZero))), + fill=minusColor, width=lineWidth + #, clipX=(xLeftOffset, xLeftOffset + plotWidth) + ) else: minYc = min(Yc-yZero, Yc0-yZero) if minYc < 0: - canvas.drawLine(Xc0, Yc0, Xc, Yc, color=plusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)) + im_drawer.line( + xy=((Xc0, Yc0), (Xc, Yc)), + fill=plusColor, width=lineWidth + #, clipX=(xLeftOffset, xLeftOffset + plotWidth) + ) else: - canvas.drawLine(Xc0, yZero - (Yc0-yZero), Xc, yZero - (Yc-yZero), color=minusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)) + im_drawer.line( + xy=((Xc0, yZero - (Yc0-yZero)), + (Xc, yZero - (Yc-yZero))), + fill=minusColor, width=lineWidth + #, clipX=(xLeftOffset, xLeftOffset + plotWidth) + ) if not self.multipleInterval and INTERCROSS and self.dominanceChecked: plusColor = self.DOMINANCE_COLOR_POSITIVE @@ -2045,27 +2381,61 @@ class DisplayMappingResults(object): else: Xcm = (yZero-Yc0)/((Yc-Yc0)/(Xc-Xc0)) +Xc0 if Yc0 < yZero: - canvas.drawLine(Xc0, Yc0, Xcm, yZero, color=plusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)) - canvas.drawLine(Xcm, yZero, Xc, yZero-(Yc-yZero), color=minusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)) + im_drawer.line( + xy=((Xc0, Yc0), (Xcm, yZero)), + fill=plusColor, width=lineWidth + #, clipX=(xLeftOffset, xLeftOffset + plotWidth) + ) + im_drawer.line( + xy=((Xcm, yZero), (Xc, yZero-(Yc-yZero))), + fill=minusColor, width=lineWidth + #, clipX=(xLeftOffset, xLeftOffset + plotWidth) + ) else: - canvas.drawLine(Xc0, yZero - (Yc0-yZero), Xcm, yZero, color=minusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)) - canvas.drawLine(Xcm, yZero, Xc, Yc, color=plusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)) + im_drawer.line( + xy=((Xc0, yZero - (Yc0-yZero)), (Xcm, yZero)), + fill=minusColor, width=lineWidth + #, clipX=(xLeftOffset, xLeftOffset + plotWidth) + ) + im_drawer.line( + xy=((Xcm, yZero), (Xc, Yc)), + fill=plusColor, width=lineWidth + #, clipX=(xLeftOffset, xLeftOffset + plotWidth) + ) elif (Yc0-yZero)*(Yc-yZero) > 0: if Yc < yZero: - canvas.drawLine(Xc0, Yc0, Xc, Yc, color=plusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)) + im_drawer.line( + xy=((Xc0, Yc0), (Xc, Yc)), + fill=plusColor, width=lineWidth + #, clipX=(xLeftOffset, xLeftOffset + plotWidth) + ) else: - canvas.drawLine(Xc0, yZero - (Yc0-yZero), Xc, yZero - (Yc-yZero), color=minusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)) + im_drawer.line( + xy=((Xc0, yZero - (Yc0-yZero)), + (Xc, yZero - (Yc-yZero))), + fill=minusColor, width=lineWidth + #, clipX=(xLeftOffset, xLeftOffset + plotWidth) + ) else: minYc = min(Yc-yZero, Yc0-yZero) if minYc < 0: - canvas.drawLine(Xc0, Yc0, Xc, Yc, color=plusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)) + im_drawer.line( + xy=((Xc0, Yc0), (Xc, Yc)), + fill=plusColor, width=lineWidth + #, clipX=(xLeftOffset, xLeftOffset + plotWidth) + ) else: - canvas.drawLine(Xc0, yZero - (Yc0-yZero), Xc, yZero - (Yc-yZero), color=minusColor, width=lineWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth)) + im_drawer.line( + xy=((Xc0, yZero - (Yc0-yZero)), + (Xc, yZero - (Yc-yZero))), fill=minusColor, + width=lineWidth + #, clipX=(xLeftOffset, xLeftOffset + plotWidth) + ) ###draw additive scale if not self.multipleInterval and self.additiveChecked: - additiveScaleFont=pid.Font(ttf="verdana",size=16*zoom,bold=0) + additiveScaleFont=ImageFont.truetype(font=VERDANA_FILE,size=16*zoom) additiveScale = Plot.detScaleOld(0,additiveMax) additiveStep = (additiveScale[1]-additiveScale[0])/additiveScale[2] additiveAxisList = Plot.frange(0, additiveScale[1], additiveStep) @@ -2074,13 +2444,24 @@ class DisplayMappingResults(object): additiveAxisList.append(additiveScale[1]) for item in additiveAxisList: additiveY = yZero - item*addPlotScale - canvas.drawLine(xLeftOffset + plotWidth,additiveY,xLeftOffset+4+ plotWidth,additiveY,color=self.ADDITIVE_COLOR_POSITIVE, width=1*zoom) + im_drawer.line( + xy=((xLeftOffset + plotWidth,additiveY), + (xLeftOffset+4+ plotWidth,additiveY)), + fill=self.ADDITIVE_COLOR_POSITIVE, width=1*zoom) scaleStr = "%2.3f" % item - canvas.drawString(scaleStr,xLeftOffset + plotWidth +6,additiveY+5,font=additiveScaleFont,color=self.ADDITIVE_COLOR_POSITIVE) + im_drawer.text( + text=scaleStr, + xy=(xLeftOffset + plotWidth +6,additiveY+5), + font=additiveScaleFont,fill=self.ADDITIVE_COLOR_POSITIVE) - canvas.drawLine(xLeftOffset+plotWidth,additiveY,xLeftOffset+plotWidth,yZero,color=self.ADDITIVE_COLOR_POSITIVE, width=1*zoom) + im_drawer.line( + xy=((xLeftOffset+plotWidth,additiveY), + (xLeftOffset+plotWidth,yZero)), + fill=self.ADDITIVE_COLOR_POSITIVE, width=1*zoom) - canvas.drawLine(xLeftOffset, yZero, xLeftOffset, yTopOffset + 30*(zoom - 1), color=self.LRS_COLOR, width=1*zoom) #the blue line running up the y axis + im_drawer.line( + xy=((xLeftOffset, yZero), (xLeftOffset, yTopOffset + 30*(zoom - 1))), + fill=self.LRS_COLOR, width=1*zoom) #the blue line running up the y axis def drawGraphBackground(self, canvas, gifmap, offset= (80, 120, 80, 50), zoom = 1, startMb = None, endMb = None): @@ -2088,6 +2469,7 @@ class DisplayMappingResults(object): ##multiple Chromosome view ##single Chromosome Physical ##single Chromosome Genetic + im_drawer = ImageDraw.Draw(canvas) xLeftOffset, xRightOffset, yTopOffset, yBottomOffset = offset plotWidth = canvas.size[0] - xLeftOffset - xRightOffset plotHeight = canvas.size[1] - yTopOffset - yBottomOffset @@ -2114,8 +2496,10 @@ class DisplayMappingResults(object): else: theBackColor = self.GRAPH_BACK_LIGHT_COLOR i += 1 - canvas.drawRect(startPix, yTopOffset, min(startPix+spacingAmt, xLeftOffset+plotWidth), \ - yBottom, edgeColor=theBackColor, fillColor=theBackColor) + im_drawer.rectangle( + [(startPix, yTopOffset), + (min(startPix+spacingAmt, xLeftOffset+plotWidth), yBottom)], + outline=theBackColor, fill=theBackColor) drawRegionDistance = self.ChrLengthDistList[self.ChrList[self.selectedChr][1]] self.ChrLengthDistList = [drawRegionDistance] @@ -2132,7 +2516,7 @@ class DisplayMappingResults(object): chrFontZoom = 2 else: chrFontZoom = 1 - chrLabelFont=pid.Font(ttf="verdana",size=24*chrFontZoom,bold=0) + chrLabelFont=ImageFont.truetype(font=VERDANA_FILE,size=24*chrFontZoom) for i, _chr in enumerate(self.genotype): if (i % 2 == 0): @@ -2141,14 +2525,18 @@ class DisplayMappingResults(object): theBackColor = self.GRAPH_BACK_LIGHT_COLOR #draw the shaded boxes and the sig/sug thick lines - canvas.drawRect(startPosX, yTopOffset, startPosX + self.ChrLengthDistList[i]*plotXScale, \ - yBottom, edgeColor=GAINSBORO,fillColor=theBackColor) + im_drawer.rectangle( + ((startPosX, yTopOffset), + (startPosX + self.ChrLengthDistList[i]*plotXScale, yBottom)), + outline=GAINSBORO, + fill=theBackColor) - chrNameWidth = canvas.stringWidth(_chr.name, font=chrLabelFont) + chrNameWidth, chrNameHeight = im_drawer.textsize(_chr.name, font=chrLabelFont) chrStartPix = startPosX + (self.ChrLengthDistList[i]*plotXScale -chrNameWidth)/2 chrEndPix = startPosX + (self.ChrLengthDistList[i]*plotXScale +chrNameWidth)/2 - canvas.drawString(_chr.name, chrStartPix, yTopOffset + 20 ,font = chrLabelFont,color=BLACK) + im_drawer.text(xy=(chrStartPix, yTopOffset + 20), + text=_chr.name, font=chrLabelFont, fill=BLACK) COORDS = "%d,%d,%d,%d" %(chrStartPix, yTopOffset, chrEndPix,yTopOffset +20) #add by NL 09-03-2010 @@ -2164,7 +2552,7 @@ class DisplayMappingResults(object): ######################################### # Permutation Graph ######################################### - myCanvas = pid.PILCanvas(size=(500,300)) + myCanvas = Image.new("RGBA", size=(500, 300)) if 'lod_score' in self.qtlresults[0] and self.LRS_LOD == "LRS": perm_output = [value*4.61 for value in self.perm_output] elif 'lod_score' not in self.qtlresults[0] and self.LRS_LOD == "LOD": @@ -2174,7 +2562,8 @@ class DisplayMappingResults(object): filename= webqtlUtil.genRandStr("Reg_") Plot.plotBar(myCanvas, perm_output, XLabel=self.LRS_LOD, YLabel='Frequency', title=' Histogram of Permutation Test') - myCanvas.save(GENERATED_IMAGE_DIR+filename, format='gif') + myCanvas.save("{}.gif".format(GENERATED_IMAGE_DIR+filename), + format='gif') return filename -- cgit v1.2.3 From 3d5bff591766d6cea659f041c87b6ef4ff359bee Mon Sep 17 00:00:00 2001 From: Muriithi Frederick Muriuki Date: Mon, 18 Feb 2019 14:34:08 +0300 Subject: Add missing font files * wqflask/fonts/ttf: Add ttf font files. --- wqflask/fonts/ttf/arial.ttf | Bin 0 -> 151232 bytes wqflask/fonts/ttf/courbd.ttf | Bin 0 -> 181388 bytes wqflask/fonts/ttf/fnt_bs.ttf | Bin 0 -> 20988 bytes wqflask/fonts/ttf/tahoma.ttf | Bin 0 -> 249012 bytes wqflask/fonts/ttf/trebucbd.ttf | Bin 0 -> 123828 bytes wqflask/fonts/ttf/verdana.ttf | Bin 0 -> 139640 bytes 6 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 wqflask/fonts/ttf/arial.ttf create mode 100644 wqflask/fonts/ttf/courbd.ttf create mode 100644 wqflask/fonts/ttf/fnt_bs.ttf create mode 100644 wqflask/fonts/ttf/tahoma.ttf create mode 100644 wqflask/fonts/ttf/trebucbd.ttf create mode 100644 wqflask/fonts/ttf/verdana.ttf (limited to 'wqflask') diff --git a/wqflask/fonts/ttf/arial.ttf b/wqflask/fonts/ttf/arial.ttf new file mode 100644 index 00000000..bf0d4a95 Binary files /dev/null and b/wqflask/fonts/ttf/arial.ttf differ diff --git a/wqflask/fonts/ttf/courbd.ttf b/wqflask/fonts/ttf/courbd.ttf new file mode 100644 index 00000000..c8081467 Binary files /dev/null and b/wqflask/fonts/ttf/courbd.ttf differ diff --git a/wqflask/fonts/ttf/fnt_bs.ttf b/wqflask/fonts/ttf/fnt_bs.ttf new file mode 100644 index 00000000..712c38cf Binary files /dev/null and b/wqflask/fonts/ttf/fnt_bs.ttf differ diff --git a/wqflask/fonts/ttf/tahoma.ttf b/wqflask/fonts/ttf/tahoma.ttf new file mode 100644 index 00000000..bb314be3 Binary files /dev/null and b/wqflask/fonts/ttf/tahoma.ttf differ diff --git a/wqflask/fonts/ttf/trebucbd.ttf b/wqflask/fonts/ttf/trebucbd.ttf new file mode 100644 index 00000000..1ab1ae0a Binary files /dev/null and b/wqflask/fonts/ttf/trebucbd.ttf differ diff --git a/wqflask/fonts/ttf/verdana.ttf b/wqflask/fonts/ttf/verdana.ttf new file mode 100644 index 00000000..754a9b7b Binary files /dev/null and b/wqflask/fonts/ttf/verdana.ttf differ -- cgit v1.2.3 From d1e5ab462e9e8d147a4eedae57a541084f1bcdcc Mon Sep 17 00:00:00 2001 From: Muriithi Frederick Muriuki Date: Sat, 23 Feb 2019 07:20:18 +0300 Subject: Update SNP Browser to Pillow * wqflask/wqflask/snp_browser/snp_browser.py: Use newer, and supported Pillow in place of obsoleted Piddle library. --- wqflask/wqflask/snp_browser/snp_browser.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'wqflask') diff --git a/wqflask/wqflask/snp_browser/snp_browser.py b/wqflask/wqflask/snp_browser/snp_browser.py index 73ab8798..1d28d76a 100644 --- a/wqflask/wqflask/snp_browser/snp_browser.py +++ b/wqflask/wqflask/snp_browser/snp_browser.py @@ -3,7 +3,7 @@ from __future__ import absolute_import, print_function, division from flask import Flask, g, url_for import string -import piddle as pid +from PIL import (Image) from utility.logger import getLogger logger = getLogger(__name__ ) @@ -629,7 +629,7 @@ class SnpBrowser(object): canvas_width = 900 canvas_height = 200 - snp_canvas = pid.PILCanvas(size=(canvas_width, canvas_height)) + snp_canvas = Image.new("RGBA", size=(canvas_width, canvas_height)) left_offset, right_offset, top_offset, bottom_offset = (30, 30, 40, 50) plot_width = canvas_width - left_offset - right_offset plot_height = canvas_height - top_offset - bottom_offset -- cgit v1.2.3 From 95dbb4a18a205b475ca8eb72210d7d2193062295 Mon Sep 17 00:00:00 2001 From: Muriithi Frederick Muriuki Date: Sat, 23 Feb 2019 07:32:29 +0300 Subject: Fix font paths * wqflask/utility/Plot.py: Update font paths. * wqflask/fonts/ttf: Update font files. --- wqflask/fonts/ttf/arial.ttf | Bin 151232 -> 0 bytes wqflask/fonts/ttf/courbd.ttf | Bin 181388 -> 0 bytes wqflask/fonts/ttf/fnt_bs.ttf | Bin 20988 -> 0 bytes wqflask/fonts/ttf/tahoma.ttf | Bin 249012 -> 0 bytes wqflask/fonts/ttf/trebucbd.ttf | Bin 123828 -> 0 bytes wqflask/fonts/ttf/verdana.ttf | Bin 139640 -> 0 bytes wqflask/utility/Plot.py | 6 +++--- wqflask/wqflask/static/fonts/courbd.ttf | Bin 0 -> 181388 bytes wqflask/wqflask/static/fonts/tahoma.ttf | Bin 0 -> 249012 bytes 9 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 wqflask/fonts/ttf/arial.ttf delete mode 100644 wqflask/fonts/ttf/courbd.ttf delete mode 100644 wqflask/fonts/ttf/fnt_bs.ttf delete mode 100644 wqflask/fonts/ttf/tahoma.ttf delete mode 100644 wqflask/fonts/ttf/trebucbd.ttf delete mode 100644 wqflask/fonts/ttf/verdana.ttf create mode 100644 wqflask/wqflask/static/fonts/courbd.ttf create mode 100644 wqflask/wqflask/static/fonts/tahoma.ttf (limited to 'wqflask') diff --git a/wqflask/fonts/ttf/arial.ttf b/wqflask/fonts/ttf/arial.ttf deleted file mode 100644 index bf0d4a95..00000000 Binary files a/wqflask/fonts/ttf/arial.ttf and /dev/null differ diff --git a/wqflask/fonts/ttf/courbd.ttf b/wqflask/fonts/ttf/courbd.ttf deleted file mode 100644 index c8081467..00000000 Binary files a/wqflask/fonts/ttf/courbd.ttf and /dev/null differ diff --git a/wqflask/fonts/ttf/fnt_bs.ttf b/wqflask/fonts/ttf/fnt_bs.ttf deleted file mode 100644 index 712c38cf..00000000 Binary files a/wqflask/fonts/ttf/fnt_bs.ttf and /dev/null differ diff --git a/wqflask/fonts/ttf/tahoma.ttf b/wqflask/fonts/ttf/tahoma.ttf deleted file mode 100644 index bb314be3..00000000 Binary files a/wqflask/fonts/ttf/tahoma.ttf and /dev/null differ diff --git a/wqflask/fonts/ttf/trebucbd.ttf b/wqflask/fonts/ttf/trebucbd.ttf deleted file mode 100644 index 1ab1ae0a..00000000 Binary files a/wqflask/fonts/ttf/trebucbd.ttf and /dev/null differ diff --git a/wqflask/fonts/ttf/verdana.ttf b/wqflask/fonts/ttf/verdana.ttf deleted file mode 100644 index 754a9b7b..00000000 Binary files a/wqflask/fonts/ttf/verdana.ttf and /dev/null differ diff --git a/wqflask/utility/Plot.py b/wqflask/utility/Plot.py index c557bcc6..e7115036 100644 --- a/wqflask/utility/Plot.py +++ b/wqflask/utility/Plot.py @@ -48,9 +48,9 @@ BLACK = ImageColor.getrgb("black") # ---- END: Define common colours ---- # # ---- FONT FILES ---- # -VERDANA_FILE = "fonts/ttf/verdana.ttf" -COUR_FILE = "fonts/ttf/courbd.ttf" -TAHOMA_FILE = "fonts/ttf/tahoma.ttf" +VERDANA_FILE = "./wqflask/static/fonts/verdana.ttf" +COUR_FILE = "./wqflask/static/fonts/courbd.ttf" +TAHOMA_FILE = "./wqflask/static/fonts/tahoma.ttf" # ---- END: FONT FILES ---- # def cformat(d, rank=0): diff --git a/wqflask/wqflask/static/fonts/courbd.ttf b/wqflask/wqflask/static/fonts/courbd.ttf new file mode 100644 index 00000000..c8081467 Binary files /dev/null and b/wqflask/wqflask/static/fonts/courbd.ttf differ diff --git a/wqflask/wqflask/static/fonts/tahoma.ttf b/wqflask/wqflask/static/fonts/tahoma.ttf new file mode 100644 index 00000000..bb314be3 Binary files /dev/null and b/wqflask/wqflask/static/fonts/tahoma.ttf differ -- cgit v1.2.3 From dcd053e0249b14c938d94eb749a8b4095c80be29 Mon Sep 17 00:00:00 2001 From: Muriithi Frederick Muriuki Date: Fri, 8 Mar 2019 10:39:53 +0300 Subject: Create new utility module for drawing * wqflask/utility/pillow_utils.py: Create a module to hold some utility functions for drawing with Pillow. Initialise the module with a function to draw rotated text. --- wqflask/utility/pillow_utils.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 wqflask/utility/pillow_utils.py (limited to 'wqflask') diff --git a/wqflask/utility/pillow_utils.py b/wqflask/utility/pillow_utils.py new file mode 100644 index 00000000..4a666e4b --- /dev/null +++ b/wqflask/utility/pillow_utils.py @@ -0,0 +1,16 @@ +from PIL import Image, ImageColor, ImageDraw, ImageFont + +import utility.logger +logger = utility.logger.getLogger(__name__ ) + +BLACK = ImageColor.getrgb("black") +# def draw_rotated_text(canvas: Image, text: str, font: ImageFont, xy: tuple, fill: ImageColor=BLACK, angle: int=-90): +def draw_rotated_text(canvas, text, font, xy, fill=BLACK, angle=-90): + # type: (Image, str, ImageFont, tuple, ImageColor, int) + """Utility function draw rotated text""" + tmp_img = Image.new("RGBA", font.getsize(text), color=(0,0,0,0)) + draw_text = ImageDraw.Draw(tmp_img) + draw_text.text(text=text, xy=(0,0), font=font, fill=fill) + tmp_img2 = tmp_img.rotate(angle, expand=1) + tmp_img2.save("/tmp/{}.png".format(text), format="png") + canvas.paste(im=tmp_img2, box=tuple([int(i) for i in xy])) -- cgit v1.2.3 From 6e1102e36737a3f48a74cf431819c269c54f2601 Mon Sep 17 00:00:00 2001 From: Muriithi Frederick Muriuki Date: Fri, 8 Mar 2019 10:41:40 +0300 Subject: Use draw_rotated_text() Use the new draw_rotated_text() function to draw the text rotated as was formerly done. * wqflask/utility/Plot.py (plotBar): Use draw_rotated_text(). * wqflask/wqflask/marker_regression/display_mapping_results.py: (DisplayMappingResults) Use draw_rotated_text(). --- wqflask/utility/Plot.py | 14 ++++++------- .../marker_regression/display_mapping_results.py | 24 +++++++++++++--------- 2 files changed, 21 insertions(+), 17 deletions(-) (limited to 'wqflask') diff --git a/wqflask/utility/Plot.py b/wqflask/utility/Plot.py index e7115036..d4373412 100644 --- a/wqflask/utility/Plot.py +++ b/wqflask/utility/Plot.py @@ -38,7 +38,7 @@ from numarray import ones, array, dot, swapaxes import webqtlUtil import corestats from base import webqtlConfig - +from utility.pillow_utils import draw_rotated_text import utility.logger logger = utility.logger.getLogger(__name__ ) @@ -219,12 +219,12 @@ def plotBar(canvas, data, barColor=BLUE, axesColor=BLACK, labelColor=BLACK, XLab font=labelFont,fill=labelColor) if YLabel: - im_drawer.text( - text=YLabel, - xy=(19, - yTopOffset+plotHeight-(plotHeight-im_drawer.textsize( - YLabel,font=labelFont)[0])/2.0), - font=labelFont,fill=labelColor,angle=90) + draw_rotated_text(canvas, text=YLabel, + xy=(19, + yTopOffset+plotHeight-( + plotHeight-im_drawer.textsize( + YLabel,font=labelFont)[0])/2.0), + font=labelFont, fill=labelColor, angle=90) labelFont=ImageFont.truetype(font=VERDANA_FILE,size=16) if title: diff --git a/wqflask/wqflask/marker_regression/display_mapping_results.py b/wqflask/wqflask/marker_regression/display_mapping_results.py index 39067fc5..b03902a5 100644 --- a/wqflask/wqflask/marker_regression/display_mapping_results.py +++ b/wqflask/wqflask/marker_regression/display_mapping_results.py @@ -45,6 +45,7 @@ from utility import Plot from utility.benchmark import Bench from wqflask.interval_analyst import GeneUtil from base.webqtlConfig import TMPDIR, GENERATED_TEXT_DIR, GENERATED_IMAGE_DIR +from utility.pillow_utils import draw_rotated_text import utility.logger logger = utility.logger.getLogger(__name__ ) @@ -1519,11 +1520,12 @@ class DisplayMappingResults(object): if lastGene == 0: - im_drawer.text( - text="%s" % (_chr[j].name), + draw_rotated_text( + canvas, text="%s" % (_chr[j].name), + font=ImageFont.truetype(font=VERDANA_FILE, + size=12), xy=(geneStartPix, geneYLocation+17+2*maxind*self.EACH_GENE_HEIGHT*zoom), - font=ImageFont.truetype(font=VERDANA_FILE, size=12), fill=BLACK, angle=-90) oldgeneEndPix = geneEndPix; @@ -1804,9 +1806,10 @@ class DisplayMappingResults(object): (startPosX+tickdists*plotXScale, yZero + 7)), fill=BLACK, width=1*zoom) if j % 2 == 0: - im_drawer.text( - xy=(startPosX+tickdists*plotXScale, yZero+10*zoom), - text=str(tickdists), fill=BLACK, font=MBLabelFont, angle=270) + draw_rotated_text( + canvas, text=str(tickdists), font=MBLabelFont, + xy=(startPosX+tickdists*plotXScale, + yZero+10*zoom), fill=BLACK, angle=270) startPosX += (self.ChrLengthDistList[i]+self.GraphInterval)*plotXScale megabaseLabelFont = ImageFont.truetype(font=VERDANA_FILE, size=int(18*zoom*1.5)) @@ -2037,11 +2040,12 @@ class DisplayMappingResults(object): LRSLODFont=ImageFont.truetype(font=VERDANA_FILE, size=int(18*zoom*1.5)) yZero = yTopOffset + plotHeight - im_drawer.text( - text=self.LRS_LOD, - xy=(xLeftOffset - im_drawer.textsize("999.99", font=LRSScaleFont)[0] - 15*(zoom-1), + draw_rotated_text( + canvas, text=self.LRS_LOD, font=LRSLODFont, + xy=(xLeftOffset - im_drawer.textsize( + "999.99", font=LRSScaleFont)[0] - 15*(zoom-1), yZero - 150 - 300*(zoom - 1)), - font=LRSLODFont, fill=BLACK, angle=90) + fill=BLACK, angle=90) for item in LRSAxisList: if LRS_LOD_Max == 0.0: -- cgit v1.2.3 From 97646f40bd8bff699f9ee2721fc9c960162ad3eb Mon Sep 17 00:00:00 2001 From: Muriithi Frederick Muriuki Date: Fri, 8 Mar 2019 10:57:40 +0300 Subject: Replace "color" with "fill" keyword argument * wqflask/wqflask/marker_regression/display_mapping_results.py: (DisplayMappingResults): Pillow uses 'fill' in place of 'color'. --- wqflask/wqflask/marker_regression/display_mapping_results.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'wqflask') diff --git a/wqflask/wqflask/marker_regression/display_mapping_results.py b/wqflask/wqflask/marker_regression/display_mapping_results.py index b03902a5..9a96cd52 100644 --- a/wqflask/wqflask/marker_regression/display_mapping_results.py +++ b/wqflask/wqflask/marker_regression/display_mapping_results.py @@ -758,7 +758,7 @@ class DisplayMappingResults(object): (canvas.size[0]-bootOffset,bootY)), fill=BLACK) im_drawer.text(xy=(canvas.size[0]-bootOffset+10,bootY+5), - text='%2.1f'%item, font=bootScaleFont, color=BLACK) + text='%2.1f'%item, font=bootScaleFont, fill=BLACK) if self.legendChecked: startPosY = 30 @@ -770,7 +770,7 @@ class DisplayMappingResults(object): fill=YELLOW) im_drawer.text(xy=(leftOffset+ 20, startPosY+5), text='Frequency of the Peak LRS', - font=smallLabelFont, color=BLACK) + font=smallLabelFont, fill=BLACK) def drawProbeSetPosition(self, canvas, plotXScale, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None): im_drawer = ImageDraw.Draw(canvas) -- cgit v1.2.3 From e3c0745fdc3bf33cb10256643f3b1469ee6614c4 Mon Sep 17 00:00:00 2001 From: Muriithi Frederick Muriuki Date: Sat, 9 Mar 2019 08:33:19 +0300 Subject: Add draw_open_polygon() utility * wqflask/utility/pillow_utils.py: New method. --- wqflask/utility/pillow_utils.py | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'wqflask') diff --git a/wqflask/utility/pillow_utils.py b/wqflask/utility/pillow_utils.py index 4a666e4b..dfbf3e19 100644 --- a/wqflask/utility/pillow_utils.py +++ b/wqflask/utility/pillow_utils.py @@ -4,6 +4,8 @@ import utility.logger logger = utility.logger.getLogger(__name__ ) BLACK = ImageColor.getrgb("black") +WHITE = ImageColor.getrgb("white") + # def draw_rotated_text(canvas: Image, text: str, font: ImageFont, xy: tuple, fill: ImageColor=BLACK, angle: int=-90): def draw_rotated_text(canvas, text, font, xy, fill=BLACK, angle=-90): # type: (Image, str, ImageFont, tuple, ImageColor, int) @@ -14,3 +16,10 @@ def draw_rotated_text(canvas, text, font, xy, fill=BLACK, angle=-90): tmp_img2 = tmp_img.rotate(angle, expand=1) tmp_img2.save("/tmp/{}.png".format(text), format="png") canvas.paste(im=tmp_img2, box=tuple([int(i) for i in xy])) + +# def draw_open_polygon(canvas: Image, xy: tuple, fill: ImageColor=WHITE, outline: ImageColor=BLACK): +def draw_open_polygon(canvas, xy, fill=None, outline=BLACK, width=0): + # type: (Image, tuple, ImageColor, ImageColor) + draw_ctx = ImageDraw.Draw(canvas) + draw_ctx.polygon(xy, fill=fill) + draw_ctx.line(xy, fill=outline, width=width) -- cgit v1.2.3 From 5a19179f0b93a80a4c6cc22eb81c0395e1879026 Mon Sep 17 00:00:00 2001 From: Muriithi Frederick Muriuki Date: Sat, 9 Mar 2019 08:34:13 +0300 Subject: Use new `draw_open_polygon()` utility * wqflask/wqflask/marker_regression/display_mapping_results.py: Use the new `draw_open_polygon()` utility to draw open polygons. --- .../marker_regression/display_mapping_results.py | 48 ++++++++++++++-------- 1 file changed, 30 insertions(+), 18 deletions(-) (limited to 'wqflask') diff --git a/wqflask/wqflask/marker_regression/display_mapping_results.py b/wqflask/wqflask/marker_regression/display_mapping_results.py index 9a96cd52..b754662f 100644 --- a/wqflask/wqflask/marker_regression/display_mapping_results.py +++ b/wqflask/wqflask/marker_regression/display_mapping_results.py @@ -45,7 +45,7 @@ from utility import Plot from utility.benchmark import Bench from wqflask.interval_analyst import GeneUtil from base.webqtlConfig import TMPDIR, GENERATED_TEXT_DIR, GENERATED_IMAGE_DIR -from utility.pillow_utils import draw_rotated_text +from utility.pillow_utils import draw_rotated_text, draw_open_polygon import utility.logger logger = utility.logger.getLogger(__name__ ) @@ -841,10 +841,8 @@ class DisplayMappingResults(object): break if locPixel >= 0 and self.plotScale == 'physic': traitPixel = ((locPixel, yZero), (locPixel-7, yZero+14), (locPixel+7, yZero+14)) - im_drawer.polygon( - xy=traitPixel, outline=BLACK, - fill=self.TRANSCRIPT_LOCATION_COLOR#, closed=1 - ) + draw_open_polygon(canvas, xy=traitPixel, outline=BLACK, + fill=self.TRANSCRIPT_LOCATION_COLOR) if self.legendChecked: startPosY = 15 @@ -854,8 +852,18 @@ class DisplayMappingResults(object): leftOffset = xLeftOffset else: leftOffset = xLeftOffset+(nCol-1)*200*fontZoom - canvas.drawPolygon(((leftOffset+7, startPosY-7), (leftOffset, startPosY+7), (leftOffset+14, startPosY+7)), edgeColor=BLACK, fillColor=self.TRANSCRIPT_LOCATION_COLOR, closed=1) - canvas.drawString("Sequence Site", (leftOffset+15), (startPosY+5), smallLabelFont, self.TOP_RIGHT_INFO_COLOR) + draw_open_polygon( + canvas, + xy=( + (leftOffset+7, startPosY-7), + (leftOffset, startPosY+7), + (leftOffset+14, startPosY+7)), + outline=BLACK, fill=self.TRANSCRIPT_LOCATION_COLOR + ) + im_drawer.text( + text="Sequence Site", + xy=(leftOffset+15,startPosY+5), font=smallLabelFont, + fill=self.TOP_RIGHT_INFO_COLOR) def drawSNPTrackNew(self, canvas, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None): im_drawer = ImageDraw.Draw(canvas) @@ -2143,12 +2151,14 @@ class DisplayMappingResults(object): thisLRSColor = self.colorCollection[0] if qtlresult['chr'] != previous_chr and self.selectedChr == -1: if self.manhattan_plot != True: - im_drawer.polygon( - xy=LRSCoordXY, - outline=thisLRSColor - # , closed=0, edgeWidth=lrsEdgeWidth, - # clipX=(xLeftOffset, xLeftOffset + plotWidth) - ) + # im_drawer.polygon( + # xy=LRSCoordXY, + # outline=thisLRSColor + # # , closed=0, edgeWidth=lrsEdgeWidth, + # # clipX=(xLeftOffset, xLeftOffset + plotWidth) + # ) + draw_open_polygon(canvas, xy=LRSCoordXY, + outline=thisLRSColor, width=lrsEdgeWidth) if not self.multipleInterval and self.additiveChecked: plusColor = self.ADDITIVE_COLOR_POSITIVE @@ -2301,11 +2311,13 @@ class DisplayMappingResults(object): m += 1 if self.manhattan_plot != True: - im_drawer.polygon( - xy=LRSCoordXY, - outline=thisLRSColor - #, closed=0, edgeWidth=lrsEdgeWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth) - ) + # im_drawer.polygon( + # xy=LRSCoordXY, + # outline=thisLRSColor + # #, closed=0, edgeWidth=lrsEdgeWidth, clipX=(xLeftOffset, xLeftOffset + plotWidth) + # ) + draw_open_polygon(canvas, xy=LRSCoordXY, outline=thisLRSColor, + width=lrsEdgeWidth) if not self.multipleInterval and self.additiveChecked: plusColor = self.ADDITIVE_COLOR_POSITIVE -- cgit v1.2.3 From 882d8425d62bafdad653b1d939af6cfefb6cc66d Mon Sep 17 00:00:00 2001 From: Muriithi Frederick Muriuki Date: Sat, 9 Mar 2019 09:06:20 +0300 Subject: Give rectangles black outlines * wqflask/wqflask/marker_regression/display_mapping_results.py: Give the rectangles black outlines to correspond to earlier drawings. --- wqflask/wqflask/marker_regression/display_mapping_results.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'wqflask') diff --git a/wqflask/wqflask/marker_regression/display_mapping_results.py b/wqflask/wqflask/marker_regression/display_mapping_results.py index b754662f..6cac51ee 100644 --- a/wqflask/wqflask/marker_regression/display_mapping_results.py +++ b/wqflask/wqflask/marker_regression/display_mapping_results.py @@ -728,7 +728,7 @@ class DisplayMappingResults(object): im_drawer.rectangle( xy=((item[0], yZero), (item[1], yZero - item[2]*bootHeightThresh/maxBootCount)), - fill=self.BOOTSTRAP_BOX_COLOR) + fill=self.BOOTSTRAP_BOX_COLOR, outline=BLACK) ###draw boot scale highestPercent = (maxBootCount*100.0)/nboot @@ -741,7 +741,7 @@ class DisplayMappingResults(object): im_drawer.rectangle( xy=((canvas.size[0]-bootOffset, yZero-bootHeightThresh), (canvas.size[0]-bootOffset-15*zoom,yZero)), - fill = YELLOW) + fill = YELLOW, outline=BLACK) im_drawer.line( xy=((canvas.size[0]-bootOffset+4, yZero), (canvas.size[0]-bootOffset, yZero)), @@ -767,7 +767,7 @@ class DisplayMappingResults(object): leftOffset = xLeftOffset+(nCol-1)*200 im_drawer.rectangle( xy=((leftOffset,startPosY-6), (leftOffset+12,startPosY+6)), - fill=YELLOW) + fill=YELLOW, outline=BLACK) im_drawer.text(xy=(leftOffset+ 20, startPosY+5), text='Frequency of the Peak LRS', font=smallLabelFont, fill=BLACK) @@ -937,7 +937,7 @@ class DisplayMappingResults(object): im_drawer.rectangle( xy=((rightShift,yPaddingTop+kstep*15), (rectWidth+rightShift,yPaddingTop+10+kstep*15)), - fill=thisLRSColor) + fill=thisLRSColor, outline=BLACK) im_drawer.text( text=name,xy=(rectWidth+2+rightShift,yPaddingTop+10+kstep*15), font=colorFont,fill=BLACK) -- cgit v1.2.3 From a1b31f6f217ff8c84e981bbc79784672c9b982dd Mon Sep 17 00:00:00 2001 From: Muriithi Frederick Muriuki Date: Sat, 9 Mar 2019 11:38:11 +0300 Subject: Use TEXT_Y_DISPLACEMENT instead of magic numbers * wqflask/wqflask/marker_regression/display_mapping_results.py: Use TEXT_Y_DISPLACEMENT instead of magic numbers to help with making it clear that the drawn text is displaced somewhat. --- .../marker_regression/display_mapping_results.py | 28 +++++++++++++--------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'wqflask') diff --git a/wqflask/wqflask/marker_regression/display_mapping_results.py b/wqflask/wqflask/marker_regression/display_mapping_results.py index 6cac51ee..4d9649bd 100644 --- a/wqflask/wqflask/marker_regression/display_mapping_results.py +++ b/wqflask/wqflask/marker_regression/display_mapping_results.py @@ -746,7 +746,8 @@ class DisplayMappingResults(object): xy=((canvas.size[0]-bootOffset+4, yZero), (canvas.size[0]-bootOffset, yZero)), fill=BLACK) - im_drawer.text(xy=(canvas.size[0]-bootOffset+10,yZero+5), text='0%', + TEXT_Y_DISPLACEMENT = -8 + im_drawer.text(xy=(canvas.size[0]-bootOffset+10,yZero+TEXT_Y_DISPLACEMENT), text='0%', font=bootScaleFont, fill=BLACK) for item in bootScale: @@ -757,7 +758,7 @@ class DisplayMappingResults(object): xy=((canvas.size[0]-bootOffset+4,bootY), (canvas.size[0]-bootOffset,bootY)), fill=BLACK) - im_drawer.text(xy=(canvas.size[0]-bootOffset+10,bootY+5), + im_drawer.text(xy=(canvas.size[0]-bootOffset+10,bootY+TEXT_Y_DISPLACEMENT), text='%2.1f'%item, font=bootScaleFont, fill=BLACK) if self.legendChecked: @@ -768,7 +769,7 @@ class DisplayMappingResults(object): im_drawer.rectangle( xy=((leftOffset,startPosY-6), (leftOffset+12,startPosY+6)), fill=YELLOW, outline=BLACK) - im_drawer.text(xy=(leftOffset+ 20, startPosY+5), + im_drawer.text(xy=(leftOffset+ 20, startPosY+TEXT_Y_DISPLACEMENT), text='Frequency of the Peak LRS', font=smallLabelFont, fill=BLACK) @@ -860,9 +861,10 @@ class DisplayMappingResults(object): (leftOffset+14, startPosY+7)), outline=BLACK, fill=self.TRANSCRIPT_LOCATION_COLOR ) + TEXT_Y_DISPLACEMENT = -8 im_drawer.text( text="Sequence Site", - xy=(leftOffset+15,startPosY+5), font=smallLabelFont, + xy=(leftOffset+15,startPosY+TEXT_Y_DISPLACEMENT), font=smallLabelFont, fill=self.TOP_RIGHT_INFO_COLOR) def drawSNPTrackNew(self, canvas, offset= (40, 120, 80, 10), zoom = 1, startMb = None, endMb = None): @@ -953,6 +955,7 @@ class DisplayMappingResults(object): plotWidth = canvas.size[0] - xLeftOffset - xRightOffset plotHeight = canvas.size[1] - yTopOffset - yBottomOffset yZero = canvas.size[1] - yBottomOffset + TEXT_Y_DISPLACEMENT = -8 fontZoom = zoom if zoom == 2: fontZoom = 1.5 @@ -965,7 +968,7 @@ class DisplayMappingResults(object): xy=((xLeftOffset,startPosY),(xLeftOffset+32,startPosY)), fill=self.LRS_COLOR, width=2) im_drawer.text( - text=self.LRS_LOD, xy=(xLeftOffset+40,startPosY+5), + text=self.LRS_LOD, xy=(xLeftOffset+40,startPosY+TEXT_Y_DISPLACEMENT), font=labelFont,fill=BLACK) startPosY += stepPosY @@ -978,7 +981,7 @@ class DisplayMappingResults(object): xy=((startPosX+18,startPosY),(startPosX+32,startPosY)), fill=self.ADDITIVE_COLOR_NEGATIVE, width=2) im_drawer.text( - text='Additive Effect',xy=(startPosX+40,startPosY+5), + text='Additive Effect',xy=(startPosX+40,startPosY+TEXT_Y_DISPLACEMENT), font=labelFont,fill=BLACK) if self.genotype.type == 'intercross' and self.dominanceChecked: @@ -1024,10 +1027,10 @@ class DisplayMappingResults(object): fill=self.SUGGESTIVE_COLOR, width=self.SUGGESTIVE_WIDTH) im_drawer.text( text='Significant %s = %2.2f' % (self.LRS_LOD,self.significant), - xy=(xLeftOffset+42,startPosY +5),font=labelFont,fill=BLACK) + xy=(xLeftOffset+42,startPosY+TEXT_Y_DISPLACEMENT),font=labelFont,fill=BLACK) im_drawer.text( text='Suggestive %s = %2.2f' % (self.LRS_LOD, self.suggestive), - xy=(xLeftOffset+42,startPosY + 5 +stepPosY),font=labelFont, + xy=(xLeftOffset+42,startPosY + TEXT_Y_DISPLACEMENT +stepPosY),font=labelFont, fill=BLACK) labelFont = ImageFont.truetype(font=VERDANA_FILE,size=12*fontZoom) @@ -2067,10 +2070,11 @@ class DisplayMappingResults(object): else: scaleStr = "%2.1f" % item #Draw the LRS/LOD Y axis label + TEXT_Y_DISPLACEMENT = -10 im_drawer.text( text=scaleStr, xy=(xLeftOffset-4-im_drawer.textsize(scaleStr, font=LRSScaleFont)[0]-5, - yLRS+3), + yLRS+TEXT_Y_DISPLACEMENT), font=LRSScaleFont, fill=self.LRS_COLOR) if self.permChecked and self.nperm > 0 and not self.multipleInterval: @@ -2456,6 +2460,7 @@ class DisplayMappingResults(object): additiveStep = (additiveScale[1]-additiveScale[0])/additiveScale[2] additiveAxisList = Plot.frange(0, additiveScale[1], additiveStep) addPlotScale = AdditiveHeightThresh/additiveMax + TEXT_Y_DISPLACEMENT = -8 additiveAxisList.append(additiveScale[1]) for item in additiveAxisList: @@ -2467,7 +2472,7 @@ class DisplayMappingResults(object): scaleStr = "%2.3f" % item im_drawer.text( text=scaleStr, - xy=(xLeftOffset + plotWidth +6,additiveY+5), + xy=(xLeftOffset + plotWidth +6,additiveY+TEXT_Y_DISPLACEMENT), font=additiveScaleFont,fill=self.ADDITIVE_COLOR_POSITIVE) im_drawer.line( @@ -2551,7 +2556,8 @@ class DisplayMappingResults(object): chrStartPix = startPosX + (self.ChrLengthDistList[i]*plotXScale -chrNameWidth)/2 chrEndPix = startPosX + (self.ChrLengthDistList[i]*plotXScale +chrNameWidth)/2 - im_drawer.text(xy=(chrStartPix, yTopOffset + 20), + TEXT_Y_DISPLACEMENT = 0 + im_drawer.text(xy=(chrStartPix, yTopOffset + TEXT_Y_DISPLACEMENT), text=_chr.name, font=chrLabelFont, fill=BLACK) COORDS = "%d,%d,%d,%d" %(chrStartPix, yTopOffset, chrEndPix,yTopOffset +20) -- cgit v1.2.3 From b48698b2dfcf04b2016eb92e3de764d8ab176aab Mon Sep 17 00:00:00 2001 From: Muriithi Frederick Muriuki Date: Sat, 9 Mar 2019 12:03:05 +0300 Subject: Fix placement for axes labels * wqflask/wqflask/marker_regression/display_mapping_results.py: Fix the placement for the axes labels. --- wqflask/wqflask/marker_regression/display_mapping_results.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'wqflask') diff --git a/wqflask/wqflask/marker_regression/display_mapping_results.py b/wqflask/wqflask/marker_regression/display_mapping_results.py index 4d9649bd..2f235896 100644 --- a/wqflask/wqflask/marker_regression/display_mapping_results.py +++ b/wqflask/wqflask/marker_regression/display_mapping_results.py @@ -1823,13 +1823,14 @@ class DisplayMappingResults(object): yZero+10*zoom), fill=BLACK, angle=270) startPosX += (self.ChrLengthDistList[i]+self.GraphInterval)*plotXScale + TEXT_Y_DISPLACEMENT = -15 megabaseLabelFont = ImageFont.truetype(font=VERDANA_FILE, size=int(18*zoom*1.5)) im_drawer.text( text="Megabases", xy=( xLeftOffset+(plotWidth-im_drawer.textsize( "Megabases",font=megabaseLabelFont)[0])/2, - strYLoc+MBLabelFont.font.height+10*(zoom%2)+ 10), + strYLoc+MBLabelFont.font.height+10*(zoom%2)+TEXT_Y_DISPLACEMENT), font=megabaseLabelFont, fill=BLACK) pass else: @@ -2051,11 +2052,13 @@ class DisplayMappingResults(object): LRSLODFont=ImageFont.truetype(font=VERDANA_FILE, size=int(18*zoom*1.5)) yZero = yTopOffset + plotHeight + TEXT_X_DISPLACEMENT = -20 + TEXT_Y_DISPLACEMENT = -215 draw_rotated_text( canvas, text=self.LRS_LOD, font=LRSLODFont, xy=(xLeftOffset - im_drawer.textsize( - "999.99", font=LRSScaleFont)[0] - 15*(zoom-1), - yZero - 150 - 300*(zoom - 1)), + "999.99", font=LRSScaleFont)[0] - 15*(zoom-1) + TEXT_X_DISPLACEMENT, + yZero + TEXT_Y_DISPLACEMENT - 300*(zoom - 1)), fill=BLACK, angle=90) for item in LRSAxisList: -- cgit v1.2.3 From 7f982bfb55f7832f63bb960e084f5ca6d40eb519 Mon Sep 17 00:00:00 2001 From: Muriithi Frederick Muriuki Date: Thu, 21 Mar 2019 09:45:08 +0300 Subject: Change Y Coodinate system * wqflask/wqflask/marker_regression/display_mapping_results.py: Piddle seemed to centre text about the given Y coordinate, while Pillow requires specification to top-left corner of the text. This slight change means text all over the image is displaced somewhat, and this fixes the coordinate system for some of the text. --- wqflask/wqflask/marker_regression/display_mapping_results.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'wqflask') diff --git a/wqflask/wqflask/marker_regression/display_mapping_results.py b/wqflask/wqflask/marker_regression/display_mapping_results.py index 2f235896..9b406b72 100644 --- a/wqflask/wqflask/marker_regression/display_mapping_results.py +++ b/wqflask/wqflask/marker_regression/display_mapping_results.py @@ -1698,21 +1698,21 @@ class DisplayMappingResults(object): im_drawer.text( text="Click to view the corresponding section of the genome in an 8x expanded WebQTL map", - xy=((xLeftOffset + 10), paddingTop + self.BAND_HEIGHT/2), + xy=((xLeftOffset + 10), paddingTop),# + self.BAND_HEIGHT/2), font=clickableRegionLabelFont, fill=self.CLICKABLE_WEBQTL_TEXT_COLOR) if self.dataset.group.species == "mouse" or self.dataset.group.species == "rat": im_drawer.text( text="Click to view the corresponding section of the genome in PhenoGen", - xy=((xLeftOffset + 10), phenogenPaddingTop + self.BAND_HEIGHT/2), + xy=((xLeftOffset + 10), phenogenPaddingTop),# + self.BAND_HEIGHT/2), font=clickableRegionLabelFont, fill=self.CLICKABLE_PHENOGEN_TEXT_COLOR) im_drawer.text( text="Click to view the corresponding section of the genome in the UCSC Genome Browser", - xy=((xLeftOffset + 10), ucscPaddingTop + self.BAND_HEIGHT/2), + xy=((xLeftOffset + 10), ucscPaddingTop),# + self.BAND_HEIGHT/2), font=clickableRegionLabelFont, fill=self.CLICKABLE_UCSC_TEXT_COLOR) im_drawer.text( text="Click to view the corresponding section of the genome in the Ensembl Genome Browser", - xy=((xLeftOffset+10), ensemblPaddingTop + self.BAND_HEIGHT/2), + xy=((xLeftOffset+10), ensemblPaddingTop),# + self.BAND_HEIGHT/2), font=clickableRegionLabelFont, fill=self.CLICKABLE_ENSEMBL_TEXT_COLOR) #draw the gray text -- cgit v1.2.3 From 3a8409757e2e095cd18c483de07af1eed8719c02 Mon Sep 17 00:00:00 2001 From: BonfaceKilz Date: Sat, 8 Aug 2020 03:36:31 +0300 Subject: Add a basic test for test_display_marking_results.py * wqflask/tests/wqflask/marker_regression/__init__.py: Add it * wqflask/tests/wqflask/marker_regression/test_display_marking_results.py: Check that PIL colors are being used instead of the deprecated Piddle colors. --- wqflask/tests/wqflask/marker_regression/__init__.py | 0 .../wqflask/marker_regression/test_display_marking_results.py | 9 +++++++++ 2 files changed, 9 insertions(+) create mode 100644 wqflask/tests/wqflask/marker_regression/__init__.py create mode 100644 wqflask/tests/wqflask/marker_regression/test_display_marking_results.py (limited to 'wqflask') diff --git a/wqflask/tests/wqflask/marker_regression/__init__.py b/wqflask/tests/wqflask/marker_regression/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/wqflask/tests/wqflask/marker_regression/test_display_marking_results.py b/wqflask/tests/wqflask/marker_regression/test_display_marking_results.py new file mode 100644 index 00000000..67da508b --- /dev/null +++ b/wqflask/tests/wqflask/marker_regression/test_display_marking_results.py @@ -0,0 +1,9 @@ +import unittest + +from wqflask.marker_regression.display_mapping_results import DisplayMappingResults + +class TestDisplayMappingResults(unittest.TestCase): + def test_pil_colors(self): + """Test that colors use PILLOW color format""" + self.assertEqual(DisplayMappingResults.CLICKABLE_WEBQTL_REGION_COLOR, + (245, 211, 211)) -- cgit v1.2.3 From c1b1c914b10781715bb6a2e7fc061e6e506fb92f Mon Sep 17 00:00:00 2001 From: Pjotr Prins Date: Mon, 18 Feb 2019 10:10:56 +0000 Subject: Add fonts for pillow * wqflask/wqflask/marker_regression/display_mapping_results.py: replace piddle method with PIL.ImageFont * wqflask/wqflask/static/fonts: Add fonts in path --- .../marker_regression/display_mapping_results.py | 15 +++++++++------ wqflask/wqflask/static/fonts/README | 1 + wqflask/wqflask/static/fonts/arial.ttf | Bin 0 -> 151232 bytes wqflask/wqflask/static/fonts/fnt_bs.ttf | Bin 0 -> 20988 bytes wqflask/wqflask/static/fonts/trebucbd.ttf | Bin 0 -> 123828 bytes wqflask/wqflask/static/fonts/verdana.ttf | Bin 0 -> 139640 bytes 6 files changed, 10 insertions(+), 6 deletions(-) create mode 100644 wqflask/wqflask/static/fonts/README create mode 100644 wqflask/wqflask/static/fonts/arial.ttf create mode 100644 wqflask/wqflask/static/fonts/fnt_bs.ttf create mode 100644 wqflask/wqflask/static/fonts/trebucbd.ttf create mode 100644 wqflask/wqflask/static/fonts/verdana.ttf (limited to 'wqflask') diff --git a/wqflask/wqflask/marker_regression/display_mapping_results.py b/wqflask/wqflask/marker_regression/display_mapping_results.py index 9b406b72..6f50601d 100644 --- a/wqflask/wqflask/marker_regression/display_mapping_results.py +++ b/wqflask/wqflask/marker_regression/display_mapping_results.py @@ -72,10 +72,13 @@ MEDIUMPURPLE = ImageColor.getrgb("mediumpurple") # ---- END: Define common colours ---- # # ---- FONT FILES ---- # -VERDANA_FILE = "fonts/ttf/verdana.ttf" -TREBUC_FILE = "fonts/ttf/trebucbd.ttf" -FNT_BS_FILE = "fonts/ttf/fnt_bs.ttf" -ARIAL_FILE = "fonts/ttf/arial.ttf" +VERDANA_FILE = "./wqflask/static/fonts/verdana.ttf" +TREBUC_FILE = "./wqflask/static/fonts/trebucbd.ttf" +FNT_BS_FILE = "./wqflask/static/fonts/fnt_bs.ttf" +ARIAL_FILE = "./wqflask/static/fonts/arial.ttf" + +assert(os.path.isfile(VERDANA_FILE)) + # ---- END: FONT FILES ---- # ######################################### @@ -2008,8 +2011,8 @@ class DisplayMappingResults(object): js_data['max_score'] = LRS_LOD_Max self.js_data = json.dumps(js_data) - LRSScaleFont=pid.Font(ttf="verdana", size=16*zoom, bold=0) - LRSLODFont=pid.Font(ttf="verdana", size=18*zoom*1.5, bold=0) + LRSScaleFont=ImageFont.truetype(font=VERDANA_FILE, size=16*zoom) + LRSLODFont=ImageFont.truetype(font=VERDANA_FILE, size=int(18*zoom*1.5)) yZero = yTopOffset + plotHeight LRSHeightThresh = drawAreaHeight diff --git a/wqflask/wqflask/static/fonts/README b/wqflask/wqflask/static/fonts/README new file mode 100644 index 00000000..75a3e444 --- /dev/null +++ b/wqflask/wqflask/static/fonts/README @@ -0,0 +1 @@ +These fonts are used by pillow for 'interval mapping' diff --git a/wqflask/wqflask/static/fonts/arial.ttf b/wqflask/wqflask/static/fonts/arial.ttf new file mode 100644 index 00000000..bf0d4a95 Binary files /dev/null and b/wqflask/wqflask/static/fonts/arial.ttf differ diff --git a/wqflask/wqflask/static/fonts/fnt_bs.ttf b/wqflask/wqflask/static/fonts/fnt_bs.ttf new file mode 100644 index 00000000..712c38cf Binary files /dev/null and b/wqflask/wqflask/static/fonts/fnt_bs.ttf differ diff --git a/wqflask/wqflask/static/fonts/trebucbd.ttf b/wqflask/wqflask/static/fonts/trebucbd.ttf new file mode 100644 index 00000000..1ab1ae0a Binary files /dev/null and b/wqflask/wqflask/static/fonts/trebucbd.ttf differ diff --git a/wqflask/wqflask/static/fonts/verdana.ttf b/wqflask/wqflask/static/fonts/verdana.ttf new file mode 100644 index 00000000..754a9b7b Binary files /dev/null and b/wqflask/wqflask/static/fonts/verdana.ttf differ -- cgit v1.2.3 From d157019159ae3eb2e3efb02d874a1b4edfc559cb Mon Sep 17 00:00:00 2001 From: zsloan Date: Wed, 12 Aug 2020 15:46:13 -0500 Subject: Fix positioning for many instances of text in the mapping figure * wqflask/wqflask/marker_regression/display_mapping_results.py: Many text instances had their positions changed by the switch from piddle to PIL. Change various Y offsets and in some cases changing the logic of the way text is positioned related to its length and font size. * wqflask/wqflask/static/fonts/verdanab.ttf: Add bold Verdana, since there needs to be a separate font file for bold text. --- .../marker_regression/display_mapping_results.py | 40 ++++++++++++--------- wqflask/wqflask/static/fonts/verdanab.ttf | Bin 0 -> 156340 bytes 2 files changed, 23 insertions(+), 17 deletions(-) create mode 100644 wqflask/wqflask/static/fonts/verdanab.ttf (limited to 'wqflask') diff --git a/wqflask/wqflask/marker_regression/display_mapping_results.py b/wqflask/wqflask/marker_regression/display_mapping_results.py index 6f50601d..bda899fb 100644 --- a/wqflask/wqflask/marker_regression/display_mapping_results.py +++ b/wqflask/wqflask/marker_regression/display_mapping_results.py @@ -73,6 +73,7 @@ MEDIUMPURPLE = ImageColor.getrgb("mediumpurple") # ---- FONT FILES ---- # VERDANA_FILE = "./wqflask/static/fonts/verdana.ttf" +VERDANA_BOLD_FILE = "./wqflask/static/fonts/verdanab.ttf" TREBUC_FILE = "./wqflask/static/fonts/trebucbd.ttf" FNT_BS_FILE = "./wqflask/static/fonts/fnt_bs.ttf" ARIAL_FILE = "./wqflask/static/fonts/arial.ttf" @@ -1719,18 +1720,16 @@ class DisplayMappingResults(object): font=clickableRegionLabelFont, fill=self.CLICKABLE_ENSEMBL_TEXT_COLOR) #draw the gray text - chrFont = ImageFont.truetype(font=VERDANA_FILE, size=26*zoom) - traitFont = ImageFont.truetype(font=VERDANA_FILE, size=14) + chrFont = ImageFont.truetype(font=VERDANA_BOLD_FILE, size=26*zoom) chrX = xLeftOffset + plotWidth - 2 - im_drawer.textsize( "Chr %s" % self.ChrList[self.selectedChr][0], font=chrFont)[0] im_drawer.text( text="Chr %s" % self.ChrList[self.selectedChr][0], - xy=(chrX, ensemblPaddingTop-5), font=chrFont, fill=GRAY) + xy=(chrX, phenogenPaddingTop), font=chrFont, fill=GRAY) # end of drawBrowserClickableRegions else: #draw the gray text chrFont = ImageFont.truetype(font=VERDANA_FILE, size=26*zoom) - traitFont = ImageFont.truetype(font=VERDANA_FILE, size=14) chrX = xLeftOffset + (plotWidth - im_drawer.textsize( "Chr %s" % currentChromosome, font=chrFont)[0])/2 im_drawer.text( @@ -1751,7 +1750,7 @@ class DisplayMappingResults(object): #Parameters NUM_MINOR_TICKS = 5 # Number of minor ticks between major ticks - X_MAJOR_TICK_THICKNESS = 2 + X_MAJOR_TICK_THICKNESS = 3 X_MINOR_TICK_THICKNESS = 1 X_AXIS_THICKNESS = 1*zoom @@ -1762,10 +1761,10 @@ class DisplayMappingResults(object): xAxisTickMarkColor = BLACK xAxisLabelColor = BLACK fontHeight = 12*fontZoom # How tall the font that we're using is - spacingFromLabelToAxis = 5 + spacingFromLabelToAxis = 10 if self.plotScale == 'physic': - strYLoc = yZero + spacingFromLabelToAxis + MBLabelFont.font.height + strYLoc = yZero + MBLabelFont.font.height/2 ###Physical single chromosome view if self.selectedChr > -1: XScale = Plot.detScale(startMb, endMb) @@ -1826,18 +1825,17 @@ class DisplayMappingResults(object): yZero+10*zoom), fill=BLACK, angle=270) startPosX += (self.ChrLengthDistList[i]+self.GraphInterval)*plotXScale - TEXT_Y_DISPLACEMENT = -15 megabaseLabelFont = ImageFont.truetype(font=VERDANA_FILE, size=int(18*zoom*1.5)) im_drawer.text( text="Megabases", xy=( xLeftOffset+(plotWidth-im_drawer.textsize( "Megabases",font=megabaseLabelFont)[0])/2, - strYLoc+MBLabelFont.font.height+10*(zoom%2)+TEXT_Y_DISPLACEMENT), + strYLoc+MBLabelFont.font.height+10*(zoom%2)), font=megabaseLabelFont, fill=BLACK) pass else: - strYLoc = yZero + spacingFromLabelToAxis + MBLabelFont.font.height + 8 + strYLoc = yZero + spacingFromLabelToAxis + MBLabelFont.font.height/2 ChrAInfo = [] preLpos = -1 distinctCount = 0.0 @@ -1933,12 +1931,12 @@ class DisplayMappingResults(object): fill=lineColor) startPosX += (self.ChrLengthDistList[j]+self.GraphInterval)*plotXScale - centimorganLabelFont = ImageFont.truetype(font=VERDANA_FILE, size=18*zoom*1.5) + centimorganLabelFont = ImageFont.truetype(font=VERDANA_FILE, size=int(18*zoom*1.5)) im_drawer.text( text="Centimorgans", xy=(xLeftOffset+(plotWidth-im_drawer.textsize( - "Megabases", font=centimorganLabelFont)[0])/2, - strYLoc + MBLabelFont.font.height+ 10*(zoom%2) + 10), + "Centimorgans", font=centimorganLabelFont)[0])/2, + strYLoc + MBLabelFont.font.height+ 10*(zoom%2)), font=centimorganLabelFont, fill=BLACK) im_drawer.line(xy=((xLeftOffset,yZero), (xLeftOffset+plotWidth,yZero)), @@ -2055,8 +2053,16 @@ class DisplayMappingResults(object): LRSLODFont=ImageFont.truetype(font=VERDANA_FILE, size=int(18*zoom*1.5)) yZero = yTopOffset + plotHeight - TEXT_X_DISPLACEMENT = -20 - TEXT_Y_DISPLACEMENT = -215 + # TEXT_X_DISPLACEMENT = -20 + #TEXT_Y_DISPLACEMENT = -215 + if all_int: + TEXT_X_DISPLACEMENT = -12 + else: + TEXT_X_DISPLACEMENT = -30 + if self.LRS_LOD == "-log(p)": + TEXT_Y_DISPLACEMENT = -242 + else: + TEXT_Y_DISPLACEMENT = -210 draw_rotated_text( canvas, text=self.LRS_LOD, font=LRSLODFont, xy=(xLeftOffset - im_drawer.textsize( @@ -2140,7 +2146,7 @@ class DisplayMappingResults(object): else: if self.additiveChecked: additiveMax = max(map(lambda X : abs(X['additive']), self.qtlresults)) - lrsEdgeWidth = 2 + lrsEdgeWidth = 3 if zoom == 2: lrsEdgeWidth = 2 * lrsEdgeWidth @@ -2307,7 +2313,7 @@ class DisplayMappingResults(object): text="5", xy=( Xc-im_drawer.textsize("5",font=symbolFont)[0]/2+1, - Yc+2), + Yc-4), fill=point_color, font=symbolFont) else: LRSCoordXY.append((Xc, Yc)) diff --git a/wqflask/wqflask/static/fonts/verdanab.ttf b/wqflask/wqflask/static/fonts/verdanab.ttf new file mode 100644 index 00000000..1a99258f Binary files /dev/null and b/wqflask/wqflask/static/fonts/verdanab.ttf differ -- cgit v1.2.3