Raw Datasets
Investigation into the raw data of the solubility challenge expanded datasets.
4 data sources, obtained by Adam Atkins: • Delaney – 1144 compounds from Syngenta paper http://pubs.acs.org/doi/abs/10.1021/ci034243x • Huuskonen – 1312 compounds in three separate sets from http://pubs.acs.org/doi/pdf/10.1021/ci9901338 obtained from AQUASOL database and SCR’s PHYSPROP database. • Pubchem – 57859 compounds obtained from Pubchem through the API https://pubchem.ncbi.nlm.nih.gov/bioassay/1996 (Aqueous solubilty from MLSMR stock solutions) produced by Burnham Centre for Chemical Genomics. • Solubility_challenge – 132 compounds (141 compound forms) obtained from the Pfizer Institute for Pharmaceutical Materials Science & Unilever Centre for Molecular Informatics, Department of Chemistry, University of Cambridge http://pubs.acs.org/doi/pdf/10.1021/ci800058v , http://www-jmg.ch.cam.ac.uk/data/solubility/
Total number of compounds in combined dataset : 60456 Not all of these compounds were taken through to the descriptor stage. Some were rejected by Dragon due to incorrectly depicted structures. Of those that did have descriptors calculated, some of them do not have solubility measurements.
Compounds outputted by Dragon: 58562 Compounds rejected by Dragon: 1894
Compounds without solubility measurements (from total compounds): uncalculated
Compounds without solubility measurements (from outputted compounds): 12
Import the solubility values, these are the compounds output by Dragon, with only their MW descriptor and the solubility value (converted to LogS for all compounds) some of these currently are not rounded, but contain many decimal places due to the calculation carried out on them. These should be rounded as they are not known to many decimal places.
Distribution of data values
#histogram of the LogS values
hist(solubility_output_MW_only$LogS.M.)

#histogram of the MW values
hist(solubility_output_MW_only$MW)

What is the peak at approx -3.5 why would so many compounds be contained within that group, but such a sharp drop in the neighbouring category.
In order to produce a density plot, the dataset can only contain complete columns. Therefore we need to remove lines which do not have LogS values in the dataset. This leaves us with 58550 compounds in the datset.
#density plots
solubility_output_LogS_MW_complete <- na.omit(solubility_output_LogS_MW)
#58550 compounds
d<- density(solubility_output_LogS_MW_complete$LogS)
plot(d)

#kernel density plot for the data. Large peak at approx -4
#add some descriptions to this plot
Kernel density plot for the dataset, only complete cases. Plots the distribution of the LogS variable. Large peak at approx -4, what could be casusing this. This is caused by the PubChem dataset as that is the largest component of the data. How does the data distribution differ for the other sets?
PubChem subset - 55971 compounds

Delaney subset - 1144 compounds
Delaney <- subset(solubility_output_LogS_MW_complete, Source == "Delaney")
plot(dDelaney)

Huuskonen subset - 1305 compounds
Huuskonen <- subset(solubility_output_LogS_MW_complete, Source == "Huuskonen")
dHuuskonen <- density(Huuskonen$LogS)
plot(dHuuskonen)

Solubility Challenge subset - 130 compounds
Solubility_Challenge <- subset(solubility_output_LogS_MW_complete, Source == "Solubility Challenge")
dSolubility_Challenge <- density(Solubility_Challenge$LogS)
plot(dSolubility_Challenge)

Compare the distributions of the various sets.
library(sm)
attach(solubility_output_LogS_MW_complete)
The following objects are masked from solubility_output_LogS_MW_complete (pos = 4):
Compound_Identifier, LogS, MW, Source
The following objects are masked from solubility_output_LogS_MW_complete (pos = 5):
Compound_Identifier, LogS, MW, Source
#create value labels
Source.f <- factor(Source, levels=c("Delaney", "Huuskonen", "PubChem", "Solubility Challenge"), labels = c("Delaney", "Huuskonen", "PubChem", "Solubility Challenge"))
#plot densities
sm.density.compare(LogS, Source, xlab="LogS")
# add legend
colfill<-c(2:(2+length(levels(Source.f))))
legend("topright", levels(Source.f), fill=colfill)

