@@ -596,122 +596,37 @@ def update_params_for_interventions(self):
596
596
597
597
processed_params = self .processed_params
598
598
599
- def expand_to_age_years (values_by_age_groups , ages_by_year ):
600
- _d = dict (zip (['15-19' , '20-24' , '25-29' , '30-34' , '35-39' , '40-44' , '45-49' ], values_by_age_groups ))
601
- return np .array (
602
- [_d [self .sim .modules ['Demography' ].AGE_RANGE_LOOKUP [_age_year ]] for _age_year in ages_by_year ]
603
- )
604
-
605
- def time_age_trend_in_initiation ():
606
- """The age-specific effect of calendar year on the probability of starting use of contraceptive
607
- (multiplicative effect). Values are chosen to induce a trend in age-specific fertility consistent with
608
- the WPP estimates."""
609
-
610
- _years = np .arange (2010 , 2101 )
611
- _ages = np .arange (15 , 50 )
612
-
613
- _init_over_time = np .exp (+ 0.05 * np .minimum (2020 - 2010 , (_years - 2010 ))) * np .maximum (1.0 , np .exp (
614
- + 0.01 * (_years - 2020 )))
615
- _init_over_time_modification_by_age = 1.0 / expand_to_age_years ([1.0 , 0.5 , 0.5 , 0.5 , 0.5 , 0.5 , 0.5 ], _ages )
616
- _init = np .outer (_init_over_time , _init_over_time_modification_by_age )
617
-
618
- return pd .DataFrame (index = _years , columns = _ages , data = _init )
619
-
620
- def avoid_sterilization_below30 (probs ):
621
- """Prevent women below 30 years having female sterilization and adjust the probability for women 30 and over
622
- to preserve the overall probability of initiating sterilization."""
623
- # Input 'probs' must include probs for all methods including 'not_using'
624
- assert set (probs .index ) == set (self .all_contraception_states )
625
-
626
- # Prevent women below 30 years having 'female_sterilization'
627
- probs_below30 = probs .copy ()
628
- probs_below30 ['female_sterilization' ] = 0.0
629
- # Scale so that the probability of all outcomes sum to 1.0
630
- probs_below30 = probs_below30 / probs_below30 .sum ()
631
- assert np .isclose (1.0 , probs_below30 .sum ())
632
-
633
- # Increase prob of 'female_sterilization' in older women accordingly
634
- probs_30plus = probs .copy ()
635
- probs_30plus ['female_sterilization' ] = (
636
- probs .loc ['female_sterilization' ] /
637
- self .ratio_n_females_30_49_to_15_49_in_2010
638
- )
639
- # Scale so that the probability of all outcomes sum to 1.0
640
- probs_30plus = probs_30plus / probs_30plus .sum ()
641
- assert np .isclose (1.0 , probs_30plus .sum ())
642
-
643
- return probs_below30 , probs_30plus
644
-
645
- def contraception_initiation_with_interv ():
646
- """Generate the probability per month of a woman initiating onto each contraceptive, by the age (in whole
647
- years) if FP interventions are applied."""
648
-
649
- # Probability of initiation by method per month (average over all ages)
650
- p_init_by_method = self .parameters ['Initiation_ByMethod' ].loc [0 ]
651
-
652
- # Prevent women below 30 years having 'female_sterilization' while preserving the overall probability of
653
- # 'female_sterilization' initiation
654
- p_init_by_method_below30 , p_init_by_method_30plus = avoid_sterilization_below30 (p_init_by_method )
655
-
656
- # Effect of age
657
- age_effect = 1.0 + self .parameters ['Initiation_ByAge' ].set_index ('age' )['r_init1_age' ].rename_axis (
658
- "age_years" )
659
-
660
- # Year effect
661
- year_effect = time_age_trend_in_initiation ()
662
-
663
- def apply_intervention_age_year_effects (probs_below30 , probs_30plus ):
664
- # Apply Pop intervention
665
- probs_by_method_below30 = \
666
- probs_below30 .copy ().drop ('not_using' ).mul (self .parameters ['Interventions_Pop' ].loc [0 ])
667
- probs_by_method_30plus = \
668
- probs_30plus .copy ().drop ('not_using' ).mul (self .parameters ['Interventions_Pop' ].loc [0 ])
669
- # Assemble into age-specific data-frame:
670
- p_init = dict ()
671
- for year in year_effect .index :
672
-
673
- p_init_this_year = dict ()
674
- for a in age_effect .index :
675
- if a < 30 :
676
- p_init_this_year [a ] = probs_by_method_below30 * age_effect .at [a ] * year_effect .at [year , a ]
677
- else :
678
- p_init_this_year [a ] = probs_by_method_30plus * age_effect .at [a ] * year_effect .at [year , a ]
679
- p_init_this_year_df = pd .DataFrame .from_dict (p_init_this_year , orient = 'index' )
680
-
681
- # Check correct format of age/method data-frame
682
- assert set (p_init_this_year_df .columns ) == set (self .all_contraception_states - {'not_using' })
683
- assert (p_init_this_year_df .index == range (15 , 50 )).all ()
684
- assert (p_init_this_year_df >= 0.0 ).all ().all ()
685
-
686
- p_init [year ] = p_init_this_year_df
687
-
688
- return p_init
689
-
690
- return apply_intervention_age_year_effects (p_init_by_method_below30 , p_init_by_method_30plus )
691
-
692
- def contraception_initiation_after_birth_with_interv ():
693
- """Get the probability of a woman starting a contraceptive following giving birth if FP interventions are
694
- applied. Avoid sterilization in women below 30 years old."""
695
-
696
- # Get initiation probabilities of contraception methods after birth from read-in Excel sheet
697
- p_start_after_birth = self .parameters ['Initiation_AfterBirth' ].loc [0 ].drop ('not_using' )
698
-
699
- # Apply PPFP intervention multipliers
700
- p_start_after_birth = p_start_after_birth .mul (self .parameters ['Interventions_PPFP' ].loc [0 ])
701
-
702
- # Add 'not_using' to initiation probabilities of contraception methods after birth
703
- p_start_after_birth = pd .concat (
704
- (
705
- pd .Series ((1.0 - p_start_after_birth .sum ()), index = ['not_using' ]),
706
- p_start_after_birth
707
- )
708
- )
709
-
710
- return avoid_sterilization_below30 (p_start_after_birth )
711
-
712
- processed_params ['p_start_per_month' ] = contraception_initiation_with_interv ()
713
- processed_params ['p_start_after_birth_below30' ], processed_params ['p_start_after_birth_30plus' ] = \
714
- contraception_initiation_after_birth_with_interv ()
599
+ def contraception_initiation_with_interv (p_start_per_month_without_interv ):
600
+ """Increase the probabilities of a woman starting modern contraceptives due to Pop intervention being
601
+ applied."""
602
+ p_start_per_month_with_interv = {}
603
+ for year , age_method_df in p_start_per_month_without_interv .items ():
604
+ if year >= self .sim .date .year :
605
+ p_start_per_month_with_interv [year ] = age_method_df * self .parameters ['Interventions_Pop' ].loc [0 ]
606
+ return p_start_per_month_with_interv
607
+
608
+ def contraception_initiation_after_birth_with_interv (p_start_after_birth_without_interv ):
609
+ """Increase the probabilities of a woman starting modern contraceptives following giving birth due to PPFP
610
+ intervention being applied."""
611
+ # Exclude prob of 'not_using'
612
+ p_start_after_birth_with_interv = p_start_after_birth_without_interv .copy ().drop ('not_using' )
613
+
614
+ # Apply PPFP intervention multipliers (ie increase probs of modern methods)
615
+ p_start_after_birth_with_interv = \
616
+ p_start_after_birth_with_interv .mul (self .parameters ['Interventions_PPFP' ].loc [0 ])
617
+
618
+ # Return reduced prob of 'not_using'
619
+ p_start_after_birth_with_interv = pd .Series ((1.0 - p_start_after_birth_with_interv .sum ()),
620
+ index = ['not_using' ]).append (p_start_after_birth_with_interv )
621
+
622
+ return p_start_after_birth_with_interv
623
+
624
+ processed_params ['p_start_per_month' ] = \
625
+ contraception_initiation_with_interv (processed_params ['p_start_per_month' ])
626
+ processed_params ['p_start_after_birth_below30' ] = \
627
+ contraception_initiation_after_birth_with_interv (processed_params ['p_start_after_birth_below30' ])
628
+ processed_params ['p_start_after_birth_30plus' ] = \
629
+ contraception_initiation_after_birth_with_interv (processed_params ['p_start_after_birth_30plus' ])
715
630
716
631
return processed_params
717
632
0 commit comments