@@ -515,9 +515,9 @@ def calculate_kinetics(self):
515
515
end_milestones = {}
516
516
bulk_milestones = []
517
517
MFPTs = {}
518
+ MFPTs_anchors_to_bulk_milestones = defaultdict (float )
518
519
k_off = 0.0
519
520
k_ons = {}
520
- bulk_milestone = None
521
521
for anchor in self .model .anchors :
522
522
if anchor .endstate :
523
523
for milestone_id in anchor .get_ids ():
@@ -532,8 +532,8 @@ def calculate_kinetics(self):
532
532
if anchor .alias_from_id (milestone_id ) == 1 :
533
533
# TODO: hacky
534
534
continue
535
- # bulk_milestones.append(milestone_id)
536
- bulk_milestone = milestone_id
535
+ bulk_milestones .append (milestone_id )
536
+ # bulk_milestone = milestone_id
537
537
538
538
if np .any (self .Q .sum (axis = 1 ) > 1.E-10 ):
539
539
problem_milestone = np .argmin (self .Q .T .sum (axis = 1 ))
@@ -547,75 +547,92 @@ def calculate_kinetics(self):
547
547
problem_milestone )
548
548
raise Exception (error_msg )
549
549
B , tau = PyGT .tools .load_CTMC (self .Q .T )
550
- assert len (bulk_milestones ) <= 1 , \
551
- "There cannot be more than one bulk milestone."
552
- if bulk_milestone is not None :
553
- n = self .Q .shape [0 ]
554
- for end_milestone in end_milestones :
555
- if end_milestone == bulk_milestone :
550
+ #assert len(bulk_milestones) <= 1, \
551
+ # "There cannot be more than one bulk milestone."
552
+ #if bulk_milestone is not None:
553
+ p_i_hat_normalize_per_anchor = defaultdict (float )
554
+ for end_milestone_src in end_milestones :
555
+ src_anchor_index = end_milestones [end_milestone_src ]
556
+ p_i_hat_normalize_per_anchor [src_anchor_index ] \
557
+ += self .p_i [end_milestone_src ]
558
+
559
+ n = self .Q .shape [0 ]
560
+ for bulk_milestone in bulk_milestones :
561
+ for end_milestone_src in end_milestones :
562
+
563
+ if end_milestone_src in bulk_milestones :
556
564
continue
557
565
558
566
mfpt_ij , mfpt_ji = PyGT .mfpt .compute_MFPT (
559
- end_milestone , bulk_milestone , B , tau )
567
+ end_milestone_src , bulk_milestone , B , tau )
560
568
mfpt = mfpt_ji
561
- MFPTs [(end_milestones [end_milestone ], "bulk" )] = mfpt
562
-
563
- MFPT_to_bulk = 0
569
+ src_anchor_index = end_milestones [end_milestone_src ]
570
+ weighted_mfpt = mfpt * self .p_i [end_milestone_src ] \
571
+ / p_i_hat_normalize_per_anchor [src_anchor_index ]
572
+ #MFPTs[(src_anchor_index, "bulk")] += weighted_mfpt
573
+ MFPTs_anchors_to_bulk_milestones [(src_anchor_index , bulk_milestone )] \
574
+ += weighted_mfpt
575
+
576
+ for (mfpt_key , mfpt_value ) in MFPTs_anchors_to_bulk_milestones .items ():
577
+ (src_anchor_index , bulk_milestone ) = mfpt_key
578
+ if src_anchor_index not in MFPTs :
579
+ MFPTs [(src_anchor_index , "bulk" )] = mfpt_value
580
+ elif mfpt_value < MFPTs [src_anchor ]:
581
+ MFPTs [(src_anchor_index , "bulk" )] = mfpt_value
582
+
583
+ MFPTs_to_bulk_dict = {}
584
+ for bulk_milestone in bulk_milestones :
564
585
for i in range (self .model .num_milestones ):
565
586
mfpt_ij , mfpt_ji = PyGT .mfpt .compute_MFPT (
566
587
i , bulk_milestone , B , tau )
567
588
mfpt = mfpt_ji
589
+ if i not in MFPTs_to_bulk_dict :
590
+ MFPTs_to_bulk_dict [i ] = mfpt
591
+ elif mfpt < MFPTs_to_bulk_dict [i ]:
592
+ MFPTs_to_bulk_dict [i ] = mfpt
593
+
594
+ if len (bulk_milestones ) > 0 :
595
+ MFPT_to_bulk = 0
596
+ for i in range (self .model .num_milestones ):
597
+ mfpt = MFPTs_to_bulk_dict [i ]
568
598
MFPT_to_bulk += mfpt * self .p_i [i ]
569
599
570
600
# convert to 1/s
571
601
k_off = 1.0e12 / MFPT_to_bulk
572
602
self .k_off = k_off
573
603
574
- p_i_hat_normalize = defaultdict (float )
575
-
576
- for end_milestone_dest in end_milestones :
577
- if end_milestone_dest == bulk_milestone :
578
- continue
579
- for end_milestone_src in end_milestones :
580
- if end_milestones [end_milestone_dest ] \
581
- == end_milestones [end_milestone_src ]:
582
- continue
583
- if end_milestone_src == bulk_milestone :
584
- continue
585
- p_i_hat_normalize [end_milestone_src ] \
586
- += self .p_i [end_milestone_src ]
587
-
588
604
# Next, compute the MFPTs between different states
589
605
possible_MFPTs = defaultdict (float )
590
606
for end_milestone_dest in end_milestones :
591
- if end_milestone_dest == bulk_milestone :
607
+ dest_anchor_index = end_milestones [end_milestone_dest ]
608
+ if end_milestone_dest in bulk_milestones :
592
609
continue
593
610
594
611
for end_milestone_src in end_milestones :
595
- if end_milestones [end_milestone_dest ] \
596
- == end_milestones [ end_milestone_src ] :
612
+ src_anchor_index = end_milestones [end_milestone_src ]
613
+ if dest_anchor_index == src_anchor_index :
597
614
# don't get the MFPT from a milestone to itself
598
615
continue
599
- if end_milestone_src == bulk_milestone :
616
+ if end_milestone_src in bulk_milestones :
600
617
# a bulk milestone will never be a source
601
618
continue
602
619
603
620
mfpt_ij , mfpt_ji = PyGT .mfpt .compute_MFPT (
604
621
end_milestone_src , end_milestone_dest , B , tau )
605
622
mfpt = mfpt_ji
606
- possible_MFPTs [(end_milestones [end_milestone_src ],
607
- end_milestone_dest )] += mfpt \
623
+ possible_MFPTs [(src_anchor_index , end_milestone_dest )] += mfpt \
608
624
* self .p_i [end_milestone_src ] \
609
- / p_i_hat_normalize [ end_milestone_src ]
625
+ / p_i_hat_normalize_per_anchor [ src_anchor_index ]
610
626
611
627
# TODO: verify if correct: this finds the destination with the
612
628
# fastest MFPT and just uses that, although the sources are
613
629
# statistically weighed.
614
630
for end_milestone_src in end_milestones :
631
+ src_anchor_index = end_milestones [end_milestone_src ]
615
632
for end_milestone_dest in end_milestones :
616
- key = ( end_milestones [end_milestone_src ], end_milestone_dest )
617
- full_key = (end_milestones [ end_milestone_src ],
618
- end_milestones [ end_milestone_dest ] )
633
+ dest_anchor_index = end_milestones [end_milestone_dest ]
634
+ key = (src_anchor_index , end_milestone_dest )
635
+ full_key = ( src_anchor_index , dest_anchor_index )
619
636
if key in possible_MFPTs :
620
637
if full_key in MFPTs :
621
638
# Get the minimum MFPT
0 commit comments