emod-api 3.2.1__tar.gz → 3.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. {emod_api-3.2.1/emod_api.egg-info → emod_api-3.2.2}/PKG-INFO +1 -1
  2. emod_api-3.2.2/emod_api/__init__.py +1 -0
  3. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/campaign.py +8 -8
  4. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/demographics/node.py +2 -3
  5. {emod_api-3.2.1 → emod_api-3.2.2/emod_api.egg-info}/PKG-INFO +1 -1
  6. {emod_api-3.2.1 → emod_api-3.2.2}/pyproject.toml +2 -2
  7. {emod_api-3.2.1 → emod_api-3.2.2}/tests/test_campaign_module.py +13 -13
  8. {emod_api-3.2.1 → emod_api-3.2.2}/tests/test_node.py +6 -2
  9. emod_api-3.2.1/emod_api/__init__.py +0 -1
  10. {emod_api-3.2.1 → emod_api-3.2.2}/LICENSE +0 -0
  11. {emod_api-3.2.1 → emod_api-3.2.2}/MANIFEST.in +0 -0
  12. {emod_api-3.2.1 → emod_api-3.2.2}/README.md +0 -0
  13. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/channelreports/__init__.py +0 -0
  14. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/channelreports/channels.py +0 -0
  15. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/channelreports/plot_icj_means.py +0 -0
  16. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/channelreports/plot_prop_report.py +0 -0
  17. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/channelreports/utils.py +0 -0
  18. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/config/__init__.py +0 -0
  19. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/config/default_from_schema.py +0 -0
  20. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/config/default_from_schema_no_validation.py +0 -0
  21. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/config/from_overrides.py +0 -0
  22. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/demographics/__init__.py +0 -0
  23. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/demographics/age_distribution.py +0 -0
  24. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/demographics/base_input_file.py +0 -0
  25. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/demographics/calculators.py +0 -0
  26. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/demographics/demographic_exceptions.py +0 -0
  27. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/demographics/demographics.py +0 -0
  28. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/demographics/demographics_base.py +0 -0
  29. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/demographics/demographics_overlay.py +0 -0
  30. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/demographics/fertility_distribution.py +0 -0
  31. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/demographics/implicit_functions.py +0 -0
  32. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/demographics/mortality_distribution.py +0 -0
  33. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/demographics/overlay_node.py +0 -0
  34. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/demographics/properties_and_attributes.py +0 -0
  35. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/demographics/service/__init__.py +0 -0
  36. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/demographics/service/grid_construction.py +0 -0
  37. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/demographics/service/service.py +0 -0
  38. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/demographics/susceptibility_distribution.py +0 -0
  39. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/demographics/updateable.py +0 -0
  40. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/legacy/__init__.py +0 -0
  41. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/legacy/plotAllCharts.py +0 -0
  42. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/multidim_plotter.py +0 -0
  43. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/schema_to_class.py +0 -0
  44. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/serialization/__init__.py +0 -0
  45. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/serialization/census_and_mod_pop.py +0 -0
  46. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/serialization/dtk_file_support.py +0 -0
  47. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/serialization/dtk_file_tools.py +0 -0
  48. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/serialization/dtk_file_utility.py +0 -0
  49. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/serialization/serialized_population.py +0 -0
  50. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/spatialreports/__init__.py +0 -0
  51. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/spatialreports/__main__.py +0 -0
  52. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/spatialreports/plot_spat_means.py +0 -0
  53. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/spatialreports/spatial.py +0 -0
  54. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/utils/__init__.py +0 -0
  55. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/utils/distributions/__init__.py +0 -0
  56. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/utils/distributions/base_distribution.py +0 -0
  57. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/utils/distributions/bimodal_distribution.py +0 -0
  58. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/utils/distributions/constant_distribution.py +0 -0
  59. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/utils/distributions/demographic_distribution_flag.py +0 -0
  60. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/utils/distributions/distribution_type.py +0 -0
  61. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/utils/distributions/dual_constant_distribution.py +0 -0
  62. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/utils/distributions/dual_exponential_distribution.py +0 -0
  63. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/utils/distributions/exponential_distribution.py +0 -0
  64. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/utils/distributions/gaussian_distribution.py +0 -0
  65. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/utils/distributions/log_normal_distribution.py +0 -0
  66. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/utils/distributions/poisson_distribution.py +0 -0
  67. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/utils/distributions/uniform_distribution.py +0 -0
  68. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/utils/distributions/weibull_distribution.py +0 -0
  69. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/utils/emod_enum.py +0 -0
  70. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/utils/str_enum.py +0 -0
  71. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/weather/__init__.py +0 -0
  72. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api/weather/weather.py +0 -0
  73. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api.egg-info/SOURCES.txt +0 -0
  74. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api.egg-info/dependency_links.txt +0 -0
  75. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api.egg-info/requires.txt +0 -0
  76. {emod_api-3.2.1 → emod_api-3.2.2}/emod_api.egg-info/top_level.txt +0 -0
  77. {emod_api-3.2.1 → emod_api-3.2.2}/setup.cfg +0 -0
  78. {emod_api-3.2.1 → emod_api-3.2.2}/tests/test_channel_reports.py +0 -0
  79. {emod_api-3.2.1 → emod_api-3.2.2}/tests/test_config.py +0 -0
  80. {emod_api-3.2.1 → emod_api-3.2.2}/tests/test_config_demog.py +0 -0
  81. {emod_api-3.2.1 → emod_api-3.2.2}/tests/test_demog_from_pop.py +0 -0
  82. {emod_api-3.2.1 → emod_api-3.2.2}/tests/test_demographics.py +0 -0
  83. {emod_api-3.2.1 → emod_api-3.2.2}/tests/test_demographics_calculators.py +0 -0
  84. {emod_api-3.2.1 → emod_api-3.2.2}/tests/test_distributions.py +0 -0
  85. {emod_api-3.2.1 → emod_api-3.2.2}/tests/test_property_reports.py +0 -0
  86. {emod_api-3.2.1 → emod_api-3.2.2}/tests/test_schema.py +0 -0
  87. {emod_api-3.2.1 → emod_api-3.2.2}/tests/test_serialization.py +0 -0
  88. {emod_api-3.2.1 → emod_api-3.2.2}/tests/test_spatial_reports.py +0 -0
  89. {emod_api-3.2.1 → emod_api-3.2.2}/tests/test_weather_files.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: emod-api
