Iterates though a list of seasons e.g. ["DJF", "FMA", ...], and splits that into multiple sequences of non-overlapping seasons. >>> find_independent_seasons( ... ["DJF", "FMA", "AMJ", "JJA", "ASO", "OND"] ... ) # doctest: +NORMALIZE_WHITESPACE [SeasonsGroup(seasons=('D
(seasons: Sequence[str])
| 756 | |
| 757 | |
| 758 | def find_independent_seasons(seasons: Sequence[str]) -> Sequence[SeasonsGroup]: |
| 759 | """ |
| 760 | Iterates though a list of seasons e.g. ["DJF", "FMA", ...], |
| 761 | and splits that into multiple sequences of non-overlapping seasons. |
| 762 | |
| 763 | >>> find_independent_seasons( |
| 764 | ... ["DJF", "FMA", "AMJ", "JJA", "ASO", "OND"] |
| 765 | ... ) # doctest: +NORMALIZE_WHITESPACE |
| 766 | [SeasonsGroup(seasons=('DJF', 'AMJ', 'ASO'), inds=((12, 1, 2), (4, 5, 6), (8, 9, 10)), codes=[0, 2, 4]), SeasonsGroup(seasons=('FMA', 'JJA', 'OND'), inds=((2, 3, 4), (6, 7, 8), (10, 11, 12)), codes=[1, 3, 5])] |
| 767 | |
| 768 | >>> find_independent_seasons(["DJF", "MAM", "JJA", "SON"]) |
| 769 | [SeasonsGroup(seasons=('DJF', 'MAM', 'JJA', 'SON'), inds=((12, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11)), codes=[0, 1, 2, 3])] |
| 770 | """ |
| 771 | season_inds = season_to_month_tuple(seasons) |
| 772 | grouped = defaultdict(list) |
| 773 | codes = defaultdict(list) |
| 774 | seen: set[tuple[int, ...]] = set() |
| 775 | # This is quadratic, but the number of seasons is at most 12 |
| 776 | for i, current in enumerate(season_inds): |
| 777 | # Start with a group |
| 778 | if current not in seen: |
| 779 | grouped[i].append(current) |
| 780 | codes[i].append(i) |
| 781 | seen.add(current) |
| 782 | |
| 783 | # Loop through remaining groups, and look for overlaps |
| 784 | for j, second in enumerate(season_inds[i:]): |
| 785 | if not (set(chain(*grouped[i])) & set(second)) and second not in seen: |
| 786 | grouped[i].append(second) |
| 787 | codes[i].append(j + i) |
| 788 | seen.add(second) |
| 789 | if len(seen) == len(seasons): |
| 790 | break |
| 791 | # found all non-overlapping groups for this row start over |
| 792 | |
| 793 | grouped_ints = tuple(tuple(idx) for idx in grouped.values() if idx) |
| 794 | return [ |
| 795 | SeasonsGroup(seasons=inds_to_season_string(inds), inds=inds, codes=codes) |
| 796 | for inds, codes in zip(grouped_ints, codes.values(), strict=False) |
| 797 | ] |
| 798 | |
| 799 | |
| 800 | @dataclass |
searching dependent graphs…