1
1
""" OWClusterAnalysis """
2
+
2
3
import sys
3
4
import itertools
4
5
36
37
)
37
38
from Orange .widgets .utils .signals import Input , Output
38
39
39
- from orangecontrib .bioinformatics .geneset . utils import GeneSetException
40
+ from orangecontrib .bioinformatics .geneset import GeneSets
40
41
from orangecontrib .bioinformatics .cluster_analysis import (
41
42
DISPLAY_GENE_SETS_COUNT ,
42
43
Cluster ,
47
48
from orangecontrib .bioinformatics .widgets .utils .gui import (
48
49
HTMLDelegate ,
49
50
GeneScoringWidget ,
50
- GeneSetsSelection ,
51
51
)
52
+ from orangecontrib .bioinformatics .widgets .components import GeneSetSelection
52
53
from orangecontrib .bioinformatics .widgets .utils .data import (
53
54
TAX_ID ,
54
55
GENE_ID_COLUMN ,
58
59
59
60
60
61
class ClusterAnalysisContextHandler (PerfectDomainContextHandler ):
61
- def encode_setting (self , context , setting , value ):
62
+ def encode_setting (self , context , setting , value , * args ):
62
63
if setting .name == 'cluster_indicators' :
63
64
value = [(var .name , 100 + vartype (var )) for var in value ]
64
- return super ().encode_setting (context , setting , value )
65
+ return super ().encode_setting (context , setting , value , * args )
65
66
66
- def decode_setting (self , setting , value , domain = None ):
67
+ def decode_setting (self , setting , value , domain = None , * args ):
67
68
return (
68
69
[domain [var [0 ]] for var in value ]
69
70
if setting .name == 'cluster_indicators'
70
- else super ().decode_setting (setting , value , domain )
71
+ else super ().decode_setting (setting , value , domain , * args )
71
72
)
72
73
73
74
@@ -107,6 +108,9 @@ class Error(OWWidget.Error):
107
108
'Organism in input data and custom gene sets does not match'
108
109
)
109
110
cluster_batch_conflict = Msg ('Cluster and batch must not be the same variable' )
111
+ custom_gene_sets_table_format = Msg (
112
+ 'Custom gene sets data must have genes represented as rows.'
113
+ )
110
114
111
115
settingsHandler = ClusterAnalysisContextHandler ()
112
116
cluster_indicators = ContextSetting ([])
@@ -215,31 +219,14 @@ def __init__(self):
215
219
self .gene_scoring .set_method_design_area ('scoring_method_design' )
216
220
self .gene_scoring .set_test_type ('scoring_test_type' )
217
221
218
- # Gene Sets widget
219
- gene_sets_box = widgetBox (self . controlArea , "Gene Sets" )
220
- self .gs_widget = GeneSetsSelection (
221
- gene_sets_box , self , 'stored_gene_sets_selection'
222
+ box = vBox ( self . controlArea , True , margin = 0 )
223
+ self . gs_selection_component : GeneSetSelection = GeneSetSelection (self , box )
224
+ self .gs_selection_component . selection_changed . connect (
225
+ self . _on_selection_changed
222
226
)
223
- self .gs_widget .hierarchy_tree_widget .itemClicked .connect (
224
- self .__gene_sets_enrichment
225
- )
226
-
227
- # custom gene sets area
228
- box = vBox (self .controlArea , "Custom Gene Sets" )
229
-
230
- if self .custom_gene_set_indicator not in self .feature_model :
231
- self .custom_gene_set_indicator = None
232
-
233
- self .gs_label_combobox = comboBox (
234
- box ,
235
- self ,
236
- "custom_gene_set_indicator" ,
237
- sendSelectedValue = True ,
238
- model = self .feature_model ,
239
- callback = self .handle_custom_gene_sets ,
240
- )
241
- self .gs_label_combobox .setDisabled (True )
242
-
227
+ self .gs_selection_component .sample_column_combo .hide ()
228
+ self .gs_selection_component .sample_column_combo .parent ().hide ()
229
+ self .gs_selection_component ._update_tree_widget ()
243
230
# main area
244
231
splitter = QSplitter (Qt .Horizontal , self .mainArea )
245
232
self .mainArea .layout ().addWidget (splitter )
@@ -386,7 +373,7 @@ def __create_temp_class_var(self):
386
373
row_profile = None
387
374
new_cluster_values = []
388
375
var_index_lookup = {
389
- val : idx
376
+ ( var . name , str ( val )) : idx
390
377
for var in self .cluster_indicators
391
378
for idx , val in enumerate (var .values )
392
379
}
@@ -396,7 +383,12 @@ def __create_temp_class_var(self):
396
383
)
397
384
for comb in cart_prod :
398
385
new_cluster_values .append (', ' .join (list (comb )))
399
- self .new_cluster_profile .append ([var_index_lookup [val ] for val in comb ])
386
+ self .new_cluster_profile .append (
387
+ [
388
+ var_index_lookup [(var .name , str (val ))]
389
+ for var , val in zip (self .cluster_indicators , comb )
390
+ ]
391
+ )
400
392
401
393
row_profile_lookup = {
402
394
tuple (profile ): indx
@@ -418,13 +410,15 @@ def __create_temp_class_var(self):
418
410
ca_ind = DiscreteVariable .make (
419
411
cluster_indicator_name ,
420
412
values = list (new_cluster_values ),
421
- ordered = True ,
422
413
)
423
-
424
414
domain = Domain (
425
415
self .input_data .domain .attributes ,
426
416
self .input_data .domain .class_vars ,
427
- self .input_data .domain .metas + (ca_ind ,),
417
+ (
418
+ self .input_data .domain .metas [:- 1 ] + (ca_ind ,)
419
+ if ca_ind in self .input_data .domain
420
+ else self .input_data .domain .metas + (ca_ind ,)
421
+ ),
428
422
)
429
423
430
424
table = self .input_data .transform (domain )
@@ -512,6 +506,8 @@ def filter_gene_sets(self):
512
506
# call sizeHint function
513
507
self .cluster_info_view .resizeRowsToContents ()
514
508
509
+ self .commit ()
510
+
515
511
def __gene_enrichment (self ):
516
512
design = bool (
517
513
self .gene_scoring .get_selected_desig ()
@@ -538,8 +534,8 @@ def __gene_enrichment(self):
538
534
def __gene_sets_enrichment (self ):
539
535
if self .input_data :
540
536
self .Warning .no_selected_gene_sets .clear ()
541
- all_sets = self .gs_widget . get_hierarchies ()
542
- selected_sets = self .gs_widget . get_hierarchies ( only_selected = True )
537
+ selected_sets = self .gs_selection_component . selection
538
+ all_sets = self .gs_selection_component . gene_sets . hierarchies ( )
543
539
544
540
if len (selected_sets ) == 0 and len (all_sets ) > 0 :
545
541
self .Warning .no_selected_gene_sets ()
@@ -550,7 +546,7 @@ def __gene_sets_enrichment(self):
550
546
551
547
try :
552
548
self .cluster_info_model .gene_sets_enrichment (
553
- self .gs_widget . gs_object , selected_sets , ref_genes
549
+ self .gs_selection_component . gene_sets , selected_sets , ref_genes
554
550
)
555
551
except Exception as e :
556
552
# TODO: possible exceptions?
@@ -580,6 +576,34 @@ def invalidate(self, cluster_init=True):
580
576
def batch_indicator_changed (self ):
581
577
self .invalidate (cluster_init = False )
582
578
579
+ def _on_selection_changed (self ):
580
+ if not self .input_data or not self .gs_selection_component :
581
+ return
582
+ self .num_of_custom_sets = self .gs_selection_component .num_of_custom_sets
583
+
584
+ selected_sets = self .gs_selection_component .selection
585
+ all_sets = self .gs_selection_component .gene_sets .hierarchies ()
586
+
587
+ self .Warning .no_selected_gene_sets .clear ()
588
+ if not selected_sets and all_sets :
589
+ self .Warning .no_selected_gene_sets ()
590
+
591
+ self .stored_gene_sets_selection = tuple (selected_sets )
592
+ ref_genes = set (self .input_genes_ids )
593
+
594
+ if not self .cluster_info_model or len (ref_genes ) == 0 :
595
+ return
596
+ try :
597
+ self .cluster_info_model .gene_sets_enrichment (
598
+ self .gs_selection_component .gene_sets , selected_sets , ref_genes
599
+ )
600
+ except Exception as e :
601
+ raise e
602
+
603
+ self .filter_gene_sets ()
604
+ self .__update_info_box ()
605
+ self .cluster_info_view .resizeRowsToContents ()
606
+
583
607
@Inputs .data_table
584
608
def handle_input (self , data ):
585
609
self .closeContext ()
@@ -596,8 +620,6 @@ def handle_input(self, data):
596
620
self .gene_id_attribute = None
597
621
self .clusters = None
598
622
599
- self .gs_widget .clear ()
600
- self .gs_widget .clear_gene_sets ()
601
623
self .cluster_info_view .setModel (None )
602
624
603
625
self .cluster_indicators = []
@@ -638,6 +660,9 @@ def handle_input(self, data):
638
660
GENE_ID_ATTRIBUTE , None
639
661
)
640
662
663
+ self .gs_selection_component .set_selected_organism_by_tax_id (self .tax_id )
664
+ self .gs_selection_component ._load_gene_sets ()
665
+
641
666
if not self .cluster_indicator_model :
642
667
self .Error .no_cluster_indicator ()
643
668
return
@@ -647,21 +672,17 @@ def handle_input(self, data):
647
672
648
673
self .openContext (self .input_data .domain )
649
674
650
- self .gs_widget .load_gene_sets (self .tax_id )
651
675
if self .cluster_indicator_model and len (self .cluster_indicators ) < 1 :
652
676
self .cluster_indicators = [self .cluster_indicator_model [0 ]]
653
677
if self .batch_indicator_model and self .batch_indicator is None :
654
678
self .batch_indicator = self .batch_indicator_model [0 ]
655
-
656
679
self .invalidate ()
657
-
658
- if self .custom_data :
659
- self .refresh_custom_gene_sets ()
660
- self ._handle_future_model ()
661
- self .handle_custom_gene_sets ()
680
+ else :
681
+ self .gs_selection_component ._gene_sets = GeneSets ()
682
+ self .handle_custom_gene_sets ()
662
683
663
684
@Inputs .custom_sets
664
- def handle_custom_input (self , data ):
685
+ def handle_custom_input (self , custom_data ):
665
686
self .Error .clear ()
666
687
self .Warning .clear ()
667
688
self .closeContext ()
@@ -672,9 +693,8 @@ def handle_custom_input(self, data):
672
693
self .custom_gene_id_column = None
673
694
self .num_of_custom_sets = None
674
695
self .feature_model .set_domain (None )
675
-
676
- if data :
677
- self .custom_data = data
696
+ if custom_data :
697
+ self .custom_data = custom_data
678
698
self .feature_model .set_domain (self .custom_data .domain )
679
699
self .custom_tax_id = str (self .custom_data .attributes .get (TAX_ID , None ))
680
700
self .custom_use_attr_names = self .custom_data .attributes .get (
@@ -686,15 +706,14 @@ def handle_custom_input(self, data):
686
706
self .custom_gene_id_column = self .custom_data .attributes .get (
687
707
GENE_ID_COLUMN , None
688
708
)
689
-
690
- self ._handle_future_model ()
691
-
692
- if self .input_data :
693
- self .openContext (self .input_data .domain )
694
-
695
- self .gs_label_combobox .setDisabled (True )
696
- self .refresh_custom_gene_sets ()
709
+ self .gs_selection_component .initialize_custom_gene_sets (custom_data )
710
+ self .num_of_custom_sets = self .gs_selection_component .num_of_custom_sets
711
+ else :
712
+ self .stored_gene_sets_selection = ()
713
+ self .gs_selection_component .selection = []
714
+ self .gs_selection_component .initialize_custom_gene_sets (None )
697
715
self .handle_custom_gene_sets (select_customs_flag = True )
716
+ self .__update_info_box ()
698
717
699
718
def __check_organism_mismatch (self ):
700
719
"""Check if organisms from different inputs match.
@@ -719,49 +738,21 @@ def handle_custom_gene_sets(self, select_customs_flag=False):
719
738
if self .custom_gene_set_indicator :
720
739
if self .custom_data is not None and self .custom_gene_id_column is not None :
721
740
if self .__check_organism_mismatch ():
722
- self .gs_label_combobox . setDisabled ( True )
741
+ self .gs_selection_component . initialize_custom_gene_sets ( None )
723
742
self .Error .organism_mismatch ()
724
- self .gs_widget .update_gs_hierarchy ()
725
743
self .__gene_sets_enrichment ()
726
744
return
727
-
728
- if isinstance (self .custom_gene_set_indicator , DiscreteVariable ):
729
- labels = self .custom_gene_set_indicator .values
730
- gene_sets_names = [
731
- labels [int (idx )]
732
- for idx in self .custom_data .get_column (
733
- self .custom_gene_set_indicator
734
- )
735
- ]
736
- else :
737
- gene_sets_names = self .custom_data .get_column (
738
- self .custom_gene_set_indicator
739
- )
740
-
741
- self .num_of_custom_sets = len (set (gene_sets_names ))
742
- gene_names = self .custom_data .get_column (self .custom_gene_id_column )
743
- hierarchy_title = (
744
- self .custom_data .name if self .custom_data .name else 'Custom sets' ,
745
- )
746
- try :
747
- self .gs_widget .add_custom_sets (
748
- gene_sets_names ,
749
- gene_names ,
750
- hierarchy_title = hierarchy_title ,
751
- select_customs_flag = select_customs_flag ,
752
- )
753
- except GeneSetException :
754
- pass
755
- self .gs_label_combobox .setDisabled (False )
756
745
else :
757
- self .gs_widget .update_gs_hierarchy ()
758
-
746
+ self .gs_selection_component ._update_tree_widget ()
759
747
self .__gene_sets_enrichment ()
760
748
self .__update_info_box ()
761
749
762
750
def refresh_custom_gene_sets (self ):
763
- self .gs_widget .clear_custom_sets ()
764
- # self.gs_widget.update_gs_hierarchy()
751
+ self .gs_selection_component ._gene_sets .delete_sets_by_hierarchy (
752
+ self .gs_selection_component .custom_gene_set_hierarchy
753
+ )
754
+ self .gs_selection_component .custom_gene_set_hierarchy = None
755
+ self .gs_selection_component ._update_tree_widget ()
765
756
766
757
def gene_scores_output (self , selected_clusters ):
767
758
metas = [
@@ -856,7 +847,15 @@ def commit(self):
856
847
selected_cluster_indexes = set ()
857
848
selected_cluster_genes = set ()
858
849
859
- if not self .input_data or not selected_rows :
850
+ if self .input_data and not selected_rows :
851
+ selected_rows = [
852
+ self .cluster_info_model .index (row , 0 )
853
+ for row in range (self .cluster_info_model .rowCount ())
854
+ ]
855
+
856
+ if not self .input_data :
857
+ self .Outputs .gene_scores .send (None )
858
+ self .Outputs .gene_set_scores .send (None )
860
859
self .Outputs .selected_data .send (None )
861
860
return
862
861
0 commit comments