Created
July 7, 2023 12:09
-
-
Save MyKo101/d94ec9ceb2394d26423db1c0081760ad to your computer and use it in GitHub Desktop.
Multi-Modality Testing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import itertools | |
| from dataclasses import dataclass | |
| from typing import Tuple | |
| import numpy as np | |
| from diptest import diptest | |
| MEAN = 18.75 | |
| STDDEV = 5.647 | |
| @dataclass | |
| class Pair: | |
| """ | |
| Data shown represent one of two values. Since we cannot tell | |
| which of the two values the frequency is associated with, | |
| we need to be able to check all combinations of both values. | |
| """ | |
| start: int | |
| freq: int | |
| def __iter__(self): | |
| """ | |
| Begin an iteration | |
| """ | |
| self.count = 0 | |
| return self | |
| def __next__(self): | |
| """ | |
| Returns a list of length `freq`, returning | |
| all combinations of the two possible values. | |
| For example, Pair(1,2) would return [1,1], then [1,2] and then [2,2] | |
| """ | |
| n = self.count | |
| m = self.freq - self.count | |
| if m < 0: | |
| raise StopIteration | |
| self.count += 1 | |
| a = [self.start] | |
| b = [self.start+1] | |
| return a*m + b*n | |
| @dataclass | |
| class Data: | |
| """ | |
| A way to represent the data (just a tuple of ints) | |
| """ | |
| ls: Tuple[int] | |
| def mean(self, sf: int): | |
| """ | |
| Returns the mean to the appropriate number of significant figures | |
| """ | |
| return float(round(np.mean(self.ls), sf)) | |
| def std(self, sf: int): | |
| """ | |
| Returns the standard deviation to the appropriate number of significant figures | |
| """ | |
| return float(round(np.std(self.ls), sf)) | |
| def matches(self, mean=MEAN, std=STDDEV): | |
| """ | |
| Test if the data matches the mean & std given | |
| """ | |
| return self.mean(2) == mean and self.std(3) == std | |
| def test(self): | |
| """ | |
| Test if the data is multi-modal or not | |
| """ | |
| dp = diptest(np.array(self.ls)) | |
| return {"stat": dp[0], "p": dp[1]} | |
| @dataclass | |
| class PairList: | |
| ls: Tuple[Pair] | |
| def __init__(self, *args): | |
| self.ls = tuple(args) | |
| def __iter__(self): | |
| self.iters = itertools.product(*self.ls) | |
| return self | |
| def __next__(self) -> Data: | |
| return Data(tuple(y for x in next(self.iters) for y in x)) | |
| # Data taken from the plot | |
| datapairs = PairList( | |
| Pair(1, 1), | |
| Pair(3, 2), | |
| Pair(5, 1), | |
| Pair(15, 3), | |
| Pair(17, 5), | |
| Pair(19, 12), | |
| Pair(21, 9), | |
| Pair(23, 5), | |
| Pair(25, 2) | |
| ) | |
| sig = 0 | |
| nsig = 0 | |
| for gen_data in datapairs: | |
| if gen_data.matches(): | |
| dp = gen_data.test() | |
| if dp["p"] < 0.05: | |
| sig += 1 | |
| else: | |
| nsig += 1 | |
| print(f"{sig = } <=> {nsig=}. Prop: {sig/(sig+nsig)}") |
Author
MyKo101
commented
Jul 7, 2023

Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment