SAR interpretation¶
Matched molecular pairs, activity cliffs, SALI, SARI, Free-Wilson analysis and R-group decomposition.
This is the part of the workflow that tells you why a model performs as it does, and — more usefully — predicts before you fit anything whether a regression model can work on this series at all.
Activity cliffs¶
An activity cliff is a pair of near-identical structures with very different activity. Cliffs are where QSAR fails by construction: any model built on a smooth similarity assumption must predict them wrong.
>>> from qsarkit.sar import activity_cliff_report
>>> report = activity_cliff_report(demo_mols, DEMO_Y, similarity_threshold=0.5)
>>> report["n_cliffs"], round(report["cliff_ratio"], 4)
(4, 0.0145)
The report names the substituent changes responsible, which is the part a chemist can act on:
>>> sorted(report["top_transformations"])
['[1*]C>>[1*]Cl', '[1*]Cl>>[1*]Br', '[1*]Cl>>[1*]N']
and the specific pairs:
>>> cliff = report["top_cliffs"][0]
>>> cliff.index_a, cliff.index_b, round(cliff.delta, 2)
(2, 5, 2.9)
Note
The default similarity threshold is 0.85, the figure usually quoted in the cliff literature — calibrated for drug-sized molecules with a large shared core. The demo set is small molecules, where a single-atom change alters every atom environment within the fingerprint radius and similarity scores run far below intuition. Threshold to your data, not to the paper.
SALI and the activity landscape¶
SALI ranks pairs by how steep the cliff is: activity difference over structural distance.
>>> from qsarkit.sar import SALIAnalyzer
>>> sali = SALIAnalyzer().sali_matrix(demo_mols, DEMO_Y)
>>> sali.shape
(24, 24)
>>> round(float(sali.max()), 2)
6.38
SARI condenses the whole landscape into one number, separating the continuous component (smooth SAR, which a model can learn) from the discontinuous one (cliffs, which it cannot):
>>> from qsarkit.sar import SARIAnalyzer
>>> scores = SARIAnalyzer().analyze(demo_mols, DEMO_Y)
>>> round(scores["sari"], 3), round(scores["discontinuity"], 3)
(0.481, 0.065)
Matched molecular pairs¶
MMPs are the formalization of “change one thing and see what happens”, which is how medicinal chemistry is actually done.
>>> from qsarkit.sar import MatchedMolecularPairs
>>> pairs = MatchedMolecularPairs().find_pairs(demo_mols[:8])
>>> len(pairs)
12
>>> print(pairs[0])
MatchedPair([1*]C(=O)O>>[1*]NC(C)=O)
The transformation is recorded as a SMIRKS-like rule, so identical changes across different cores aggregate — which is what turns a list of pairs into a transferable design rule.
Free-Wilson¶
Free-Wilson analysis fits activity as a sum of substituent contributions: the oldest QSAR method still in use, and still the most interpretable when the series shares one core.
>>> from qsarkit.sar import FreeWilsonAnalysis
>>> analysis = FreeWilsonAnalysis()
>>> hasattr(analysis, "fit")
True
Its assumption — that substituent effects are additive and independent — is exactly what an activity cliff violates. A high cliff ratio is a warning that Free-Wilson will mislead here.
API¶
Structure-activity relationship analysis: MMPs, activity cliffs, SAR tables.
This module answers the interpretation questions that come after a QSAR model is fitted: which structural changes drive activity, where the SAR is smooth versus discontinuous, and which compound pairs form activity cliffs that any similarity-based model will struggle with.
Examples
>>> from rdkit import Chem
>>> from qsarkit.sar import ActivityCliffDetector, activity_cliff_report
>>> mols = [Chem.MolFromSmiles(s) for s in
... ("CC(=O)Nc1ccc(Cl)cc1", "CC(=O)Nc1ccc(Br)cc1")]
>>> cliffs = ActivityCliffDetector(similarity_threshold=0.6).detect(mols, [9.0, 5.0])
>>> len(cliffs)
1
>>> activity_cliff_report(mols, [9.0, 5.0], similarity_threshold=0.6)["cliff_ratio"]
1.0
- class qsarkit.sar.MatchedPair(mol_a, mol_b, core, transformation, delta_activity=None, index_a=-1, index_b=-1)[source]¶
Bases:
objectOne matched molecular pair: two molecules sharing a common core.
- Variables:
mol_b (mol_a,) – The paired molecules.
core (
str) – Canonical SMILES of the shared context (with attachment points).transformation (
str) – The change, written"<frag_a>>>frag_b>"in SMIRKS-like form.delta_activity (
floatorNone) –activity_b - activity_awhen activities were supplied.index_b (index_a,) – Positions of the two molecules in the input sequence.
- mol_a: Mol¶
- mol_b: Mol¶
- class qsarkit.sar.MatchedMolecularPairs(max_cuts=1, max_fragment_heavy_atoms=13)[source]¶
Bases:
objectIdentify matched molecular pairs by the fragment-index algorithm.
Implements the Hussain & Rea approach: every molecule is fragmented at each acyclic single bond (and optionally at pairs or triples of such bonds); each
(context, fragment)split is indexed by its context; and any two molecules sharing a context — but differing in the attached fragment — constitute a matched pair whose transformation isfragment_a >> fragment_b.This is what turns a flat activity table into interpretable SAR: the effect of a substituent change, measured across every pair in which it occurs.
- Parameters:
max_cuts (
int) – Number of bonds cut simultaneously. 1 finds single-substituent changes (the vast majority of useful MMPs); 2-3 also finds linker and multi-point changes at rapidly growing cost.max_fragment_heavy_atoms (
Optional[int]) – Discard splits whose variable fragment is larger than this, which keeps pairs interpretable (a “pair” differing by half the molecule is not a useful MMP).Nonedisables the filter.
Examples
>>> from rdkit import Chem >>> mols = [Chem.MolFromSmiles(s) for s in ("c1ccccc1Cl", "c1ccccc1Br")] >>> pairs = MatchedMolecularPairs().find_pairs(mols) >>> len(pairs) >= 1 True
References
Hussain, J. & Rea, C. (2010). “Computationally Efficient Algorithm to Identify Matched Molecular Pairs (MMPs) in Large Data Sets.” J. Chem. Inf. Model., 50(3), 339-348. https://doi.org/10.1021/ci900450m
Griffen, E. et al. (2011). “Matched Molecular Pairs as a Medicinal Chemistry Tool.” J. Med. Chem., 54(22), 7739-7750. https://doi.org/10.1021/jm200452d
Dossetter, A. G., Griffen, E. J. & Leach, A. G. (2013). “Matched Molecular Pair Analysis in Drug Discovery.” Drug Discov. Today, 18(15-16), 724-731. https://doi.org/10.1016/j.drudis.2013.03.003
RDKit
FragmentOnBondsdocumentation: https://www.rdkit.org/docs/source/rdkit.Chem.rdmolops.html
- class qsarkit.sar.MMPAnalyzer(max_cuts=1, max_fragment_heavy_atoms=13)[source]¶
Bases:
objectSummarize the SAR encoded by a set of matched molecular pairs.
Aggregates pairs by transformation to answer the medicinal-chemistry question “what does this substituent change usually do to potency?”, which is the basis of MMP-derived design rules.
- Parameters:
max_cuts (
int) – Passed toMatchedMolecularPairs.max_fragment_heavy_atoms (
Optional[int]) – Passed toMatchedMolecularPairs.
Examples
>>> from rdkit import Chem >>> mols = [Chem.MolFromSmiles(s) for s in ("c1ccccc1Cl", "c1ccccc1Br")] >>> analyzer = MMPAnalyzer() >>> pairs = analyzer.find_pairs(mols, [5.0, 6.0]) >>> len(pairs) >= 1 True
References
Hussain, J. & Rea, C. (2010). J. Chem. Inf. Model., 50(3), 339-348. https://doi.org/10.1021/ci900450m
Leach, A. G. et al. (2006). “Matched Molecular Pairs as a Guide in the Optimization of Pharmaceutical Properties.” J. Med. Chem., 49(23), 6672-6682. https://doi.org/10.1021/jm0605233
- find_pairs(mols, activities=None)[source]¶
Delegate to
MatchedMolecularPairs.find_pairs().- Return type:
- transformation_summary(pairs)[source]¶
Aggregate activity change per transformation.
- Parameters:
pairs (
Sequence[MatchedPair]) – Pairs carryingdelta_activity.- Returns:
Columns
transformation,count,mean_delta,median_delta,std_delta, sorted by descendingcountthen descendingmean_delta. Transformations whose pairs have no activity data are omitted.- Return type:
- to_dataframe(pairs)[source]¶
Render pairs as a table.
- Parameters:
pairs (
Sequence[MatchedPair])- Returns:
Columns
smiles_a,smiles_b,core,transformation,delta_activity,index_a,index_b.- Return type:
- class qsarkit.sar.ActivityCliff(index_a, index_b, mol_a, mol_b, similarity, activity_a, activity_b, delta, sali)[source]¶
Bases:
objectA pair of similar molecules with a large activity difference.
- Variables:
index_b (index_a,) – Positions of the two molecules in the input sequence.
mol_b (mol_a,) – The two molecules.
similarity (
float) – Structural similarity in [0, 1].activity_b (activity_a,) – Their activities on a logarithmic scale (e.g. pIC50).
delta (
float) –abs(activity_a - activity_b).sali (
float) – Structure-Activity Landscape Index for the pair.
- mol_a: Mol¶
- mol_b: Mol¶
- class qsarkit.sar.ActivityCliffDetector(similarity_threshold=0.85, activity_threshold=2.0, method='fingerprint', radius=2, n_bits=2048)[source]¶
Bases:
objectDetect activity cliffs: similar structures with very different activity.
Activity cliffs are the single biggest obstacle to QSAR: they violate the similarity-property principle that regression models rely on, and a model that cannot reproduce them will systematically mispredict the most interesting compounds in a series. Detecting them tells you both where a model will fail and where the SAR carries real information.
A pair
(i, j)is a cliff whensimilarity(i, j) >= similarity_thresholdand|activity_i - activity_j| >= activity_threshold.- Parameters:
similarity_threshold (
float) – Minimum structural similarity. 0.85 on ECFP4 is the conventional cutoff in the activity-cliff literature.activity_threshold (
float) – Minimum absolute activity difference, in log units. 2.0 means a 100-fold potency change.method (
Literal['fingerprint','scaffold','mmp']) – How structural similarity is measured."scaffold"and"mmp"give binary similarity (1.0 for same scaffold / a matched pair), so with those the similarity threshold acts as a simple on/off test.radius (
int) – Morgan radius (ECFP4 = radius 2) for the fingerprint method.n_bits (
int) – Fingerprint length for the fingerprint method.
Examples
A 4-Cl / 4-Br swap on the same anilide core, four log units apart:
>>> from rdkit import Chem >>> mols = [Chem.MolFromSmiles(s) for s in ... ("CC(=O)Nc1ccc(Cl)cc1", "CC(=O)Nc1ccc(Br)cc1")] >>> detector = ActivityCliffDetector(similarity_threshold=0.6) >>> cliffs = detector.detect(mols, [9.0, 5.0]) >>> len(cliffs) 1 >>> round(cliffs[0].similarity, 3), cliffs[0].delta (0.615, 4.0)
Note how low that similarity is for a single-atom change. Morgan fingerprints of small molecules score far below intuition, because one substituent alters every atom environment within
radiusbonds of it. A threshold of 0.85 – the usual figure quoted for cliff analysis, and this class’s default – is calibrated for drug-sized molecules with a large shared core, and will find nothing in a set of fragments.References
Maggiora, G. M. (2006). “On Outliers and Activity Cliffs - Why QSAR Often Disappoints.” J. Chem. Inf. Model., 46(4), 1535. https://doi.org/10.1021/ci060117s
Stumpfe, D. & Bajorath, J. (2012). “Exploring Activity Cliffs in Medicinal Chemistry.” J. Med. Chem., 55(7), 2932-2942. https://doi.org/10.1021/jm300288g
Stumpfe, D., Hu, H. & Bajorath, J. (2019). “Evolving Concept of Activity Cliffs.” ACS Omega / J. Med. Chem., 62(5), 2354-2363. https://doi.org/10.1021/acs.jmedchem.9b00004
Cruz-Monteagudo, M. et al. (2014). “Activity Cliffs in Drug Discovery: Dr Jekyll or Mr Hyde?” Drug Discov. Today, 19(8), 1069-1080. https://doi.org/10.1016/j.drudis.2014.02.003
- detect(mols, activities)[source]¶
Find every activity cliff in a dataset.
- Parameters:
- Returns:
Sorted by descending SALI, so the sharpest cliffs come first.
- Return type:
- to_dataframe(cliffs)[source]¶
Render detected cliffs as a table.
- Parameters:
cliffs (
Sequence[ActivityCliff])- Return type:
- class qsarkit.sar.SALIAnalyzer(method='fingerprint', radius=2, n_bits=2048)[source]¶
Bases:
objectStructure-Activity Landscape Index (SALI) analysis.
SALI quantifies how sharply activity changes with structure:
SALI(i, j) = |A_i - A_j| / (1 - sim(i, j))
Large values mark cliffs — small structural change, large activity change. Beyond the pairwise matrix, the SALI curve scores how well a model reproduces the landscape: pairs are ranked by true SALI and by predicted SALI, and the fraction of top-ranked true pairs the model also ranks highly gives a curve whose area (in [0, 1], 1 = perfect) is a landscape-aware model-quality metric that ordinary RMSE/R2 completely miss.
- Parameters:
Examples
>>> from rdkit import Chem >>> mols = [Chem.MolFromSmiles(s) for s in ("CCO", "CCC", "CCN")] >>> analyzer = SALIAnalyzer() >>> S = analyzer.sali_matrix(mols, [5.0, 6.0, 7.0]) >>> S.shape (3, 3)
References
Guha, R. & Van Drie, J. H. (2008). “Structure-Activity Landscape Index: Identifying and Quantifying Activity Cliffs.” J. Chem. Inf. Model., 48(3), 646-658. https://doi.org/10.1021/ci7004093
Guha, R. (2012). “Exploring Structure-Activity Data Using the Landscape Paradigm.” WIREs Comput. Mol. Sci. / J. Chem. Inf. Model., 52(8), 2181-2191. https://doi.org/10.1021/ci300047k
Guha, R. & Van Drie, J. H. (2008). “Assessing How Well a Modeling Protocol Captures a Structure-Activity Landscape.” J. Chem. Inf. Model., 48(8), 1716-1728. https://doi.org/10.1021/ci8001414
- sali_matrix(mols, activities)[source]¶
Pairwise SALI matrix.
- Parameters:
- Returns:
Symmetric, zero diagonal,
infwhere two distinct molecules have identical structure fingerprints.- Return type:
- sali_curve(mols, y_true, y_pred, n_points=50)[source]¶
SALI curve comparing true and predicted activity landscapes.
For each cutoff
X(fraction of the highest-SALI true pairs), the curve reports the fraction of those pairs whose activity ordering the model reproduces.
- class qsarkit.sar.SARIAnalyzer(similarity_threshold=0.6, reference_delta=3.0, radius=2, n_bits=2048)[source]¶
Bases:
objectStructure-Activity Relationship Index (SARI): continuity vs discontinuity.
SARI scores a compound set on two orthogonal axes and combines them:
SARI = 0.5 * ((1 - continuity_norm) + discontinuity_norm)
The continuity score reflects smooth, gradual SAR (similar molecules with similar potency, weighted by potency); the discontinuity score reflects cliffs (similar molecules with very different potency). A series can be high in both — a “heterogeneous” SAR that is smooth in one region and cliff-ridden in another.
- Parameters:
similarity_threshold (
float) – Minimum similarity for a pair to contribute to the discontinuity term.reference_delta (
float) – Activity difference, in log units, treated as maximally discontinuous when normalizing the discontinuity score. Fixing this on an absolute scale (rather than the dataset’s own range) is what makes SARI comparable between series.radius (
int) – Morgan radius.n_bits (
int) – Fingerprint length.
Examples
>>> from rdkit import Chem >>> mols = [Chem.MolFromSmiles(s) for s in ("CCO", "CCC", "CCN", "CCCl")] >>> scores = SARIAnalyzer().analyze(mols, [5.0, 5.2, 5.1, 8.0]) >>> set(scores) == {"continuity", "discontinuity", "sari"} True
References
Peltason, L. & Bajorath, J. (2007). “SAR Index: Quantifying the Nature of Structure-Activity Relationships.” J. Med. Chem., 50(23), 5571-5578. https://doi.org/10.1021/jm070562u
Wassermann, A. M., Wawer, M. & Bajorath, J. (2010). “Activity Landscape Representations for Structure-Activity Relationship Analysis.” J. Med. Chem., 53(23), 8209-8223. https://doi.org/10.1021/jm100933w
- class qsarkit.sar.ActivityLandscapePlotter(similarity_threshold=0.6, activity_threshold=0.6, radius=2, n_bits=2048)[source]¶
Bases:
objectStructure-Activity Similarity (SAS) map data and Plotly figure.
A SAS map plots every compound pair as (structure similarity, activity similarity) and reads the four quadrants as distinct SAR regimes:
Structure sim.
Activity sim.
Interpretation
high
high
smooth / continuous SAR
high
low
activity cliff
low
high
scaffold hop
low
low
nondescript
- Parameters:
Examples
>>> from rdkit import Chem >>> mols = [Chem.MolFromSmiles(s) for s in ("CCO", "CCC", "CCN")] >>> df = ActivityLandscapePlotter().sas_data(mols, [5.0, 7.0, 5.1]) >>> sorted(df.columns) ['activity_similarity', 'delta_activity', 'index_a', 'index_b', 'quadrant', 'structure_similarity']
One row per pair, each assigned to a quadrant of the SAS map:
>>> len(df) # three pairs from three molecules 3 >>> sorted(set(df["quadrant"])) ['nondescript', 'scaffold hop']
References
Shanmugasundaram, V. & Maggiora, G. M. (2001). “Characterizing Property and Activity Landscapes Using an Information-Theoretic Approach.” 222nd ACS National Meeting, CINF 77.
Wassermann, A. M., Wawer, M. & Bajorath, J. (2010). J. Med. Chem., 53(23), 8209-8223. https://doi.org/10.1021/jm100933w
Perez-Villanueva, J. et al. (2011). “Comparison of Multiple 2D Representations for the Activity Landscape Modeling.” Bioorg. Med. Chem., 19(21), 6183-6193. https://doi.org/10.1016/j.bmc.2011.09.024
- qsarkit.sar.activity_cliff_report(mols, activities, similarity_threshold=0.85, activity_threshold=2.0, top_n=10)[source]¶
Summarize the activity-cliff content of a dataset.
A one-call diagnostic to run before modeling: a high cliff ratio predicts that a regression model will underperform on this series no matter how it is tuned, and points at which scaffolds and which substituent changes are responsible.
- Parameters:
mols (
Sequence[Mol]) – Molecules.similarity_threshold (
float) – Passed toActivityCliffDetector.activity_threshold (
float) – Passed toActivityCliffDetector.top_n (
int) – How many top scaffolds/transformations/cliffs to report.
- Returns:
n_compounds,n_pairs,n_cliffs,cliff_ratio(cliffs / all pairs),cliff_compound_fraction(fraction of compounds involved in at least one cliff),max_sali,top_cliffs,top_scaffolds(scaffold SMILES -> cliff count),top_transformations(MMP transformation -> cliff count), andsari.- Return type:
Examples
>>> from rdkit import Chem >>> mols = [Chem.MolFromSmiles(s) for s in ... ("CC(=O)Nc1ccc(Cl)cc1", "CC(=O)Nc1ccc(Br)cc1")] >>> report = activity_cliff_report(mols, [9.0, 5.0], similarity_threshold=0.6) >>> report["n_cliffs"] 1 >>> report["cliff_ratio"] # one cliff out of one pair 1.0
References
Stumpfe, D. & Bajorath, J. (2012). J. Med. Chem., 55(7), 2932-2942. https://doi.org/10.1021/jm300288g
Guha, R. & Van Drie, J. H. (2008). J. Chem. Inf. Model., 48(3), 646-658. https://doi.org/10.1021/ci7004093
van Tilborg, D., Alenicheva, A. & Grisoni, F. (2022). “Exposing the Limitations of Molecular Machine Learning with Activity Cliffs.” J. Chem. Inf. Model., 62(23), 5938-5951. https://doi.org/10.1021/acs.jcim.2c01073
- class qsarkit.sar.RGroupAnalyzer(core=None)[source]¶
Bases:
objectDecompose a congeneric series into a core plus R-group substituents.
Wraps RDKit’s
rdRGroupDecompositionto turn a set of analogues into the R-group table medicinal chemists actually reason with: one row per compound, one column per substitution point.- Parameters:
core (
Optional[Any]) – The scaffold, as a Mol or SMARTS/SMILES string. WhenNone, the most common Bemis-Murcko scaffold in the series is used.
Examples
>>> from rdkit import Chem >>> mols = [Chem.MolFromSmiles(s) for s in ("c1ccccc1Cl", "c1ccccc1Br")] >>> analyzer = RGroupAnalyzer(core="c1ccccc1") >>> table = analyzer.decompose(mols) >>> "Core" in table.columns True
References
Bemis, G. W. & Murcko, M. A. (1996). “The Properties of Known Drugs. 1. Molecular Frameworks.” J. Med. Chem., 39(15), 2887-2893. https://doi.org/10.1021/jm9602928
RDKit
rdRGroupDecompositiondocumentation: https://www.rdkit.org/docs/source/rdkit.Chem.rdRGroupDecomposition.htmlStierand, K. & Rarey, M. (2010). “Drawing the PDB: Protein-Ligand Complexes in Two Dimensions.” ACS Med. Chem. Lett., 1(9), 540-545. https://doi.org/10.1021/ml100164p
- decompose(mols)[source]¶
Run R-group decomposition over a series.
- Parameters:
mols (
Sequence[Mol]) – Analogues sharing a common core.- Returns:
One row per successfully decomposed molecule; a
Corecolumn plus oneR1,R2, … column per attachment point, all as SMILES. Molecules that do not match the core are omitted, and their positions are recorded in the frame’sattrs["unmatched"].- Return type:
- class qsarkit.sar.SARTable(core=None)[source]¶
Bases:
objectR-group x activity table for a congeneric series.
Joins an R-group decomposition to measured activities so that the contribution of each substituent at each position can be read directly, and pivoted into the classic two-position SAR grid.
- Parameters:
core (
Optional[Any]) – Passed toRGroupAnalyzer.
Examples
>>> from rdkit import Chem >>> mols = [Chem.MolFromSmiles(s) for s in ("c1ccccc1Cl", "c1ccccc1Br")] >>> table = SARTable(core="c1ccccc1").build(mols, [5.0, 6.0]) >>> "activity" in table.columns True
References
Agrafiotis, D. K. et al. (2011). “SAR Maps: A New SAR Visualization Technique for Medicinal Chemists.” J. Med. Chem., 50(24), 5926-5937. https://doi.org/10.1021/jm070845m
Wassermann, A. M. et al. (2010). J. Med. Chem., 53(23), 8209-8223. https://doi.org/10.1021/jm100933w
- pivot(table, row='R1', column='R2', aggfunc='mean')[source]¶
Pivot into the classic two-position SAR grid.
- class qsarkit.sar.FreeWilsonAnalysis(core=None, fit_intercept=True, alpha=0.0)[source]¶
Bases:
objectFree-Wilson additive SAR model over R-group indicator variables.
The original QSAR method: activity is modelled as a baseline plus an additive contribution from each substituent at each position,
\[A = \mu + \sum_{p} \sum_{s} a_{p,s} X_{p,s}\]fitted by linear regression on one-hot indicators. It is exactly interpretable — each coefficient is “what this substituent is worth at this position, in log units” — and its residuals are themselves informative: large ones mark non-additive SAR, i.e. activity cliffs and substituent interactions the additive model cannot represent.
- Parameters:
core (
Optional[Any]) – Passed toRGroupAnalyzer.fit_intercept (
bool) – Whether to fit the baseline term.alpha (
float) – Ridge penalty. Free-Wilson designs are often rank-deficient (a substituent appearing once is perfectly confounded with its compound), so a small positive alpha is frequently needed.
- Variables:
Examples
>>> from rdkit import Chem >>> mols = [Chem.MolFromSmiles(s) for s in ... ("c1ccccc1Cl", "c1ccccc1Br", "c1ccccc1F")] >>> fw = FreeWilsonAnalysis(core="c1ccccc1", alpha=0.1) >>> _ = fw.fit(mols, [5.0, 6.0, 4.0]) >>> isinstance(fw.r2_, float) True
References
Free, S. M. & Wilson, J. W. (1964). “A Mathematical Contribution to Structure-Activity Studies.” J. Med. Chem., 7(4), 395-399. https://doi.org/10.1021/jm00334a001
Kubinyi, H. (1988). “Free Wilson Analysis. Theory, Applications and its Relationship to Hansch Analysis.” Quant. Struct.-Act. Relat., 7(3), 121-133. https://doi.org/10.1002/qsar.19880070303
Patel, Y., Gillet, V. J. et al. (2018). “Reinvestigating the Free-Wilson Approach.” J. Comput. Aided Mol. Des. https://doi.org/10.1007/s10822-018-0116-z
- fit(mols, activities)[source]¶
Fit substituent contributions by linear regression.
- Parameters:
- Returns:
The fitted analysis.
- Return type:
References¶
Maggiora, G. M. (2006). “On Outliers and Activity Cliffs — Why QSAR Often Disappoints.” J. Chem. Inf. Model., 46(4), 1535. doi:10.1021/ci060117s
Guha, R. & Van Drie, J. H. (2008). “Structure-Activity Landscape Index.” J. Chem. Inf. Model., 48(3), 646-658. doi:10.1021/ci7004093
Peltason, L. & Bajorath, J. (2007). “SAR Index: Quantifying the Nature of Structure-Activity Relationships.” J. Med. Chem., 50(23), 5571-5578. doi:10.1021/jm070562u
Hussain, J. & Rea, C. (2010). “Computationally Efficient Algorithm to Identify Matched Molecular Pairs (MMPs) in Large Data Sets.” J. Chem. Inf. Model., 50(3), 339-348. doi:10.1021/ci900450m
Free, S. M. & Wilson, J. W. (1964). “A Mathematical Contribution to Structure-Activity Studies.” J. Med. Chem., 7(4), 395-399. doi:10.1021/jm00334a001
van Tilborg, D., Alenicheva, A. & Grisoni, F. (2022). “Exposing the Limitations of Molecular Machine Learning with Activity Cliffs.” J. Chem. Inf. Model., 62(23), 5938-5951. doi:10.1021/acs.jcim.2c01073