Skip to content

Commit

Permalink
Merge pull request #167 from popsim-consortium/proportions_equal_to_zero
Browse files Browse the repository at this point in the history
Add (invalid) test cases of proportions == 0.0
  • Loading branch information
grahamgower authored Nov 19, 2024
2 parents 89a054a + da7d32f commit 0f5fa52
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 15 deletions.
34 changes: 19 additions & 15 deletions reference_implementation/demes_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,16 +73,16 @@ def parse(data: dict) -> Graph:
description=(str, None),
start_time=((str, numbers.Number), is_positive_or_json_infinity),
ancestors=(list, is_list_of_identifiers),
proportions=(list, is_list_of_fractions),
proportions=(list, is_list_of_proportions),
),
)

allowed_epoch_defaults = dict(
end_time=(numbers.Number, is_non_negative_and_finite),
start_size=(numbers.Number, is_positive_and_finite),
end_size=(numbers.Number, is_positive_and_finite),
selfing_rate=(numbers.Number, is_fraction),
cloning_rate=(numbers.Number, is_fraction),
selfing_rate=(numbers.Number, is_rate),
cloning_rate=(numbers.Number, is_rate),
size_function=(str, None),
)
check_defaults(global_epoch_defaults, allowed_epoch_defaults)
Expand All @@ -101,7 +101,7 @@ def parse(data: dict) -> Graph:
),
ancestors=pop_list(deme_data, "ancestors", [], str, is_identifier),
proportions=pop_list(
deme_data, "proportions", None, numbers.Number, is_fraction
deme_data, "proportions", None, numbers.Number, is_proportion
),
)

Expand All @@ -126,8 +126,8 @@ def parse(data: dict) -> Graph:
end_size=pop_number(
epoch_data, "end_size", None, is_positive_and_finite
),
selfing_rate=pop_number(epoch_data, "selfing_rate", 0, is_fraction),
cloning_rate=pop_number(epoch_data, "cloning_rate", 0, is_fraction),
selfing_rate=pop_number(epoch_data, "selfing_rate", 0, is_rate),
cloning_rate=pop_number(epoch_data, "cloning_rate", 0, is_rate),
size_function=pop_string(epoch_data, "size_function", None),
)
check_empty(epoch_data)
Expand All @@ -142,7 +142,7 @@ def parse(data: dict) -> Graph:
check_defaults(
migration_defaults,
dict(
rate=(numbers.Number, is_fraction),
rate=(numbers.Number, is_rate),
start_time=((numbers.Number, str), is_positive_or_json_infinity),
end_time=(numbers.Number, is_non_negative_and_finite),
source=(str, is_identifier),
Expand All @@ -153,7 +153,7 @@ def parse(data: dict) -> Graph:
for migration_data in pop_list(data, "migrations", []):
insert_defaults(migration_data, migration_defaults)
graph.add_migration(
rate=pop_number(migration_data, "rate", validator=is_fraction),
rate=pop_number(migration_data, "rate", validator=is_rate),
start_time=pop_number(
migration_data,
"start_time",
Expand Down Expand Up @@ -182,7 +182,7 @@ def parse(data: dict) -> Graph:
sources=(list, is_nonempty_list_of_identifiers),
dest=(str, is_identifier),
time=(numbers.Number, is_positive_and_finite),
proportions=(list, is_nonempty_list_of_fractions_with_sum_less_than_1),
proportions=(list, is_nonempty_list_of_proportions_with_sum_less_than_1),
),
)
for pulse_data in pop_list(data, "pulses", []):
Expand All @@ -202,7 +202,7 @@ def parse(data: dict) -> Graph:
"proportions",
default=[],
required_type=numbers.Number,
validator=is_fraction,
validator=is_proportion,
),
)
check_empty(pulse_data)
Expand Down Expand Up @@ -246,10 +246,14 @@ def is_non_negative_and_finite(value):
return value >= 0 and not math.isinf(value)


def is_fraction(value):
def is_rate(value):
return 0 <= value <= 1


def is_proportion(value):
return 0 < value <= 1


def is_nonempty(value):
return len(value) > 0

Expand All @@ -266,12 +270,12 @@ def is_nonempty_list_of_identifiers(value):
return is_list_of_identifiers(value) and len(value) > 0


def is_list_of_fractions(value):
return all(isinstance(v, numbers.Number) and is_fraction(v) for v in value)
def is_list_of_proportions(value):
return all(isinstance(v, numbers.Number) and is_proportion(v) for v in value)


def is_nonempty_list_of_fractions_with_sum_less_than_1(value):
return is_list_of_fractions(value) and len(value) > 0 and sum(value) <= 1
def is_nonempty_list_of_proportions_with_sum_less_than_1(value):
return is_list_of_proportions(value) and len(value) > 0 and sum(value) <= 1


def validate_item(name, value, required_type, validator=None):
Expand Down
14 changes: 14 additions & 0 deletions test-cases/invalid/bad_ancestry_proportions_11.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
time_units: generations
demes:
- name: a
epochs:
- {start_size: 100, end_time: 50}
- name: b
epochs:
- {start_size: 100, end_time: 50}
- name: c
ancestors: [a, b]
proportions: [0.0, 1.0]
start_time: 100
epochs:
- {start_size: 100}
16 changes: 16 additions & 0 deletions test-cases/invalid/bad_pulse_proportion_09.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
time_units: generations
demes:
- name: A
epochs:
- start_size: 1000
- name: B
epochs:
- start_size: 1000
- name: C
epochs:
- start_size: 1000
pulses:
- sources: [A]
dest: C
proportions: [0.]
time: 10
13 changes: 13 additions & 0 deletions test-cases/invalid/bad_pulse_proportions_list_03.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
time_units: generations
demes:
- name: a
epochs:
- {start_size: 1}
- name: b
epochs:
- {start_size: 1}
- name: c
epochs:
- {start_size: 1}
pulses:
- {sources: [a, b], dest: c, proportions: [0.1, 0.0], time: 100}
8 changes: 8 additions & 0 deletions test-cases/invalid/bad_toplevel_defaults_deme_20.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
time_units: generations
defaults:
deme: {proportions: [0.0]}
demes:
- name: a
proportions: []
epochs:
- start_size: 1
8 changes: 8 additions & 0 deletions test-cases/invalid/bad_toplevel_defaults_deme_21.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
time_units: generations
defaults:
deme: {proportions: [0.1, 0.0]}
demes:
- name: a
proportions: []
epochs:
- start_size: 1
7 changes: 7 additions & 0 deletions test-cases/invalid/bad_toplevel_defaults_pulse_23.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
time_units: generations
defaults:
pulse: {proportions: [0.0]}
demes:
- name: a
epochs:
- start_size: 1
7 changes: 7 additions & 0 deletions test-cases/invalid/bad_toplevel_defaults_pulse_24.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
time_units: generations
defaults:
pulse: {proportions: [1.0, 0.0]}
demes:
- name: a
epochs:
- start_size: 1

0 comments on commit 0f5fa52

Please sign in to comment.