3
- Version: 3.2.1
3
+ Version: 3.2.2
4
4
  Summary: Core tools for modeling using EMOD
5
5
  Author-email: Sharon Chen <sharon.chen@gatesfoundation.org>, Zhaowei Du <zhaowei.du@gatesfoundation.org>, Clark Kirkman IV <clark.kirkmand@gatesfoundation.org>, Daniel Bridenbecker <daniel.bridenbecker@gatesfoundation.org>, Svetlana Titova <svetlana.titova@gatesfoundation.org>, Ye Chen <ye.chen@gatesfoundation.org>
6
6
  License-Expression: MIT
@@ -0,0 +1 @@
1
+ __version__ = "3.2.2"
@@ -217,7 +217,7 @@ def _validate_custom_events(listened_list, broadcast_list, builtin_list, level):
217
217
  return list(broadcast)
218
218
 
219
219
 
220
- def get_custom_coordinator_events():
220
+ def validate_custom_coordinator_events():
221
221
  """Validate and return deduplicated custom coordinator-level events.
222
222
 
223
223
  Returns:
@@ -231,7 +231,7 @@ def get_custom_coordinator_events():
231
231
  return _validate_custom_events(coordinator_events_listened, coordinator_events_broadcast, coordinator_builtin_events, "coordinator")
232
232
 
233
233
 
234
- def get_custom_node_events():
234
+ def validate_custom_node_events():
235
235
  """Validate and return deduplicated custom node-level events.
