11import json
22import math
33import os
4- import pathlib
54import sys
6- import tempfile
75import warnings
86from collections import Counter
97from functools import partial
2119from emod_api .demographics .age_distribution_old import AgeDistributionOld as AgeDistribution
2220from emod_api .demographics .demographic_exceptions import InvalidNodeIdException
2321from emod_api .demographics .mortality_distribution_old import MortalityDistributionOld as MortalityDistribution
24- from emod_api .migration import migration
2522
2623
2724class DemographicsBase (BaseInputFile ):
@@ -366,43 +363,7 @@ def get_nodes_by_name(self, node_names: List[str]) -> Dict[str, Node]:
366363 if node_name in node_names }
367364 return requested_nodes
368365
369- def SetMigrationPattern (self , pattern : str = "rwd" ):
370- """
371- Set migration pattern. Migration is enabled implicitly.
372- It's unusual for the user to need to set this directly; normally used by emodpy.
373-
374- Args:
375- pattern: Possible values are "rwd" for Random Walk Diffusion and "srt" for Single Round Trips.
376- """
377- if self .implicits is not None :
378- if pattern .lower () == "srt" :
379- self .implicits .append (DT ._set_migration_pattern_srt )
380- elif pattern .lower () == "rwd" :
381- self .implicits .append (DT ._set_migration_pattern_rwd )
382- else :
383- raise ValueError ('Unknown migration pattern: %s. Possible values are "rwd" and "srt".' , pattern )
384-
385- def _SetRegionalMigrationFileName (self , file_name ):
386- """
387- Set path to migration file.
388-
389- Args:
390- file_name: Path to migration file.
391- """
392- if self .implicits is not None :
393- self .implicits .append (partial (DT ._set_regional_migration_filenames , file_name = file_name ))
394-
395- def _SetLocalMigrationFileName (self , file_name ):
396- """
397- Set path to migration file.
398-
399- Args:
400- file_name: Path to migration file.
401- """
402- if self .implicits is not None :
403- self .implicits .append (partial (DT ._set_local_migration_filename , file_name = file_name ))
404-
405- def _SetDemographicFileNames (self , file_names ):
366+ def set_demographics_filenames (self , file_names : List [str ]):
406367 """
407368 Set paths to demographic file.
408369
@@ -412,127 +373,6 @@ def _SetDemographicFileNames(self, file_names):
412373 if self .implicits is not None :
413374 self .implicits .append (partial (DT ._set_demographic_filenames , file_names = file_names ))
414375
415- def SetRoundTripMigration (self ,
416- gravity_factor : float ,
417- probability_of_return : float = 1.0 ,
418- id_ref : str = 'short term commuting migration' ):
419- """
420- Set commuter/seasonal/temporary/round-trip migration rates. You can use the x_Local_Migration configuration
421- parameter to tune/calibrate.
422-
423- Args:
424- gravity_factor: 'Big G' in gravity equation. Combines with 1, 1, and -2 as the other exponents.
425- probability_of_return: Likelihood that an individual who 'commuter migrates' will return to the node
426- of origin during the next migration (not timestep). Defaults to 1.0. Aka, travel,
427- shed, return."
428- id_ref: Text string that appears in the migration file itself; needs to match corresponding demographics
429- file.
430- """
431- if gravity_factor < 0 :
432- raise ValueError ("gravity factor can't be negative." )
433-
434- gravity_params = [gravity_factor , 1.0 , 1.0 , - 2.0 ]
435- if probability_of_return < 0 or probability_of_return > 1.0 :
436- raise ValueError (f"probability_of_return parameter passed by not a probability: { probability_of_return } " )
437-
438- mig = migration ._from_demog_and_param_gravity (self , gravity_params = gravity_params ,
439- id_ref = id_ref ,
440- migration_type = migration .Migration .LOCAL )
441- migration_file_path = tempfile .NamedTemporaryFile ().name + ".bin"
442- mig .to_file (migration_file_path )
443- self .migration_files .append (migration_file_path )
444-
445- if self .implicits is not None :
446- self .implicits .append (partial (DT ._set_local_migration_roundtrip_probability ,
447- probability_of_return = probability_of_return ))
448- self .implicits .append (partial (DT ._set_local_migration_filename ,
449- file_name = pathlib .PurePath (migration_file_path ).name ))
450- self .SetMigrationPattern ("srt" )
451-
452- def SetOneWayMigration (self ,
453- rates_path : Union [str , os .PathLike ],
454- id_ref : str = 'long term migration' ):
455- """
456- Set one way migration. You can use the x_Regional_Migration configuration parameter to tune/calibrate.
457-
458- Args:
459- rates_path: Path to csv file with node-to-node migration rates. Format is: source (node id),destination
460- (node id),rate.
461- id_ref: Text string that appears in the migration file itself; needs to match corresponding demographics
462- file.
463- """
464-
465- mig = migration .from_csv (pathlib .Path (rates_path ), id_ref = id_ref , mig_type = migration .Migration .REGIONAL )
466- migration_file_path = tempfile .NamedTemporaryFile ().name + ".bin"
467- mig .to_file (migration_file_path )
468- self .migration_files .append (migration_file_path )
469-
470- if self .implicits is not None :
471- self .implicits .append (partial (DT ._set_regional_migration_roundtrip_probability , probability_of_return = 0.0 ))
472- self .implicits .append (partial (DT ._set_regional_migration_filenames ,
473- file_name = pathlib .PurePath (migration_file_path ).name ))
474- self .SetMigrationPattern ("srt" )
475-
476- def SetSimpleVitalDynamics (self ,
477- crude_birth_rate : CrudeRate = CrudeRate (40 ),
478- crude_death_rate : CrudeRate = CrudeRate (20 ),
479- node_ids : List = None ):
480- """
481- Set fertility, mortality, and initial age with single birth rate and single mortality rate.
482-
483- Args:
484- crude_birth_rate: Birth rate, per year per kiloperson.
485- crude_death_rate: Mortality rate, per year per kiloperson.
486- node_ids: Optional list of nodes to limit these settings to.
487-
488- """
489-
490- self .SetBirthRate (crude_birth_rate , node_ids )
491- self .SetMortalityRate (crude_death_rate , node_ids )
492- self .SetEquilibriumAgeDistFromBirthAndMortRates (crude_birth_rate , crude_death_rate , node_ids )
493-
494- # TODO: is this useful in a way that warrants a special-case function in emodpy?
495- # https://github.com/InstituteforDiseaseModeling/emod-api-old/issues/790
496- def SetEquilibriumVitalDynamics (self ,
497- crude_birth_rate : CrudeRate = CrudeRate (40 ),
498- node_ids : List = None ):
499- """
500- Set fertility, mortality, and initial age with single rate and mortality to achieve steady state population.
501-
502- Args:
503- crude_birth_rate: Birth rate. And mortality rate.
504- node_ids: Optional list of nodes to limit these settings to.
505-
506- """
507-
508- self .SetSimpleVitalDynamics (crude_birth_rate , crude_birth_rate , node_ids )
509-
510- # TODO: is this useful in a way that warrants a special-case function in emodpy?
511- # https://github.com/InstituteforDiseaseModeling/emod-api-old/issues/791
512- def SetEquilibriumVitalDynamicsFromWorldBank (self ,
513- wb_births_df : pd .DataFrame ,
514- country : str ,
515- year : int ,
516- node_ids : List = None ):
517- """
518- Set steady-state fertility, mortality, and initial age with rates from world bank, for given country and year.
519-
520- Args:
521- wb_births_df: Pandas dataframe with World Bank birth rate by country and year.
522- country: Country to pick from World Bank dataset.
523- year: Year to pick from World Bank dataset.
524- node_ids: Optional list of nodes to limit these settings to.
525-
526- """
527-
528- try :
529- birth_rate = CrudeRate (wb_births_df [wb_births_df ['Country Name' ] == country ][str (year )].tolist ()[0 ])
530- # result_scale_factor = 2.74e-06 # assuming world bank units for input
531- # birth_rate *= result_scale_factor # from births per 1000 pop per year to per person per day
532- except Exception as ex :
533- raise ValueError (f"Exception trying to find { year } and { country } in dataframe.\n { ex } " )
534- self .SetEquilibriumVitalDynamics (birth_rate , node_ids )
535-
536376 def SetDefaultIndividualAttributes (self ):
537377 """
538378 NOTE: This is very Measles-ish. We might want to move into MeaslesDemographics
@@ -888,22 +728,6 @@ def SetInitialAgeLikeSubSaharanAfrica(self, description=""):
888728
889729 self .SetInitialAgeExponential (description = description ) # use default rate
890730
891- def SetOverdispersion (self , new_overdispersion_value , nodes : List = None ):
892- """
893- Set the overdispersion value for the specified nodes (all if empty).
894- """
895- if nodes is None :
896- nodes = []
897-
898- def enable_overdispersion (config ):
899- print ("DEBUG: Setting 'Enable_Infection_Rate_Overdispersion' to 1." )
900- config .parameters .Enable_Infection_Rate_Overdispersion = 1
901- return config
902-
903- if self .implicits is not None :
904- self .implicits .append (enable_overdispersion )
905- self .raw ['Defaults' ]['NodeAttributes' ]["InfectivityOverdispersion" ] = new_overdispersion_value
906-
907731 def SetInitPrevFromUniformDraw (self , min_init_prev , max_init_prev , description = "" ):
908732 """
909733 Set Initial Prevalence (one value per node) drawn from an uniform distribution.
0 commit comments