detach(solubility_output_LogS_MW_complete)
Delaney and Huuskonen seems very similar distributions. PubChem has a lower peak than the other datasets, but much sharper. Is this simply caused by the dataset being significantly larger than the others?
Solubility values
33 compounds with a LogS value > 1 All 33 compounds are contained within the Delaney/Huuskonen dataset.
PubChem missing column
Re-examining the raw datafile obtained from the API suggests that an important column was missing from the API/script file downloaded for the PubChem assay. The assay actually has 3 possible qualified results, >, < or = to a value in the neighbouring column. For those compounds which have a = the value can simply be used. However those compounds containing < or > qualifiers, the values cannot simply be used. They should instead be excluded.
The comments on the assay suggests that there is an experimental threshold above which the method contain obtain accurate readings. possibly 75% of the 200micromolar compound load. Conversion of 150micromolar to LogS/M gives a value of -3.824 this seems to correspond to the position of the peak in the LogS distribution and may be the cause of it.
In order to identify the compounds that are < or > instead of = the assay dataset has been re-obtained with the additional column, however this does not contain the structural information columns, so the two datasets must be merged together.
The datasets have been merged and subsetted out into 3 different subsets, those containing > as the qualifier (16695 compounds), those containing < as the qualifier (3036 compounds) and those containing = as the qualifier (36420 compounds)
hist(PubChem_GT$LogS)

hist(PubChem_LT$LogS)

hist(PubChem_Equals$LogS)

There still appears to be a peak at approx -3.8 on the PubChem_equals subset. However this is reduced from the previous peak.
library(sm)
attach(PubChem_qualified_outputs)
The following objects are masked from solubility_output_LogS_MW_complete (pos = 4):
Compound_Identifier, LogS, MW, Source
The following objects are masked from solubility_output_LogS_MW_complete (pos = 5):
Compound_Identifier, LogS, MW, Source
#create value labels
Qualifier.for.solubility.f <- factor(Qualifier.for.solubility, levels=c("LT", "Equals", "GT"), labels = c("LT", "Equals", "GT"))
#plot densities
sm.density.compare(LogS, Qualifier.for.solubility, xlab="LogS")
# add legend
colfill<-c(2:(2+length(levels(Qualifier.f))))
legend("topright", levels(Qualifier.f), fill=colfill)

detach(PubChem_qualified_outputs)
This compare plot appears to have the different subsets incorrectly labelled. Additionally the densities relative to each other appear incorrect. They also appear different to the individual plots for the equals group (marked as the GT group here)
Plotting densities for the 3 subsets seperately gives the correct positioning for the curves, however the densities for the GT subset go to approx 1500 but the LT subset only goes to approx 2.5 and the equals subset approx 1.5. Look into how the density is displayed as the equals subset has over twice the number of compounds that the GT subset contains.
dPubChem_GT <-density(PubChem_GT$LogS)
plot(dPubChem_GT)

dPubChem_LT <-density(PubChem_LT$LogS)
plot(dPubChem_LT)

dPubChem_Equals <-density(PubChem_Equals$LogS)
plot(dPubChem_Equals)

LS0tDQp0aXRsZTogIlNvbHViaWxpdHkgY2hhbGxlbmdlIGV4YW1pbmF0aW9uIG9mIGRhdGEiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KI1JhdyBEYXRhc2V0cw0KDQpJbnZlc3RpZ2F0aW9uIGludG8gdGhlIHJhdyBkYXRhIG9mIHRoZSBzb2x1YmlsaXR5IGNoYWxsZW5nZSBleHBhbmRlZCBkYXRhc2V0cy4gDQoNCjQgZGF0YSBzb3VyY2VzLCBvYnRhaW5lZCBieSBBZGFtIEF0a2luczogDQrigKIJRGVsYW5leSDigJMgMTE0NCBjb21wb3VuZHMgZnJvbSBTeW5nZW50YSBwYXBlciBodHRwOi8vcHVicy5hY3Mub3JnL2RvaS9hYnMvMTAuMTAyMS9jaTAzNDI0M3gNCuKAoglIdXVza29uZW4g4oCTIDEzMTIgY29tcG91bmRzIGluIHRocmVlIHNlcGFyYXRlIHNldHMgZnJvbSBodHRwOi8vcHVicy5hY3Mub3JnL2RvaS9wZGYvMTAuMTAyMS9jaTk5MDEzMzggb2J0YWluZWQgZnJvbSBBUVVBU09MIGRhdGFiYXNlIGFuZCBTQ1LigJlzIFBIWVNQUk9QIGRhdGFiYXNlLiANCuKAoglQdWJjaGVtIOKAkyA1Nzg1OSBjb21wb3VuZHMgb2J0YWluZWQgZnJvbSBQdWJjaGVtIHRocm91Z2ggdGhlIEFQSSBodHRwczovL3B1YmNoZW0ubmNiaS5ubG0ubmloLmdvdi9iaW9hc3NheS8xOTk2IChBcXVlb3VzIHNvbHViaWx0eSBmcm9tIE1MU01SIHN0b2NrIHNvbHV0aW9ucykgcHJvZHVjZWQgYnkgQnVybmhhbSBDZW50cmUgZm9yIENoZW1pY2FsIEdlbm9taWNzLiANCuKAoglTb2x1YmlsaXR5X2NoYWxsZW5nZSDigJMgMTMyIGNvbXBvdW5kcyAgKDE0MSBjb21wb3VuZCBmb3Jtcykgb2J0YWluZWQgZnJvbSB0aGUgUGZpemVyIEluc3RpdHV0ZSBmb3IgUGhhcm1hY2V1dGljYWwgTWF0ZXJpYWxzIFNjaWVuY2UgJiBVbmlsZXZlciAgQ2VudHJlIGZvciBNb2xlY3VsYXIgSW5mb3JtYXRpY3MsIERlcGFydG1lbnQgb2YgQ2hlbWlzdHJ5LCBVbml2ZXJzaXR5IG9mIENhbWJyaWRnZQ0KaHR0cDovL3B1YnMuYWNzLm9yZy9kb2kvcGRmLzEwLjEwMjEvY2k4MDAwNTh2ICwgaHR0cDovL3d3dy1qbWcuY2guY2FtLmFjLnVrL2RhdGEvc29sdWJpbGl0eS8gDQoNCg0KVG90YWwgbnVtYmVyIG9mIGNvbXBvdW5kcyBpbiBjb21iaW5lZCBkYXRhc2V0IDogNjA0NTYNCgkgTm90IGFsbCBvZiB0aGVzZSBjb21wb3VuZHMgd2VyZSB0YWtlbiB0aHJvdWdoIHRvIHRoZSBkZXNjcmlwdG9yIHN0YWdlLiBTb21lIHdlcmUgcmVqZWN0ZWQgYnkgRHJhZ29uIGR1ZSB0byBpbmNvcnJlY3RseSBkZXBpY3RlZCBzdHJ1Y3R1cmVzLiBPZiB0aG9zZSB0aGF0IGRpZCBoYXZlIGRlc2NyaXB0b3JzIGNhbGN1bGF0ZWQsIHNvbWUgb2YgdGhlbSBkbyBub3QgaGF2ZSBzb2x1YmlsaXR5IG1lYXN1cmVtZW50cy4NCgkgDQpDb21wb3VuZHMgb3V0cHV0dGVkIGJ5IERyYWdvbjogNTg1NjINCkNvbXBvdW5kcyByZWplY3RlZCBieSBEcmFnb246IDE4OTQNCg0KQ29tcG91bmRzIHdpdGhvdXQgc29sdWJpbGl0eSBtZWFzdXJlbWVudHMgKGZyb20gdG90YWwgY29tcG91bmRzKTogdW5jYWxjdWxhdGVkICANCkNvbXBvdW5kcyB3aXRob3V0IHNvbHViaWxpdHkgbWVhc3VyZW1lbnRzIChmcm9tIG91dHB1dHRlZCBjb21wb3VuZHMpOiAxMg0KDQpJbXBvcnQgdGhlIHNvbHViaWxpdHkgdmFsdWVzLCB0aGVzZSBhcmUgdGhlIGNvbXBvdW5kcyBvdXRwdXQgYnkgRHJhZ29uLCB3aXRoIG9ubHkgdGhlaXIgTVcgZGVzY3JpcHRvciBhbmQgdGhlIHNvbHViaWxpdHkgdmFsdWUgKGNvbnZlcnRlZCB0byBMb2dTIGZvciBhbGwgY29tcG91bmRzKSBzb21lIG9mIHRoZXNlIGN1cnJlbnRseSBhcmUgbm90IHJvdW5kZWQsIGJ1dCBjb250YWluIG1hbnkgZGVjaW1hbCBwbGFjZXMgZHVlIHRvIHRoZSBjYWxjdWxhdGlvbiBjYXJyaWVkIG91dCBvbiB0aGVtLiBUaGVzZSBzaG91bGQgYmUgcm91bmRlZCBhcyB0aGV5IGFyZSBub3Qga25vd24gdG8gbWFueSBkZWNpbWFsIHBsYWNlcy4NCg0KYGBge3J9DQojaW1wb3J0IHRoZSBzb2x1YmlsaXR5IHZhbHVlcyANCnNvbHViaWxpdHlfb3V0cHV0X01XX29ubHkgPC0gcmVhZC5jc3YoIkM6XFxVc2Vyc1xcbmsxZzA5XFxEcm9wYm94XFxTb2x1YmlsaXR5X2NoYWxsZW5nZVxcUl9wcm9qZWN0XFxzb2x1YmlsaXR5X291dHB1dF9NV19vbmx5LmNzdiIpDQoNCiNzZWxlY3QgdGhlIGNvbHVtbnMNCiNtYWtlIGludG8gbmV3IGRhdGFmcmFtZQ0Kc29sdWJpbGl0eV9vdXRwdXRfTG9nU19NVzwtIGRhdGEuZnJhbWUoQ29tcG91bmRfSWRlbnRpZmllciA9IHNvbHViaWxpdHlfb3V0cHV0X01XX29ubHkkQ29tcG91bmRfSWRlbnRpZmllciwgTG9nUyA9IHNvbHViaWxpdHlfb3V0cHV0X01XX29ubHkkTG9nUy5NLiwgTVcgPSBzb2x1YmlsaXR5X291dHB1dF9NV19vbmx5JE1XLCBTb3VyY2UgPSBzb2x1YmlsaXR5X291dHB1dF9NV19vbmx5JFNvdXJjZSkNCiNpcyB0aGVyZSBhIGJldHRlciB3YXkgdG8gZG8gdGhpcz8gU3Vic2V0dGluZz8NCiM1ODU2MiBjb21wb3VuZHMNCmBgYA0KDQojRGlzdHJpYnV0aW9uIG9mIGRhdGEgdmFsdWVzDQpgYGB7cn0NCg0KI2hpc3RvZ3JhbSBvZiB0aGUgTG9nUyB2YWx1ZXMNCmhpc3Qoc29sdWJpbGl0eV9vdXRwdXRfTVdfb25seSRMb2dTLk0uKQ0KDQojaGlzdG9ncmFtIG9mIHRoZSBNVyB2YWx1ZXMNCmhpc3Qoc29sdWJpbGl0eV9vdXRwdXRfTVdfb25seSRNVykNCmBgYA0KDQpXaGF0IGlzIHRoZSBwZWFrIGF0IGFwcHJveCAtMy41IHdoeSB3b3VsZCBzbyBtYW55IGNvbXBvdW5kcyBiZSBjb250YWluZWQgd2l0aGluIHRoYXQgZ3JvdXAsIGJ1dCBzdWNoIGEgc2hhcnAgZHJvcCBpbiB0aGUgbmVpZ2hib3VyaW5nIGNhdGVnb3J5LiAgDQoNCkluIG9yZGVyIHRvIHByb2R1Y2UgYSBkZW5zaXR5IHBsb3QsIHRoZSBkYXRhc2V0IGNhbiBvbmx5IGNvbnRhaW4gY29tcGxldGUgY29sdW1ucy4gVGhlcmVmb3JlIHdlIG5lZWQgdG8gcmVtb3ZlIGxpbmVzIHdoaWNoIGRvIG5vdCBoYXZlIExvZ1MgdmFsdWVzIGluIHRoZSBkYXRhc2V0LiBUaGlzIGxlYXZlcyB1cyB3aXRoIDU4NTUwIGNvbXBvdW5kcyBpbiB0aGUgZGF0c2V0LiANCmBgYHtyfQ0KI2RlbnNpdHkgcGxvdHMNCnNvbHViaWxpdHlfb3V0cHV0X0xvZ1NfTVdfY29tcGxldGUgPC0gbmEub21pdChzb2x1YmlsaXR5X291dHB1dF9Mb2dTX01XKQ0KIzU4NTUwIGNvbXBvdW5kcw0KDQpkPC0gZGVuc2l0eShzb2x1YmlsaXR5X291dHB1dF9Mb2dTX01XX2NvbXBsZXRlJExvZ1MpDQpwbG90KGQpDQoja2VybmVsIGRlbnNpdHkgcGxvdCBmb3IgdGhlIGRhdGEuIExhcmdlIHBlYWsgYXQgYXBwcm94IC00IA0KI2FkZCBzb21lIGRlc2NyaXB0aW9ucyB0byB0aGlzIHBsb3QNCmBgYA0KS2VybmVsIGRlbnNpdHkgcGxvdCBmb3IgdGhlIGRhdGFzZXQsIG9ubHkgY29tcGxldGUgY2FzZXMuIFBsb3RzIHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIExvZ1MgdmFyaWFibGUuIExhcmdlIHBlYWsgYXQgYXBwcm94IC00LCB3aGF0IGNvdWxkIGJlIGNhc3VzaW5nIHRoaXMuIFRoaXMgaXMgY2F1c2VkIGJ5IHRoZSBQdWJDaGVtIGRhdGFzZXQgYXMgdGhhdCBpcyB0aGUgbGFyZ2VzdCBjb21wb25lbnQgb2YgdGhlIGRhdGEuIEhvdyBkb2VzIHRoZSBkYXRhIGRpc3RyaWJ1dGlvbiBkaWZmZXIgZm9yIHRoZSBvdGhlciBzZXRzPw0KDQpQdWJDaGVtIHN1YnNldCAtIDU1OTcxIGNvbXBvdW5kcw0KYGBge3J9DQpQdWJDaGVtIDwtIHN1YnNldChzb2x1YmlsaXR5X291dHB1dF9Mb2dTX01XX2NvbXBsZXRlLCBTb3VyY2UgPT0gIlB1YkNoZW0iKQ0KZFB1YkNoZW0gPC0gZGVuc2l0eShQdWJDaGVtJExvZ1MpDQpwbG90KGRQdWJDaGVtKQ0KYGBgDQpEZWxhbmV5IHN1YnNldCAtIDExNDQgY29tcG91bmRzDQpgYGB7cn0NCkRlbGFuZXkgPC0gc3Vic2V0KHNvbHViaWxpdHlfb3V0cHV0X0xvZ1NfTVdfY29tcGxldGUsIFNvdXJjZSA9PSAiRGVsYW5leSIpDQpkRGVsYW5leSA8LSBkZW5zaXR5KERlbGFuZXkkTG9nUykNCnBsb3QoZERlbGFuZXkpDQpgYGANCkh1dXNrb25lbiBzdWJzZXQgLSAxMzA1IGNvbXBvdW5kcw0KYGBge3J9DQpIdXVza29uZW4gPC0gc3Vic2V0KHNvbHViaWxpdHlfb3V0cHV0X0xvZ1NfTVdfY29tcGxldGUsIFNvdXJjZSA9PSAiSHV1c2tvbmVuIikNCmRIdXVza29uZW4gPC0gZGVuc2l0eShIdXVza29uZW4kTG9nUykNCnBsb3QoZEh1dXNrb25lbikNCmBgYA0KU29sdWJpbGl0eSBDaGFsbGVuZ2Ugc3Vic2V0IC0gMTMwIGNvbXBvdW5kcw0KYGBge3J9DQpTb2x1YmlsaXR5X0NoYWxsZW5nZSA8LSBzdWJzZXQoc29sdWJpbGl0eV9vdXRwdXRfTG9nU19NV19jb21wbGV0ZSwgU291cmNlID09ICJTb2x1YmlsaXR5IENoYWxsZW5nZSIpDQpkU29sdWJpbGl0eV9DaGFsbGVuZ2UgPC0gZGVuc2l0eShTb2x1YmlsaXR5X0NoYWxsZW5nZSRMb2dTKQ0KcGxvdChkU29sdWJpbGl0eV9DaGFsbGVuZ2UpDQpgYGANCg0KQ29tcGFyZSB0aGUgZGlzdHJpYnV0aW9ucyBvZiB0aGUgdmFyaW91cyBzZXRzLiANCmBgYHtyfQ0KbGlicmFyeShzbSkNCmF0dGFjaChzb2x1YmlsaXR5X291dHB1dF9Mb2dTX01XX2NvbXBsZXRlKQ0KDQojY3JlYXRlIHZhbHVlIGxhYmVscw0KU291cmNlLmYgPC0gZmFjdG9yKFNvdXJjZSwgbGV2ZWxzPWMoIkRlbGFuZXkiLCAiSHV1c2tvbmVuIiwgIlB1YkNoZW0iLCAiU29sdWJpbGl0eSBDaGFsbGVuZ2UiKSwgbGFiZWxzID0gYygiRGVsYW5leSIsICJIdXVza29uZW4iLCAiUHViQ2hlbSIsICJTb2x1YmlsaXR5IENoYWxsZW5nZSIpKQ0KDQojcGxvdCBkZW5zaXRpZXMNCnNtLmRlbnNpdHkuY29tcGFyZShMb2dTLCBTb3VyY2UsIHhsYWI9IkxvZ1MiKQ0KDQojIGFkZCBsZWdlbmQNCmNvbGZpbGw8LWMoMjooMitsZW5ndGgobGV2ZWxzKFNvdXJjZS5mKSkpKSANCmxlZ2VuZCgidG9wcmlnaHQiLCBsZXZlbHMoU291cmNlLmYpLCBmaWxsPWNvbGZpbGwpDQoNCmRldGFjaChzb2x1YmlsaXR5X291dHB1dF9Mb2dTX01XX2NvbXBsZXRlKQ0KYGBgDQpEZWxhbmV5IGFuZCBIdXVza29uZW4gc2VlbXMgdmVyeSBzaW1pbGFyIGRpc3RyaWJ1dGlvbnMuIA0KUHViQ2hlbSBoYXMgYSBsb3dlciBwZWFrIHRoYW4gdGhlIG90aGVyIGRhdGFzZXRzLCBidXQgbXVjaCBzaGFycGVyLiBJcyB0aGlzIHNpbXBseSBjYXVzZWQgYnkgdGhlIGRhdGFzZXQgYmVpbmcgc2lnbmlmaWNhbnRseSBsYXJnZXIgdGhhbiB0aGUgb3RoZXJzPw0KDQojU29sdWJpbGl0eSB2YWx1ZXMNCjMzIGNvbXBvdW5kcyB3aXRoIGEgTG9nUyB2YWx1ZSA+IDEgDQpBbGwgMzMgY29tcG91bmRzIGFyZSBjb250YWluZWQgd2l0aGluIHRoZSBEZWxhbmV5L0h1dXNrb25lbiBkYXRhc2V0Lg0KDQojUHViQ2hlbSBtaXNzaW5nIGNvbHVtbg0KUmUtZXhhbWluaW5nIHRoZSByYXcgZGF0YWZpbGUgb2J0YWluZWQgZnJvbSB0aGUgQVBJIHN1Z2dlc3RzIHRoYXQgYW4gaW1wb3J0YW50IGNvbHVtbiB3YXMgbWlzc2luZyBmcm9tIHRoZSBBUEkvc2NyaXB0IGZpbGUgZG93bmxvYWRlZCBmb3IgdGhlIFB1YkNoZW0gYXNzYXkuIA0KVGhlIGFzc2F5IGFjdHVhbGx5IGhhcyAzIHBvc3NpYmxlIHF1YWxpZmllZCByZXN1bHRzLCA+LCA8IG9yID0gdG8gYSB2YWx1ZSBpbiB0aGUgbmVpZ2hib3VyaW5nIGNvbHVtbi4gDQpGb3IgdGhvc2UgY29tcG91bmRzIHdoaWNoIGhhdmUgYSA9IHRoZSB2YWx1ZSBjYW4gc2ltcGx5IGJlIHVzZWQuIEhvd2V2ZXIgdGhvc2UgY29tcG91bmRzIGNvbnRhaW5pbmcgPCBvciA+IHF1YWxpZmllcnMsIHRoZSB2YWx1ZXMgY2Fubm90IHNpbXBseSBiZSB1c2VkLiBUaGV5IHNob3VsZCBpbnN0ZWFkIGJlIGV4Y2x1ZGVkLiANCg0KVGhlIGNvbW1lbnRzIG9uIHRoZSBhc3NheSBzdWdnZXN0cyB0aGF0IHRoZXJlIGlzIGFuIGV4cGVyaW1lbnRhbCB0aHJlc2hvbGQgYWJvdmUgd2hpY2ggdGhlIG1ldGhvZCBjb250YWluIG9idGFpbiBhY2N1cmF0ZSByZWFkaW5ncy4gcG9zc2libHkgNzUlIG9mIHRoZSAyMDBtaWNyb21vbGFyIGNvbXBvdW5kIGxvYWQuIENvbnZlcnNpb24gb2YgMTUwbWljcm9tb2xhciB0byBMb2dTL00gZ2l2ZXMgYSB2YWx1ZSBvZiAtMy44MjQgdGhpcyBzZWVtcyB0byBjb3JyZXNwb25kIHRvIHRoZSBwb3NpdGlvbiBvZiB0aGUgcGVhayBpbiB0aGUgTG9nUyBkaXN0cmlidXRpb24gYW5kIG1heSBiZSB0aGUgY2F1c2Ugb2YgaXQuIA0KDQpJbiBvcmRlciB0byBpZGVudGlmeSB0aGUgY29tcG91bmRzIHRoYXQgYXJlIDwgb3IgPiBpbnN0ZWFkIG9mID0gdGhlIGFzc2F5IGRhdGFzZXQgaGFzIGJlZW4gcmUtb2J0YWluZWQgd2l0aCB0aGUgYWRkaXRpb25hbCBjb2x1bW4sIGhvd2V2ZXIgdGhpcyBkb2VzIG5vdCBjb250YWluIHRoZSBzdHJ1Y3R1cmFsIGluZm9ybWF0aW9uIGNvbHVtbnMsIHNvIHRoZSB0d28gZGF0YXNldHMgbXVzdCBiZSBtZXJnZWQgdG9nZXRoZXIuIA0KDQpgYGB7cn0NClB1YkNoZW1fcXVhbGlmaWVyczwtcmVhZC5jc3YoIkM6XFxVc2Vyc1xcbmsxZzA5XFxEcm9wYm94XFxTb2x1YmlsaXR5X2NoYWxsZW5nZVxcRXhwYW5kZWRfZGF0YXNldHNcXGRhdGFfZnJvbV9hZGFtXFxQdWJDaGVtX0FJRF8xOTk2XFxBSURfMTk5Nl9xdWFsaWZpZXJzLmNzdiIpDQojcmVhZCBpbiB0aGUgZG93bmxvYWRlZCBhc3NheSBmaWxlIC0gdGhpcyBjb250YWlucyBhbGwgNTc4NTkgY29tcG91bmQgZW50cmllcy4gDQoNCiNtZXJnZSB0aGUgbmV3IGRvd25sb2FkIHdpdGggdGhlIFB1YkNoZW0gb3V0cHV0IGZpbGUgKGNvbnRhaW5pbmcgc29sdWJpbGl0eSBhcyBMb2dTL00gYW5kIE1XKSBUaGlzIHNob3VsZCBiZSBqb2luZWQgYnkgdGhlIENvbXBvdW5kX0lkZW50aWZpZXIgY29sdW1uIGFzIHRoZXNlIGFyZSB0aGUgc2FtZSBiZXR3ZWVuIHRoZSB0d28gZGF0YXNldHMsIFBVXyt0aGUgUHViQ2hlbV9DSUQgDQpQdWJDaGVtX3F1YWxpZmllZF9vdXRwdXRzPC0gbWVyZ2UoUHViQ2hlbSwgUHViQ2hlbV9xdWFsaWZpZXJzLCBieT0iQ29tcG91bmRfSWRlbnRpZmllciIgKQ0KDQpQdWJDaGVtX0dUPC1zdWJzZXQoUHViQ2hlbV9xdWFsaWZpZWRfb3V0cHV0cywgUXVhbGlmaWVyLmZvci5zb2x1YmlsaXR5PT0gIkdUIikNClB1YkNoZW1fTFQ8LXN1YnNldChQdWJDaGVtX3F1YWxpZmllZF9vdXRwdXRzLCBRdWFsaWZpZXIuZm9yLnNvbHViaWxpdHk9PSAiTFQiKQ0KUHViQ2hlbV9FcXVhbHM8LXN1YnNldChQdWJDaGVtX3F1YWxpZmllZF9vdXRwdXRzLCBRdWFsaWZpZXIuZm9yLnNvbHViaWxpdHk9PSAiRXF1YWxzIikNCg0KYGBgDQoNClRoZSBkYXRhc2V0cyBoYXZlIGJlZW4gbWVyZ2VkIGFuZCBzdWJzZXR0ZWQgb3V0IGludG8gMyBkaWZmZXJlbnQgc3Vic2V0cywgdGhvc2UgY29udGFpbmluZyA+IGFzIHRoZSBxdWFsaWZpZXIgKDE2Njk1IGNvbXBvdW5kcyksIHRob3NlIGNvbnRhaW5pbmcgPCBhcyB0aGUgcXVhbGlmaWVyICgzMDM2IGNvbXBvdW5kcykgYW5kIHRob3NlIGNvbnRhaW5pbmcgPSBhcyB0aGUgcXVhbGlmaWVyICgzNjQyMCBjb21wb3VuZHMpDQoNCmBgYHtyfQ0KaGlzdChQdWJDaGVtX0dUJExvZ1MpDQpoaXN0KFB1YkNoZW1fTFQkTG9nUykNCmhpc3QoUHViQ2hlbV9FcXVhbHMkTG9nUykNCmBgYA0KDQpUaGVyZSBzdGlsbCBhcHBlYXJzIHRvIGJlIGEgcGVhayBhdCBhcHByb3ggLTMuOCBvbiB0aGUgUHViQ2hlbV9lcXVhbHMgc3Vic2V0LiBIb3dldmVyIHRoaXMgaXMgcmVkdWNlZCBmcm9tIHRoZSBwcmV2aW91cyBwZWFrLiANCg0KYGBge3J9DQpsaWJyYXJ5KHNtKQ0KYXR0YWNoKFB1YkNoZW1fcXVhbGlmaWVkX291dHB1dHMpDQoNCiNjcmVhdGUgdmFsdWUgbGFiZWxzDQpRdWFsaWZpZXIuZm9yLnNvbHViaWxpdHkuZiA8LSBmYWN0b3IoUXVhbGlmaWVyLmZvci5zb2x1YmlsaXR5LCBsZXZlbHM9YygiTFQiLCAiRXF1YWxzIiwgIkdUIiksIGxhYmVscyA9IGMoIkxUIiwgIkVxdWFscyIsICJHVCIpKQ0KDQojcGxvdCBkZW5zaXRpZXMNCnNtLmRlbnNpdHkuY29tcGFyZShMb2dTLCBRdWFsaWZpZXIuZm9yLnNvbHViaWxpdHksIHhsYWI9IkxvZ1MiKQ0KDQojIGFkZCBsZWdlbmQNCmNvbGZpbGw8LWMoMjooMitsZW5ndGgobGV2ZWxzKFF1YWxpZmllci5mKSkpKSANCmxlZ2VuZCgidG9wcmlnaHQiLCBsZXZlbHMoUXVhbGlmaWVyLmYpLCBmaWxsPWNvbGZpbGwpDQoNCmRldGFjaChQdWJDaGVtX3F1YWxpZmllZF9vdXRwdXRzKQ0KYGBgDQoNClRoaXMgY29tcGFyZSBwbG90IGFwcGVhcnMgdG8gaGF2ZSB0aGUgZGlmZmVyZW50IHN1YnNldHMgaW5jb3JyZWN0bHkgbGFiZWxsZWQuIEFkZGl0aW9uYWxseSB0aGUgZGVuc2l0aWVzIHJlbGF0aXZlIHRvIGVhY2ggb3RoZXIgYXBwZWFyIGluY29ycmVjdC4gVGhleSBhbHNvIGFwcGVhciBkaWZmZXJlbnQgdG8gdGhlIGluZGl2aWR1YWwgcGxvdHMgZm9yIHRoZSBlcXVhbHMgZ3JvdXAgKG1hcmtlZCBhcyB0aGUgR1QgZ3JvdXAgaGVyZSkNCg0KUGxvdHRpbmcgZGVuc2l0aWVzIGZvciB0aGUgMyBzdWJzZXRzIHNlcGVyYXRlbHkgZ2l2ZXMgdGhlIGNvcnJlY3QgcG9zaXRpb25pbmcgZm9yIHRoZSBjdXJ2ZXMsIGhvd2V2ZXIgdGhlIGRlbnNpdGllcyBmb3IgdGhlIEdUIHN1YnNldCBnbyB0byBhcHByb3ggMTUwMCBidXQgdGhlIExUIHN1YnNldCBvbmx5IGdvZXMgdG8gYXBwcm94IDIuNSBhbmQgdGhlIGVxdWFscyBzdWJzZXQgYXBwcm94IDEuNS4gTG9vayBpbnRvIGhvdyB0aGUgZGVuc2l0eSBpcyBkaXNwbGF5ZWQgYXMgdGhlIGVxdWFscyBzdWJzZXQgaGFzIG92ZXIgdHdpY2UgdGhlIG51bWJlciBvZiBjb21wb3VuZHMgdGhhdCB0aGUgR1Qgc3Vic2V0IGNvbnRhaW5zLiANCg0KYGBge3J9DQpkUHViQ2hlbV9HVCA8LWRlbnNpdHkoUHViQ2hlbV9HVCRMb2dTKQ0KcGxvdChkUHViQ2hlbV9HVCkNCg0KZFB1YkNoZW1fTFQgPC1kZW5zaXR5KFB1YkNoZW1fTFQkTG9nUykNCnBsb3QoZFB1YkNoZW1fTFQpDQoNCmRQdWJDaGVtX0VxdWFscyA8LWRlbnNpdHkoUHViQ2hlbV9FcXVhbHMkTG9nUykNCnBsb3QoZFB1YkNoZW1fRXF1YWxzKQ0KYGBgDQoNCg==