236
236
 
237
237
  Returns:
@@ -245,7 +245,7 @@ def get_custom_node_events():
245
245
  return _validate_custom_events(node_events_listened, node_events_broadcast, node_builtin_events, "node")
246
246
 
247
247
 
248
- def get_custom_individual_events():
248
+ def validate_custom_individual_events():
249
249
  """Validate and return deduplicated custom individual-level events.
250
250
 
251
251
  Returns:
@@ -263,7 +263,7 @@ def get_recv_trigger(trigger, old=use_old_adhoc_handling):
263
263
  """Register an individual-level event as listened to.
264
264
 
265
265
  Tracks which individual events are used throughout the simulation
266
- so that ``get_custom_individual_events`` can validate that every
266
+ so that ``validate_custom_individual_events`` can validate that every
267
267
  listened-to event has a corresponding broadcast.
268
268
 
269
269
  Args:
@@ -283,7 +283,7 @@ def set_listened_node_event(event: str) -> str:
283
283
  """Register a node-level event as listened to.
284
284
 
285
285
  Tracks which node events are used throughout the simulation so
286
- that ``get_custom_node_events`` can validate that every listened-to
286
+ that ``validate_custom_node_events`` can validate that every listened-to
287
287
  event has a corresponding broadcast.
288
288
 
289
289
  Args:
@@ -302,7 +302,7 @@ def set_listened_coordinator_event(event: str) -> str:
302
302
  """Register a coordinator-level event as listened to.
303
303
 
304
304
  Tracks which coordinator events are used throughout the simulation
305
- so that ``get_custom_coordinator_events`` can validate that every
305
+ so that ``validate_custom_coordinator_events`` can validate that every
306
306
  listened-to event has a corresponding broadcast.
307
307
 
308
308
  Args:
@@ -337,7 +337,7 @@ def set_broadcast_node_event(event: str) -> str:
337
337
  """Register a node-level event as broadcast.
338
338
 
339
339
  Tracks which node events are used throughout the simulation so
340
- that ``get_custom_node_events`` can validate that every broadcast
340
+ that ``validate_custom_node_events`` can validate that every broadcast
341
341
  event has something listening to it.
342
342
 
343
343
  Args:
@@ -356,7 +356,7 @@ def set_broadcast_coordinator_event(event: str) -> str:
356
356
  """Register a coordinator-level event as broadcast.
357
357
 
358
358
  Tracks which coordinator events are used throughout the simulation
359
- so that ``get_custom_coordinator_events`` can validate that every
359
+ so that ``validate_custom_coordinator_events`` can validate that every
360
360
  broadcast event has something listening to it.
361
361
 
362
362
  Args:
@@ -50,6 +50,7 @@ class Node(Updateable):
50
50
  super().__init__()
51
51
  self.forced_id = forced_id
52
52
  self.meta = meta if meta else {}
53
+ # EMOD requires IndividualAttributes in every node, even if empty.
53
54
  self.individual_attributes = individual_attributes if individual_attributes else IndividualAttributes()
54
55
  self.individual_properties = individual_properties if individual_properties else IndividualProperties()
55
56
 
@@ -90,9 +91,7 @@ class Node(Updateable):
90
91
  "NodeAttributes": self.node_attributes.to_dict()}
91
92
 
92
93
  if self.individual_attributes:
93
- ia_dict = self.individual_attributes.to_dict()
94
- if ia_dict:
95
- d["IndividualAttributes"] = ia_dict
94
+ d["IndividualAttributes"] = self.individual_attributes.to_dict()
96
95
 
97
96
  if self.individual_properties:
98
97
  ip_dict = {"IndividualProperties": []}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: emod-api
3
- Version: 3.2.1
3
+ Version: 3.2.2
4
4
  Summary: Core tools for modeling using EMOD
