pySEQTarget 0.10.0__py3-none-any.whl

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 (46) hide show
  1. pySEQTarget/SEQopts.py +197 -0
  2. pySEQTarget/SEQoutput.py +163 -0
  3. pySEQTarget/SEQuential.py +375 -0
  4. pySEQTarget/__init__.py +5 -0
  5. pySEQTarget/analysis/__init__.py +8 -0
  6. pySEQTarget/analysis/_hazard.py +211 -0
  7. pySEQTarget/analysis/_outcome_fit.py +75 -0
  8. pySEQTarget/analysis/_risk_estimates.py +136 -0
  9. pySEQTarget/analysis/_subgroup_fit.py +30 -0
  10. pySEQTarget/analysis/_survival_pred.py +372 -0
  11. pySEQTarget/data/__init__.py +19 -0
  12. pySEQTarget/error/__init__.py +2 -0
  13. pySEQTarget/error/_datachecker.py +38 -0
  14. pySEQTarget/error/_param_checker.py +50 -0
  15. pySEQTarget/expansion/__init__.py +5 -0
  16. pySEQTarget/expansion/_binder.py +98 -0
  17. pySEQTarget/expansion/_diagnostics.py +53 -0
  18. pySEQTarget/expansion/_dynamic.py +73 -0
  19. pySEQTarget/expansion/_mapper.py +44 -0
  20. pySEQTarget/expansion/_selection.py +31 -0
  21. pySEQTarget/helpers/__init__.py +8 -0
  22. pySEQTarget/helpers/_bootstrap.py +111 -0
  23. pySEQTarget/helpers/_col_string.py +6 -0
  24. pySEQTarget/helpers/_format_time.py +6 -0
  25. pySEQTarget/helpers/_output_files.py +167 -0
  26. pySEQTarget/helpers/_pad.py +7 -0
  27. pySEQTarget/helpers/_predict_model.py +9 -0
  28. pySEQTarget/helpers/_prepare_data.py +19 -0
  29. pySEQTarget/initialization/__init__.py +5 -0
  30. pySEQTarget/initialization/_censoring.py +53 -0
  31. pySEQTarget/initialization/_denominator.py +39 -0
  32. pySEQTarget/initialization/_numerator.py +37 -0
  33. pySEQTarget/initialization/_outcome.py +56 -0
  34. pySEQTarget/plot/__init__.py +1 -0
  35. pySEQTarget/plot/_survival_plot.py +104 -0
  36. pySEQTarget/weighting/__init__.py +8 -0
  37. pySEQTarget/weighting/_weight_bind.py +86 -0
  38. pySEQTarget/weighting/_weight_data.py +47 -0
  39. pySEQTarget/weighting/_weight_fit.py +99 -0
  40. pySEQTarget/weighting/_weight_pred.py +192 -0
  41. pySEQTarget/weighting/_weight_stats.py +23 -0
  42. pyseqtarget-0.10.0.dist-info/METADATA +98 -0
  43. pyseqtarget-0.10.0.dist-info/RECORD +46 -0
  44. pyseqtarget-0.10.0.dist-info/WHEEL +5 -0
  45. pyseqtarget-0.10.0.dist-info/licenses/LICENSE +21 -0
  46. pyseqtarget-0.10.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,192 @@
1
+ import numpy as np
2
+ import polars as pl
3
+
4
+ from ..helpers import _predict_model
5
+
6
+
7
+ def _weight_predict(self, WDT):
8
+ grouping = [self.id_col]
9
+ grouping += ["trial"] if not self.weight_preexpansion else []
10
+ time = self.time_col if self.weight_preexpansion else "followup"
11
+
12
+ if self.method == "ITT":
13
+ WDT = WDT.with_columns(
14
+ [pl.lit(1.0).alias("numerator"), pl.lit(1.0).alias("denominator")]
15
+ )
16
+ else:
17
+ WDT = WDT.with_columns(
18
+ [pl.lit(1.0).alias("numerator"), pl.lit(1.0).alias("denominator")]
19
+ )
20
+
21
+ if not self.excused:
22
+ for i, level in enumerate(self.treatment_level):
23
+ mask = pl.col("tx_lag") == level
24
+ lag_mask = (WDT["tx_lag"] == level).to_numpy()
25
+
26
+ if self.denominator_model[i] is not None:
27
+ pred_denom = np.ones(WDT.height)
28
+ if lag_mask.sum() > 0:
29
+ subset = WDT.filter(pl.Series(lag_mask))
30
+ p = _predict_model(self, self.denominator_model[i], subset)
31
+ if p.ndim == 1:
32
+ p = p.reshape(-1, 1)
33
+ p = p[:, i]
34
+ switched_treatment = (
35
+ subset[self.treatment_col] != subset["tx_lag"]
36
+ ).to_numpy()
37
+ pred_denom[lag_mask] = np.where(switched_treatment, 1.0 - p, p)
38
+ else:
39
+ pred_denom = np.ones(WDT.height)
40
+
41
+ if self.numerator_model[i] is not None:
42
+ pred_num = np.ones(WDT.height)
43
+ if lag_mask.sum() > 0:
44
+ subset = WDT.filter(pl.Series(lag_mask))
45
+ p = _predict_model(self, self.numerator_model[i], subset)
46
+ if p.ndim == 1:
47
+ p = p.reshape(-1, 1)
48
+ p = p[:, i]
49
+ switched_treatment = (
50
+ subset[self.treatment_col] != subset["tx_lag"]
51
+ ).to_numpy()
52
+ pred_num[lag_mask] = np.where(switched_treatment, 1.0 - p, p)
53
+ else:
54
+ pred_num = np.ones(WDT.height)
55
+
56
+ WDT = WDT.with_columns(
57
+ [
58
+ pl.when(mask)
59
+ .then(pl.Series(pred_num))
60
+ .otherwise(pl.col("numerator"))
61
+ .alias("numerator"),
62
+ pl.when(mask)
63
+ .then(pl.Series(pred_denom))
64
+ .otherwise(pl.col("denominator"))
65
+ .alias("denominator"),
66
+ ]
67
+ )
68
+
69
+ else:
70
+ for i, level in enumerate(self.treatment_level):
71
+ col = self.excused_colnames[i]
72
+
73
+ if col is not None:
74
+ denom_mask = ((WDT["tx_lag"] == level) & (WDT[col] != 1)).to_numpy()
75
+
76
+ if self.denominator_model[i] is not None and denom_mask.sum() > 0:
77
+ pred_denom = np.ones(WDT.height)
78
+ subset = WDT.filter(pl.Series(denom_mask))
79
+ p = _predict_model(self, self.denominator_model[i], subset)
80
+
81
+ if p.ndim == 1:
82
+ prob_switch = p
83
+ else:
84
+ prob_switch = p[:, 1] if p.shape[1] > 1 else p.flatten()
85
+
86
+ pred_denom[denom_mask] = prob_switch
87
+
88
+ WDT = WDT.with_columns(
89
+ pl.when(pl.Series(denom_mask))
90
+ .then(pl.Series(pred_denom))
91
+ .otherwise(pl.col("denominator"))
92
+ .alias("denominator")
93
+ )
94
+
95
+ if i == 0:
96
+ flip_mask = (
97
+ (WDT["tx_lag"] == level)
98
+ & (WDT[col] == 0)
99
+ & (WDT[self.treatment_col] == level)
100
+ ).to_numpy()
101
+ else:
102
+ flip_mask = (
103
+ (WDT["tx_lag"] == level)
104
+ & (WDT[col] == 0)
105
+ & (WDT[self.treatment_col] != level)
106
+ ).to_numpy()
107
+
108
+ WDT = WDT.with_columns(
109
+ pl.when(pl.Series(flip_mask))
110
+ .then(1.0 - pl.col("denominator"))
111
+ .otherwise(pl.col("denominator"))
112
+ .alias("denominator")
113
+ )
114
+
115
+ if self.weight_preexpansion:
116
+ WDT = WDT.with_columns(pl.lit(1.0).alias("numerator"))
117
+ else:
118
+ for i, level in enumerate(self.treatment_level):
119
+ col = self.excused_colnames[i]
120
+
121
+ if col is not None:
122
+ num_mask = (
123
+ (WDT[self.treatment_col] == level) & (WDT[col] == 0)
124
+ ).to_numpy()
125
+
126
+ if self.numerator_model[i] is not None and num_mask.sum() > 0:
127
+ pred_num = np.ones(WDT.height)
128
+ subset = WDT.filter(pl.Series(num_mask))
129
+ p = _predict_model(self, self.numerator_model[i], subset)
130
+
131
+ if p.ndim == 1:
132
+ prob_switch = p
133
+ else:
134
+ prob_switch = p[:, 1] if p.shape[1] > 1 else p.flatten()
135
+
136
+ pred_num[num_mask] = prob_switch
137
+
138
+ WDT = WDT.with_columns(
139
+ pl.when(pl.Series(num_mask))
140
+ .then(pl.Series(pred_num))
141
+ .otherwise(pl.col("numerator"))
142
+ .alias("numerator")
143
+ )
144
+
145
+ first_level = self.treatment_level[0]
146
+ WDT = WDT.with_columns(
147
+ pl.when(pl.col(self.treatment_col) == first_level)
148
+ .then(1.0 - pl.col("numerator"))
149
+ .otherwise(pl.col("numerator"))
150
+ .alias("numerator")
151
+ )
152
+ if self.cense_colname is not None:
153
+ p_num = _predict_model(self, self.cense_numerator, WDT).flatten()
154
+ p_denom = _predict_model(self, self.cense_denominator, WDT).flatten()
155
+ WDT = WDT.with_columns(
156
+ [
157
+ pl.Series("cense_numerator", p_num),
158
+ pl.Series("cense_denominator", p_denom),
159
+ ]
160
+ ).with_columns(
161
+ (pl.col("cense_numerator") / pl.col("cense_denominator")).alias("_cense")
162
+ )
163
+ else:
164
+ WDT = WDT.with_columns(pl.lit(1.0).alias("_cense"))
165
+
166
+ if self.visit_colname is not None:
167
+ p_num = _predict_model(self, self.visit_numerator, WDT).flatten()
168
+ p_denom = _predict_model(self, self.visit_denominator, WDT).flatten()
169
+
170
+ WDT = WDT.with_columns(
171
+ [
172
+ pl.Series("visit_numerator", p_num),
173
+ pl.Series("visit_denominator", p_denom),
174
+ ]
175
+ ).with_columns(
176
+ (pl.col("visit_numerator") / pl.col("visit_denominator")).alias("_visit")
177
+ )
178
+ else:
179
+ WDT = WDT.with_columns(pl.lit(1.0).alias("_visit"))
180
+
181
+ kept = [
182
+ "numerator",
183
+ "denominator",
184
+ "_cense",
185
+ "_visit",
186
+ self.id_col,
187
+ "trial",
188
+ time,
189
+ "tx_lag",
190
+ ]
191
+ exists = [col for col in kept if col in WDT.columns]
192
+ return WDT.select(exists).sort(grouping + [time])
@@ -0,0 +1,23 @@
1
+ import polars as pl
2
+
3
+
4
+ def _weight_stats(self):
5
+ stats = self.DT.select(
6
+ [
7
+ pl.col("weight").min().alias("weight_min"),
8
+ pl.col("weight").max().alias("weight_max"),
9
+ pl.col("weight").mean().alias("weight_mean"),
10
+ pl.col("weight").std().alias("weight_std"),
11
+ pl.col("weight").quantile(0.01).alias("weight_p01"),
12
+ pl.col("weight").quantile(0.25).alias("weight_p25"),
13
+ pl.col("weight").quantile(0.50).alias("weight_p50"),
14
+ pl.col("weight").quantile(0.75).alias("weight_p75"),
15
+ pl.col("weight").quantile(0.99).alias("weight_p99"),
16
+ ]
17
+ )
18
+
19
+ if self.weight_p99:
20
+ self.weight_min = stats.select("weight_p01").item()
21
+ self.weight_max = stats.select("weight_p99").item()
22
+
23
+ return stats
@@ -0,0 +1,98 @@
1
+ Metadata-Version: 2.4
2
+ Name: pySEQTarget
3
+ Version: 0.10.0
4
+ Summary: Sequentially Nested Target Trial Emulation
5
+ Author-email: Ryan O'Dea <ryan.odea@psi.ch>, Alejandro Szmulewicz <aszmulewicz@hsph.harvard.edu>, Tom Palmer <tom.palmer@bristol.ac.uk>, Miguel Hernan <mhernan@hsph.harvard.edu>
6
+ Maintainer-email: Ryan O'Dea <ryan.odea@psi.ch>
7
+ License: MIT
8
+ Project-URL: Homepage, https://github.com/CausalInference/pySEQTarget
9
+ Project-URL: Repository, https://github.com/CausalInference/pySEQTarget
10
+ Project-URL: Bug Tracker, https://github.com/CausalInference/pySEQTarget/issues
11
+ Project-URL: Ryan O'Dea (ORCID), https://orcid.org/0009-0000-0103-9546
12
+ Project-URL: Alejandro Szmulewicz (ORCID), https://orcid.org/0000-0002-2664-802X
13
+ Project-URL: Tom Palmer (ORCID), https://orcid.org/0000-0003-4655-4511
14
+ Project-URL: Miguel Hernan (ORCID), https://orcid.org/0000-0003-1619-8456
15
+ Project-URL: University of Bristol (ROR), https://ror.org/0524sp257
16
+ Project-URL: Harvard University (ROR), https://ror.org/03vek6s52
17
+ Keywords: causal inference,sequential trial emulation,target trial,observational studies
18
+ Classifier: Development Status :: 4 - Beta
19
+ Classifier: Intended Audience :: Science/Research
20
+ Classifier: Programming Language :: Python :: 3
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Programming Language :: Python :: 3.14
26
+ Requires-Python: >=3.10
27
+ Description-Content-Type: text/markdown
28
+ License-File: LICENSE
29
+ Requires-Dist: numpy
30
+ Requires-Dist: polars
31
+ Requires-Dist: tqdm
32
+ Requires-Dist: statsmodels
33
+ Requires-Dist: matplotlib
34
+ Requires-Dist: pyarrow
35
+ Requires-Dist: lifelines
36
+ Dynamic: license-file
37
+
38
+ # pySEQTarget - Sequentially Nested Target Trial Emulation
39
+ [![PyPI version](https://badge.fury.io/py/pySEQTarget.svg)](https://pypi.org/project/pySEQTarget)
40
+ [![Downloads](https://static.pepy.tech/badge/pySEQTarget)](https://pepy.tech/project/pySEQTarget)
41
+ [![codecov](https://codecov.io/gh/CausalInference/pySEQTarget/graph/badge.svg?token=DMOVJJUWXP)](https://codecov.io/gh/CausalInference/pySEQTarget)[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
42
+ ![versions](https://img.shields.io/pypi/pyversions/pySEQTarget.svg)
43
+ [![Documentation Status](https://readthedocs.org/projects/pySEQTarget/badge/?version=latest)](https://pySEQTarget.readthedocs.io)
44
+
45
+ Implementation of sequential trial emulation for the analysis of
46
+ observational databases. The `SEQTaRget` software accommodates
47
+ time-varying treatments and confounders, as well as binary and failure
48
+ time outcomes. `SEQTaRget` allows to compare both static and dynamic
49
+ strategies, can be used to estimate observational analogs of
50
+ intention-to-treat and per-protocol effects, and can adjust for
51
+ potential selection bias.
52
+
53
+ ## Installation
54
+ You can install the development version of pySEQTarget from github with:
55
+ ```shell
56
+ pip install git+https://github.com/CausalInference/pySEQTarget
57
+ ```
58
+ Or from pypi iwth
59
+ ```shell
60
+ pip install pySEQTarget
61
+ ```
62
+
63
+ ## Setting up your Analysis
64
+ The primary API, `SEQuential` uses a dataclass system to handle function input. You can then recover elements as they are built by interacting with the `SEQuential` object you create.
65
+
66
+ From the user side, this amounts to creating a dataclass, `SEQopts`, and then feeding this into `SEQuential`. If you forgot to add something at class instantiation, you can, in some cases, add them when you call their respective class method.
67
+
68
+ ```python
69
+ import polars as pl
70
+ from pySEQTarget import SEQuential, SEQopts
71
+
72
+ data = pl.from_pandas(SEQdata)
73
+ options = SEQopts(km_curves = True)
74
+
75
+ # Initiate the class
76
+ model = SEQuential(data,
77
+ id_col = "ID",
78
+ time_col = "time",
79
+ eligible_col = "eligible",
80
+ time_varying_cols = ["N", "L", "P"],
81
+ fixed_cols = ["sex"],
82
+ method = "ITT",
83
+ options = options)
84
+ model.expand() # Construct the nested structure
85
+ model.bootstrap(bootstrap_nboot = 20) # Run 20 bootstrap samples
86
+ model.fit() # Fit the model
87
+ model.survival() # Create survival curves
88
+ model.plot() # Create and show a plot of the survival curves
89
+ model.collect() # Collection of important information
90
+
91
+ ```
92
+
93
+ ## Assumptions
94
+ There are several key assumptions in this package -
95
+ 1. User provided `time_col` begins at 0 per unique `id_col`, we also assume this column contains only integers and continues by 1 for every time step, e.g. (0, 1, 2, 3, 4, ...) is allowed and (0, 1, 2, 2.5, ...) or (0, 1, 4, 5) are not
96
+ 1. Provided `time_col` entries may be out of order at intake as a sort is enforced at expansion.
97
+ 2. `eligible_col` and elements of `excused_colnames` are once 1, only 1 (with respect to `time_col`) flag variables.
98
+
@@ -0,0 +1,46 @@
1
+ pySEQTarget/SEQopts.py,sha256=7AWqwJyQs5I3CkwchpyNwq3oRiQMhOM34l9EnlxZ3L4,8910
2
+ pySEQTarget/SEQoutput.py,sha256=NRXcX6TzuJjiix_I2_PwG18zn83U8cjc3Ihf-UXe-R8,6354
3
+ pySEQTarget/SEQuential.py,sha256=IQ3SpoylyMV28GQCA8cZEhqVZ52MeP6pskpwLadnd2w,12869
4
+ pySEQTarget/__init__.py,sha256=X3BKStCan0QmgpfJqN5ffBKZSDjw6s497N2b2AR3Ilg,147
5
+ pySEQTarget/analysis/__init__.py,sha256=3XOPVKVWeRoCHtuHAIqNOAcGgWmBzXpU2C7_p47xXqo,448
6
+ pySEQTarget/analysis/_hazard.py,sha256=lgluCVm6EpAcGzySRybXlsPrwhgHXW1zwxq47JVdvrg,6795
7
+ pySEQTarget/analysis/_outcome_fit.py,sha256=VR7wF4n0EKIVrm8H2e-PG1-N-Xsu8aJO_VNU8o2O4KI,2199
8
+ pySEQTarget/analysis/_risk_estimates.py,sha256=p40bSvN2wMOpCVq4Rv3ak6ZZVpobaI4zzjjeBKoQvCA,5300
9
+ pySEQTarget/analysis/_subgroup_fit.py,sha256=jeL1LBTtHiSpfiu7-w4LjVWlka8XMPVABGsvV9AFG60,829
10
+ pySEQTarget/analysis/_survival_pred.py,sha256=m_xbbz9awa3WZgaQt2-h4C3kAQLFL3aRB4U69TlsDcw,13993
11
+ pySEQTarget/data/__init__.py,sha256=2q_f_M9LW1R5iO4CaBtoC0y-wwMsFGSd54mHfJDsvJo,682
12
+ pySEQTarget/error/__init__.py,sha256=iC-55PhWIOymSHndMR-1buKE7sOApHw6Zb7W75T1Si0,116
13
+ pySEQTarget/error/_datachecker.py,sha256=h7LDXlA-6OBcpqlF7kymnKQoZ58yLRx9q2461EFcIdQ,1231
14
+ pySEQTarget/error/_param_checker.py,sha256=1d4k75b3qZUveq0S6DvaoGf6dYAKQHOc3q_KRoBie6I,1654
15
+ pySEQTarget/expansion/__init__.py,sha256=Qy-m2NB8AnGX4GOrr9n20GxOCPxf-KaMARjxyFL73yg,241
16
+ pySEQTarget/expansion/_binder.py,sha256=sa6UIcxgBl1uMIOBh-OnxYOMnEzNoceP1GVDiiYU6kM,3019
17
+ pySEQTarget/expansion/_diagnostics.py,sha256=QyQ8HRe2tt8oYfMK1Q_gQAmo_nnaBPHgDo_DDEk2DTM,1507
18
+ pySEQTarget/expansion/_dynamic.py,sha256=_iPJHR5KlCY9A71BfIS-V94hwFldPU17Yd36U7JAlJ0,2406
19
+ pySEQTarget/expansion/_mapper.py,sha256=ROw8EJhok3r_UfY3u6DEe9FtD_eco-IEd_MV72EajlE,1251
20
+ pySEQTarget/expansion/_selection.py,sha256=Ywas9JLBV3TEwm1kLb6CFD2CNza4_5DIDLgEVAobXEI,907
21
+ pySEQTarget/helpers/__init__.py,sha256=Q0H0t6kehgJBkiOaOuB_Truq7kzOKGSiNS-ihX_4sEI,416
22
+ pySEQTarget/helpers/_bootstrap.py,sha256=BiOxYfaf5HBEhoXJcw652JSJbe9BPFvT6GQ9Oq2p6A0,3375
23
+ pySEQTarget/helpers/_col_string.py,sha256=ABMK8vlesY7yIAVKnxN0DRgLZgOCImHxmKphFYRNSv0,213
24
+ pySEQTarget/helpers/_format_time.py,sha256=WGsJDJHxALz0NJSxC8Yht42yOUMju9hJQx8Nitt6bh8,247
25
+ pySEQTarget/helpers/_output_files.py,sha256=dOfgIw1Io0zNjkNexdtdduQcWfBrKK2_W2IPJiVwgDY,5100
26
+ pySEQTarget/helpers/_pad.py,sha256=9ePWswrhqSAVnAu7IBUmkBdI-w1YnBd0ozV9GvQR_dI,194
27
+ pySEQTarget/helpers/_predict_model.py,sha256=dtkMFGMi-ut_HG9Lyp33FUln7E4zitr1ALYC2Ylc8H4,267
28
+ pySEQTarget/helpers/_prepare_data.py,sha256=Nh9TZWlMqohCr4PJ0wlM8ej-w7bGc1rW_4_RVLcErq4,553
29
+ pySEQTarget/initialization/__init__.py,sha256=1ExTDKGsyVLUh6xV6zHda_6WjcD8JMAUyNvHbFVKgD4,273
30
+ pySEQTarget/initialization/_censoring.py,sha256=HkRzbdbTwG9zbX7KRqr9IgNogY3puX0qfClJdD7feo4,1720
31
+ pySEQTarget/initialization/_denominator.py,sha256=Nvqa8EErk-lIxxosm6pqBmr_O6CzpEOEHlI57StlWUg,1534
32
+ pySEQTarget/initialization/_numerator.py,sha256=LjzCVhhch_Ex4nA2el9V0xmwoTf0J2QWjUEfane_E2M,1396
33
+ pySEQTarget/initialization/_outcome.py,sha256=cMhF2KfbInrf7bH6uzngPhWgQEV769Ww578EgIeL_AE,2119
34
+ pySEQTarget/plot/__init__.py,sha256=Wf_4bmD-5gzLUXhSeDDaEIcxNknFjBvDyk55LOXiqOQ,61
35
+ pySEQTarget/plot/_survival_plot.py,sha256=WtHfcpJ5zfa71LjgiHDklxwLmanVorC4hJGJp1-Av5c,3095
36
+ pySEQTarget/weighting/__init__.py,sha256=Gv6zArKhK0many5qgi0ZikwQSCOAelCbuit13SP7DQc,449
37
+ pySEQTarget/weighting/_weight_bind.py,sha256=VP0RO-VIgXqmdp4uhsN78xefxI-Gid4J-QxH0MKDxNs,2508
38
+ pySEQTarget/weighting/_weight_data.py,sha256=P8E_-kOdb-s0Et5PL8b3Q-CnwuW6Ir8hMw_Zw80T0WM,1482
39
+ pySEQTarget/weighting/_weight_fit.py,sha256=o73Lmz-bw58y5JjU9IV584JM-rfSTQXQuJBKOwi7-6k,3143
40
+ pySEQTarget/weighting/_weight_pred.py,sha256=Rw1fQBi54ml62syKKE5xJFtIZJAchOvmnctJ10A82L8,7727
41
+ pySEQTarget/weighting/_weight_stats.py,sha256=pJNH6A9_jQd4WFV1LYMum66VBJHrGsu5CUOPtBKrLD8,815
42
+ pyseqtarget-0.10.0.dist-info/licenses/LICENSE,sha256=4iJQjIiCY2dK-vPGS4ptUlkstcDaS1MaQzv288_SNec,1065
43
+ pyseqtarget-0.10.0.dist-info/METADATA,sha256=q6tzVwxfbNwbJ5qfC367WOGfgJH0hD3ENie4HhXyy7g,4869
44
+ pyseqtarget-0.10.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
45
+ pyseqtarget-0.10.0.dist-info/top_level.txt,sha256=deyVmAqpFjyyxotp61jc5zwh0qdSqxCmvn8pWGw3YZo,12
46
+ pyseqtarget-0.10.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 CAUSALab
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ pySEQTarget