5
5
  Author-email: Sharon Chen <sharon.chen@gatesfoundation.org>, Zhaowei Du <zhaowei.du@gatesfoundation.org>, Clark Kirkman IV <clark.kirkmand@gatesfoundation.org>, Daniel Bridenbecker <daniel.bridenbecker@gatesfoundation.org>, Svetlana Titova <svetlana.titova@gatesfoundation.org>, Ye Chen <ye.chen@gatesfoundation.org>
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "emod-api"
7
- version = "3.2.1"
7
+ version = "3.2.2"
8
8
  description = "Core tools for modeling using EMOD"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -75,7 +75,7 @@ Issues = "https://github.com/EMOD-Hub/issues-and-discussions/issues"
75
75
  find = {include = ["emod_api*"]}
76
76
 
77
77
  [tool.bumpversion]
78
- current_version = "3.2.1"
78
+ current_version = "3.2.2"
79
79
  commit = true
80
80
 
81
81
  [[tool.bumpversion.files]]
@@ -107,21 +107,21 @@ class TestCampaignWithSchema(unittest.TestCase):
107
107
  data = json.load(f)
108
108
  self.assertDictEqual(data, self.campaign.campaign_dict)
109
109
 
110
- def test_get_custom_individual_events_builtin_excluded(self):
110
+ def test_validate_custom_individual_events_builtin_excluded(self):
111
111
  if not self.campaign.individual_builtin_events:
112
112
  self.skipTest("No individual builtin events in schema")
113
113
  builtin_event = self.campaign.individual_builtin_events[0]
114
114
  self.campaign.get_recv_trigger(builtin_event)
115
- result = self.campaign.get_custom_individual_events()
115
+ result = self.campaign.validate_custom_individual_events()
116
116
  self.assertNotIn(builtin_event, result)
117
117
 
118
- def test_get_custom_individual_events_broadcast_mirrors_builtin_warns(self):
118
+ def test_validate_custom_individual_events_broadcast_mirrors_builtin_warns(self):
119
119
  if not self.campaign.individual_builtin_events:
120
120
  self.skipTest("No individual builtin events in schema")
121
121
  builtin_event = self.campaign.individual_builtin_events[0]
122
122
  self.campaign.get_send_trigger(builtin_event)
123
123
  with self.assertWarns(UserWarning):
124
- self.campaign.get_custom_individual_events()
124
+ self.campaign.validate_custom_individual_events()
125
125
 
126
126
  def test_set_schema_populates_node_builtin_events(self):
127
127
  if not self.campaign.node_builtin_events:
@@ -244,54 +244,54 @@ class TestValidateCustomEvents(unittest.TestCase):
244
244
  def test_individual_valid_pair(self):
245
245
  self.campaign.get_recv_trigger("CustomEvt")
246
246
  self.campaign.get_send_trigger("CustomEvt")
247
- result = self.campaign.get_custom_individual_events()
247
+ result = self.campaign.validate_custom_individual_events()
248
248
  self.assertIn("CustomEvt", result)
249
249
 
250
250
  def test_individual_listened_not_broadcast_raises(self):
251
251
  self.campaign.get_recv_trigger("OrphanedEvt")
252
252
  with self.assertRaises(ValueError):
253
- self.campaign.get_custom_individual_events()
253
+ self.campaign.validate_custom_individual_events()
254
254
 
255
255
  def test_individual_broadcast_not_listened_warns(self):
256
256
  self.campaign.get_send_trigger("UnlistenedEvt")
257
257
  with self.assertWarns(UserWarning):
258
- self.campaign.get_custom_individual_events()
258
+ self.campaign.validate_custom_individual_events()
259
259
 
260
260
  # --- node ---
261
261
 
262
262
  def test_node_valid_pair(self):
263
263
  self.campaign.set_listened_node_event("NodeEvt")
264
264
  self.campaign.set_broadcast_node_event("NodeEvt")
265
- result = self.campaign.get_custom_node_events()
265
+ result = self.campaign.validate_custom_node_events()
266
266
  self.assertIn("NodeEvt", result)
267
267
 
268
268
  def test_node_listened_not_broadcast_raises(self):
269
269
  self.campaign.set_listened_node_event("OrphanedNodeEvt")
270
270
  with self.assertRaises(ValueError):
271
- self.campaign.get_custom_node_events()
271
+ self.campaign.validate_custom_node_events()
272
272
 
273
273
  def test_node_broadcast_not_listened_warns(self):
274
274
  self.campaign.set_broadcast_node_event("UnlistenedNodeEvt")
275
275
  with self.assertWarns(UserWarning):
276
- self.campaign.get_custom_node_events()
276
+ self.campaign.validate_custom_node_events()
277
277
 
278
278
  # --- coordinator ---
279
279
 
280
280
  def test_coordinator_valid_pair(self):
281
281
  self.campaign.set_listened_coordinator_event("CoordEvt")
282
282
  self.campaign.set_broadcast_coordinator_event("CoordEvt")
283
- result = self.campaign.get_custom_coordinator_events()
283
+ result = self.campaign.validate_custom_coordinator_events()
284
284
  self.assertIn("CoordEvt", result)
285
285
 
286
286
  def test_coordinator_listened_not_broadcast_raises(self):
287
287
  self.campaign.set_listened_coordinator_event("OrphanedCoordEvt")
288
288
  with self.assertRaises(ValueError):
289
- self.campaign.get_custom_coordinator_events()
289
+ self.campaign.validate_custom_coordinator_events()
290
290
 
291
291
  def test_coordinator_broadcast_not_listened_warns(self):
292
292
  self.campaign.set_broadcast_coordinator_event("UnlistenedCoordEvt")
293
293
  with self.assertWarns(UserWarning):
294
- self.campaign.get_custom_coordinator_events()
294
+ self.campaign.validate_custom_coordinator_events()
295
295
 
296
296
  # --- builtin filtering ---
297
297
 
@@ -93,7 +93,9 @@ class NodeTest(unittest.TestCase):
93
93
  node = Node(lat=0,lon=0,pop=100, individual_attributes=individual_attributes_1)
94
94
  self.assertEqual(node.to_dict()["IndividualAttributes"]["user_defined_2"], 2)
95
95
  node = Node(lat=0,lon=0,pop=100, individual_attributes=individual_attributes_2)
96
- self.assertNotIn("IndividualAttributes", node.to_dict())
96
+ # EMOD requires IndividualAttributes in every node, even if empty
97
+ self.assertIn("IndividualAttributes", node.to_dict())
98
+ self.assertNotIn("user_defined_2", node.to_dict()["IndividualAttributes"])
97
99
 
98
100
  ips = [IndividualProperty(property='cloudy', values=["yes", "no"], initial_distribution=[0.5, 0.5])]
99
101
  individual_properties_1 = IndividualProperties(ips)
@@ -118,7 +120,9 @@ class NodeTest(unittest.TestCase):
118
120
  node_3 = Node(lat=1, lon=2, pop=100, node_attributes=node_attributes, individual_attributes=individual_attributes)
119
121
 
120
122
  self.assertEqual(node_1.to_dict()["NodeAttributes"]["Test_1"], 1)
121
- self.assertTrue("IndividualAttributes" not in node_1.to_dict())
123
+ # EMOD requires IndividualAttributes in every node, even if empty
124
+ self.assertIn("IndividualAttributes", node_1.to_dict())
125
+ self.assertNotIn("Test_2", node_1.to_dict()["IndividualAttributes"])
122
126
 
123
127
  self.assertTrue("Test_1" not in node_2.to_dict()["NodeAttributes"])
124
128
  self.assertEqual(node_2.to_dict()["IndividualAttributes"]["Test_2"], 2)
@@ -1 +0,0 @@
1
- __version__ = "3.2.1"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes