{ "info": { "author": "Xiangyu Zhang, Sara Algeri", "author_email": "zhan6004@umn.edu, salgeri@umn.edu", "bugtrack_url": null, "classifiers": [ "Intended Audience :: Developers", "Intended Audience :: Education", "Intended Audience :: Information Technology", "Intended Audience :: Science/Research", "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", "Programming Language :: Python", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Topic :: Education", "Topic :: Scientific/Engineering", "Topic :: Scientific/Engineering :: Information Analysis", "Topic :: Scientific/Engineering :: Mathematics" ], "description": "# The 'LPBkg' Python package\n\nThe LPBkg package provides a Python implementation for the **detection of new signals under background mismodelling** algorithm, proposed in **S. Algeri, 2019**. The algorithm implements a unified statistical strategy to perform modeling, estimation, inference, and signal characterization under background mismodeling. The methodology proposed in **S. Algeri, 2019** allows to incorporate the (partial) scientific knowledge available on the background distribution and provides a data-updated version of it in a **purely nonparametric fashion** without requiring the specification of prior distributions.\n\nFurther details and theory about the algorithm can be found in the **\"Detecting new signals under background mismodelling\",** [[arXiv:1906.06615](https://arxiv.org/pdf/1906.06615.pdf)].\n\nFor more technical problems, please contact the author of thepackage Xiangyu Zhang at zhan6004@umn.edu.\n\nFor more theoretical references, please contact the author of the paper Sara Algeri at salgeri@umn.edu.\n\n## A quick Setup Guide\n\n### Getting Started \n\n#### 1. Install the LPBkg package using pip\n```bash\npython -m pip install LPBkg\n```\n#### 2. Loading packages and main functions\n```python\nfrom LPBkg.detc import BestM, dhatL2\n```\n\n## Tutorial and Examples\n\nNow everything is ready to start our analysis. We consider the Fermi-LAT example described in Section VI of the manuscript **Algeri, 2019**.\n\nThe data files are available in the folder [[data](https://drive.google.com/open?id=1FYfqDpo4O-CHqVMOaQsTcTu9fbFeca62)] and can be loaded as follows:\n\n```python\nimport numpy as np\nfrom scipy import stats\nimport seaborn as sns\nimport matplotlib.pyplot as plt\n\n# You can change to your own path to find these txt files respectively.\nca=np.loadtxt('D:\\\\data\\\\source_free.txt',dtype=str)[:,1:].astype(float)\nbk=np.loadtxt('D:\\\\data\\\\background.txt',dtype=str)[:,1:].astype(float)\nsi=np.loadtxt('D:\\\\data\\\\signal.txt',dtype=str)[:,1:].astype(float)\n```\n\nTo make these data matrix become numpy arrays for further use, we could reshape them as follows:\n```python\ncal=ca.reshape(1,len(ca))[0]\nbkg=bk.reshape(1,len(bk))[0]\nsig=si.reshape(1,len(si))[0]\n```\n\nNow, we have stored our source-free sample into the object **cal**, whereas our background and signal physics samples are stored in the objects **bkg** and **sig**, respectively.\nWe can check the number of observations in each sample and plot their histograms and kernel density estimation as follows:\n\n```python\nlen(cal)\nlen(bkg)\nlen(sig)\nsns.distplot(cal, kde=True, norm_hist= True)\nsns.distplot(bkg, kde=True, norm_hist= True)\nsns.distplot(sig, kde=True, norm_hist= True)\n```\n\n\n## Background calibration\n\nNow we fit the source free data with a power-law (also known as Pareto type I) over the range [1,35]. This is going to be our postulated background model g_b.\n\n```python\n#This is -loglikelihhod:\ndef mll(d, y): \n return -np.sum(np.log(stats.pareto.pdf(y,1,d)/stats.pareto.cdf(35,1,d)))\n\ndef powerlaw(y):\n return stats.pareto.pdf(y,1.3590681192057597,scale=1)/stats.pareto.cdf(35,1.3590681192057597,scale=1)\n\n# where the value 1.3590681192057597 is calculated by minimizing function mil with respect to the parameter ''d'' using ''Brent optimization''\n```\n\nLet's check how our postulated model fits the data\n\n```python\nfig, ax = plt.subplots(figsize=(14, 7))\nax=sns.distplot(cal, kde=False, norm_hist= True)\nuu=np.arange(min(cal),max(cal),0.05)\nax.plot(uu,powerlaw(uu),color='red',linestyle='dashed')\nax.set_xbound(lower=1,upper=15)\nax.set_ybound(lower=0, upper=0.8)\nax.figure\n```\n\nIn order to assess if g_b is a good model for our background distribution, we proceed considering our comparison-density estimator and respective inference. \n\n## Choice of M\n\nFirst of all, we can select a suitable value of **M** (i.e., the number of polynomial terms which will contribute to our estimator) by means of the function **bestM**, i.e.,\n```python\nBestM(data,g, Mmax=20,rg=[-10**7,10**7])\n```\nThe arguments for this function are the following:\n- **data**: the data vector in the original scale. This corresponds to the source-free sample in the background calibration phase and to the physics sample in the signal search phase.\n- **g**: the postulated model from which we want to assess if deviations occur.\n- **Mmax**: the maximum size of the polynomial basis from which a suitable value **M** is selected (the default is **20**).\n- **rg**: the range of the data considered. This corresponds to the interval on which the search is conducted.\n\nLet's now see what we obtain when applying this function to our source-free sample, while considering our fitted powerlaw as the postulated background model.\n\n```python\nBestM(data=cal,g=powerlaw, Mmax=20,rg=[1,35])\n```\nThe largest significance is achieved at **M=4** with a p-value of 9.383e-59.\n\n## CD-plots and deviance tests\nWe can now proceed constructing our CD-plot and deviance test by means of the function **dhatL2** below:\n```python\ndhatL2(data,g, M=6, Mmax=1,smooth=FALSE,criterion=\"AIC\",\n hist.u=TRUE,breaks=20,ylim=[0, 2.5],rg=[-10**7, 10**7],sigma=2)\n```\n\nThe arguments for this function are the following:\n- **data**: the data vector in the original scale. This corresponds to the source-free sample in the background calibration phase and to the physics sample in the signal search phase.\n- **g**: the postulated model from which we want to assess if deviations occur.\n- **M**: the size of the basis for the full solution, i.e., the estimator d^(u;G,F).\n- **Mmax**: the maximum size of the polynomial basis from which **M** was selected. The default is **20**.\n- **smooth**: a logical argument indicating if a denoising process has to be implemented. The default is **FALSE**, meaning that the full solution should be implemented.\n- **criterion**: if **smooth=TRUE**, the criterion with respect to which the denoising process should be implemented (the two possibilities are **\"AIC\" or \"BIC\"**).\n- **hist_u**: a logical argument indicating if the CD-plot should be displayed or not. The default is **TRUE**.\n- **breaks**: if **hist_u is TRUE**, the number of breaks of the CD-plot. The default is **20**.\n- **ylim**: if **hist_u is TRUE**, the range of the y-axis of the CD-plot.\n- **rg**: range of the data considered. This corresponds to the interval on which the search is conducted.\n- **sigma**: the significance level at which the confidence bands should be constructed. Notice that if **Mmax>1** or **smooth=TRUE**, Bonferroni's correction is automatically implemented. The default value of sigma is **2**.\n\nLet's now see what we get when applying this function to our source-free sample. We consider the full solution (i.e., we do not apply any denoising criterion), but we must specify that the selected value **Mmax=4** was choosen from a pool of **M=20** candidates.\n```python\ncomp = dhatL2(data=cal,g=powerlaw, M=4, Mmax=20, smooth=False, hist_u=True, breaks=20,ylim=[0,2.5],rg=[1,35],sigma=2)\n```\n\nNow let's take a look at the values contained in the **comp.density** object. We can extract the value of the deviance test statistics, its unadjusted and adjusted p-values using the following instructions:\n```python\ncomp['Deviance']\ncomp.density['Dev_pvalue']\ncomp.density['Dev_adj_pvalue']\n```\nFurthermore, we can create new functions corresponding to the estimated comparison density in both u and x scale and plot them in order to understand where the most prominent departures occur.\n\n```python\n# Estimated comparison density in u scale.\nfig, ax = plt.subplots(figsize=(14, 7))\nu=np.arange(0, 1, 0.001)\ndhat=np.zeros(len(u))\nfor i in range(len(u)):\n dhat[i] = comp['dhat'](u[i])\nax.plot(u,dhat,color='dodgerblue')\nax.set_xbound(lower=0,upper=1)\nax.set_ybound(lower=0.6, upper=1.1)\nax.set_xlabel('u', size=15)\nax.set_ylabel('Comparision density', size=15)\nax.set_title('Comparison density on u scale', size=20)\nax.figure\n```\n\n```python\n# Estimated comparison density in x scale.\nfig, ax = plt.subplots(figsize=(14, 7))\nu=np.arange(min(cal),max(cal),0.05)\ndhat_x= np.zeros(len(u))\nfor i in range(len(u)):\n dhat_x[i] = comp['dhat_x'](u[i])\nax.plot(u,dhat_x,color='dodgerblue')\nax.set_xbound(lower=0,upper=36)\nax.set_ybound(lower=0.6, upper=1.1)\nax.set_xlabel('x', size=15)\nax.set_ylabel('Comparision density', size=15)\nax.set_title('Comparison density on x scale', size=20)\nax.figure\n```\n\nSimilarly, we can define a new function corresponding to the estimate of f_b(x) and see how its fit compares to the histogram of the data.\n```python\nfig, ax = plt.subplots(figsize=(14, 7))\nfb_hat = comp['f']\nax=sns.distplot(cal,bins=30,kde=False,norm_hist=True)\nxx=np.arange(min(cal),max(cal),0.05)\nfbhat= np.zeros(len(xx))\nfor i in range(len(xx)):\n fbhat[i] = fb_hat(xx[i])\nax.set_xbound(lower=1, upper=35)\nax.plot(xx,fbhat,color='dodgerblue')\nax.set_xlabel('x')\nax.set_ylabel('Density')\nax.set_title('Source free sample and calibrated background density')\nax.figure\n```\n\nThere are several other values and function which are generated by the dhatL2 function and are summarized below. To extract them, it is sufficient to use the **['their name']** symbol.(e.g., **comp['f']**, **comp['u']**, etc. ).\n\n- **Deviance**: value of the deviance test statistic.\n- **Dev_pvalue**: unadjusted p-value of the deviance test. \n- **Dev_adj_pvalue**: adjusted p-values of the deviance test. If **smooth=FALSE**, it is computed as in formula (19) in **Algeri (2019)**. If smooth=TRUE, it is computed as in formula (28) in **Algeri (2019)**. \n- **kstar**: number of coefficients selected by the denoising process. If **smooth=FALSE** returns **kstar=M**.\n- **dhat**: function corresponding to the estimated comparison density in u scale.\n- **dhat_x**: function corresponding to the estimated comparison density in x scale.\n- **SE**: function corresponding to the estimated standard errors of the comparison density in u scale.\n- **LBf1**: function corresponding to the lower bound of the confidence bands under H_0 in u scale.\n- **UBf1**: function corresponding to the upper bound of the confidence bands under H_0 in u scale.\n- **f**: function corresponding to the estimated density of the data and obtained as in equation (10)\nin **Algeri (2019)**.\n- **u**: values u_i=G(x_i),with i=1,...,n, on which the comparison density has been estimated.\n- **LP**: estimates of the LP_j coefficients. If **smooth=TRUE**, non-zero values correspond to the k^M estimates in the denoised solution d^(u;G,F)\n- **G**: cumulative density function of the postulated model specified in the argument **g**.\n\n\n## Signal search\n\nWe can assess if our physics sample provides evidence in favor of the signal using again the functions **bestM** and **dhatL2**. \n\nBelow we work on the signal sample and we compare its distribution with the background distribution calibrated as describe in the previous section and which we called fb_hat. This is the equivalent of f^_b(x) in (14) of **Algeri (2019)**. \n\n```python\nfb_hat=comp['f']\nfig, ax = plt.subplots(figsize=(14, 7))\nax=sns.distplot(cal,bins=30,kde=False,norm_hist=True)\nxx=np.arange(min(sig),max(sig),0.05)\nfbhat= np.zeros(len(xx))\nfor i in range(len(xx)):\n fbhat[i] = fb_hat(xx[i])\nax.set_xbound(lower=1, upper=35)\nax.plot(xx,fbhat,color='mediumpurple')\nax.set_xlabel('x')\nax.set_ylabel('Density')\nax.set_title('Physics signal sample and calibrated background density')\nax.figure\n```\n\nWe select the value **M** which leads to the strongest significance. Notice that now we must specify fb_hat in the argument **g**.\n```python\nBestM(data=sig,g=fb_hat, Mmax=20, rg=[1,35])\n```\nThe selection process based on the deviance test suggests **M=3**, which we now use to estimate the comparison density using the **dhatL2** function.\n\n```python\ncomp_sig=dhatL2(data=sig,g=fb_hat, M=3, Mmax=20, smooth=False,hist_u=True,\n breaks=20,ylim=[0,2.5],rg=[1,35],sigma=2)\nadjusted_pvalue=comp_sig['Dev_adj_pvalue']\n#To convert the p-value in terms of sigma significance\nsigma_significance=np.abs(stats.norm.ppf(adjusted_pvalue, 0, 1))\nadjusted_pvalue\nsigma_significance\n```\nThe CD-plot and the deviance test suggest that a signal is present in the region [2, 3.5] with 3.317 sigma significance.\n\nWe can further explore the comparison density by plotting it on the x-domain and focusing on the [1,5] region. \n```python\nfig, ax = plt.subplots(figsize=(14, 7))\nu=np.arange(min(sig),max(sig),0.05)\ndhat_x= np.zeros(len(u))\nfor i in range(len(u)):\n dhat_x[i] = comp_sig['dhat_x'](u[i])\nax.plot(u,dhat_x,color='dodgerblue')\nax.set_xbound(lower=1,upper=5)\nax.set_ybound(lower=0.6, upper=1.6)\nax.set_xlabel('x', size=15)\nax.set_ylabel('d^(G(x), G, F)', size=15)\nax.set_title('Comparison density on X-scale', size=20)\nax.figure\n```\n\nIt seems like the signal is concentrated between 2 and 3.\n\nFurthermore, we can try repeating the same analysis with a larger basis, say M=6. Here we can set Mmax=1 since we are not doing any model selection, we are just picking M=6.\n```python\ncomp_sig2=dhatL2(data=sig,g=fb_hat, M=6, Mmax=1, smooth=False,hist_u=True,\n breaks=20,ylim=[0,2.5],rg=[1,35],sigma=2)\ncomp_sig2['Dev_adj_pvalue']\npvalue2=comp_sig2['Dev_pvalue']\nsigma_significance2=np.abs(stats.norm.ppf(pvalue2, 0, 1))\npvalue2\nsigma_significance2\n\n```\nSince no selection process was considered, no adjusted p-value is returned and the unjusted p-value leads to a\n3.745 sigma significance. This is larger than the one we obtained before, but we somehow cheated as we have ignored the selection process!\nNotice that, that despite no correction was applied the confidence bands are much larger than before but the estimated comparison density is somehow more concentrated around u=0.7. That is simply because a larger basis leads to a reduction of the bias and an increment of the variance. But what do we get if we implement a denoising process?\nTo do so we only need to specify **smooth=TRUE** and select a denoising criterion between AIC or BIC. Just for the sake of consistency with **Algeri (2019)**, we choose the AIC criterion.\n\n```python\ncomp_sig3=dhatL2(data=sig,g=fb_hat, M=6, Mmax=1, smooth=True,\n method=\"AIC\",hist_u=True,breaks=20,\n ylim=[0,2.5],rg=[1,35],sigma=2)\ncomp_sig3['kstar']\nadjusted_pvalue3=comp_sig3['Dev_adj_pvalue']\nsigma_significance3=np.abs(stats.norm.ppf(adjusted_pvalue3, 0, 1))\nadjusted_pvalue3\nsigma_significance3\n```\nBy definition the denoising process implies that a selction has been made so we do have an adjusted p-value.\nNotice that out of the initial **M=6** estimates only **kstar_6=4** for of them contribute to the estimator d^\\*(u;G,F) plotted above. The estimate of the comparison density does not show any substantial difference compared with the full solution\nd^(u;G,F). However, the significance of the deviance test has reduced (3.520sigma).\n\n## References\n\nAlgeri S. (2019). Detecting new signals under background mismodelling. [[arXiv:1906.06615](https://arxiv.org/pdf/1906.06615.pdf)]\n\n## License\n\nThe software is subjected to the GNU GPLv3 licensing terms and agreements.\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/Yorkee2018/LPBkg/tree/master/python", "keywords": "", "license": "GNU GPLv3", "maintainer": "", "maintainer_email": "", "name": "LPBkg", "package_url": "https://pypi.org/project/LPBkg/", "platform": "", "project_url": "https://pypi.org/project/LPBkg/", "project_urls": { "Homepage": "https://github.com/Yorkee2018/LPBkg/tree/master/python" }, "release_url": "https://pypi.org/project/LPBkg/0.1.2/", "requires_dist": [ "numpy", "sympy", "scipy", "matplotlib", "seaborn" ], "requires_python": "", "summary": "Detecting new signals under background mismodelling.", "version": "0.1.2" }, "last_serial": 5812107, "releases": { "0.0.1": [ { "comment_text": "", "digests": { "md5": "36906feba961851bbd3a7ed1dbbcda9e", "sha256": "d480d09930dfdd883380894e9993dc6eb33f470933021d7ae4fd3a91afaf3000" }, "downloads": -1, "filename": "LPBkg-0.0.1-py2-none-any.whl", "has_sig": false, "md5_digest": "36906feba961851bbd3a7ed1dbbcda9e", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 25375, "upload_time": "2019-09-05T14:52:50", "url": "https://files.pythonhosted.org/packages/3c/5d/e772c4d6dc13fdc64e169315e80e98efb24985161b869ead41590d8b9751/LPBkg-0.0.1-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "700e9f366b393e9cd3d0ebc31de6b75c", "sha256": "49ff73243c4f6ac36076bbd6fb1cdc440dc0207332495da8983b2acba0487688" }, "downloads": -1, "filename": "LPBkg-0.0.1.tar.gz", "has_sig": false, "md5_digest": "700e9f366b393e9cd3d0ebc31de6b75c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17810, "upload_time": "2019-09-05T14:52:52", "url": "https://files.pythonhosted.org/packages/b2/2a/40790fe9010d2b0faaa464b933779d780f1b8bd80b9985c925db026e629c/LPBkg-0.0.1.tar.gz" } ], "0.1.0": [ { "comment_text": "", "digests": { "md5": "94d2f5c259090fcbbec1bbc2a2929d6b", "sha256": "7fecd7a2b9110b15a8ba69397c3c2adb3d6dc2144ea9e18fb516caf15b107cd8" }, "downloads": -1, "filename": "LPBkg-0.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "94d2f5c259090fcbbec1bbc2a2929d6b", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 25449, "upload_time": "2019-09-06T03:15:51", "url": "https://files.pythonhosted.org/packages/2f/70/b375be5215b88a48301f7d9c0c3714754ea729519f70a233421e81ccbca8/LPBkg-0.1.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "77b6db4c18ce453634e165222ae2d363", "sha256": "f19d79dc8ea9efd69fe95a05d6f78103b82da1bae2ca994a52afe4051254064f" }, "downloads": -1, "filename": "LPBkg-0.1.0.tar.gz", "has_sig": false, "md5_digest": "77b6db4c18ce453634e165222ae2d363", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13637, "upload_time": "2019-09-06T03:15:53", "url": "https://files.pythonhosted.org/packages/71/5b/e3469494cf6966a16d316a96ae3a118a68d02bb9d5194f292bd2489fb5cb/LPBkg-0.1.0.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "318b5a17147fc81b13cfc9ff85e0c61e", "sha256": "5b3ee09d6f86ebe6c61303f4baab29554c26031d781ea4c8bb7cefc453827035" }, "downloads": -1, "filename": "LPBkg-0.1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "318b5a17147fc81b13cfc9ff85e0c61e", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 25425, "upload_time": "2019-09-06T03:20:55", "url": "https://files.pythonhosted.org/packages/e5/48/682010a182a95dca3cf655876b8ccd24b474516d3ddab5d0c7501117c7a7/LPBkg-0.1.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "aa006e3501ea8b4e4e6539c330df2c01", "sha256": "7e12dc4291756f5e96d714fec8eaa9dd8df51d3e18903a82acfde6666bf80825" }, "downloads": -1, "filename": "LPBkg-0.1.1.tar.gz", "has_sig": false, "md5_digest": "aa006e3501ea8b4e4e6539c330df2c01", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13545, "upload_time": "2019-09-06T03:20:57", "url": "https://files.pythonhosted.org/packages/f4/f5/1d73ded726aa277e384ec9596e3af0bd8558a89af55ff94dd748506e0548/LPBkg-0.1.1.tar.gz" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "8ab68478e76f13b8a3516ce9987a8ba4", "sha256": "c9b572035c3922a9afa8f85d8d9ab0e24dac171816afe38699dceb8ea563d96e" }, "downloads": -1, "filename": "LPBkg-0.1.2-py3-none-any.whl", "has_sig": false, "md5_digest": "8ab68478e76f13b8a3516ce9987a8ba4", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 25444, "upload_time": "2019-09-11T00:28:09", "url": "https://files.pythonhosted.org/packages/1c/08/df3a9406ae1ce4f725230ee6d9ca9bcad72bcaba73952c63a7c775d5c3a2/LPBkg-0.1.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ec9a012c5dc38bffc6d0d3ba5c2ce545", "sha256": "b75554dfa2621e3b817d98baba25cee892cd0eaab47f14be3db98f00b8f2620c" }, "downloads": -1, "filename": "LPBkg-0.1.2.tar.gz", "has_sig": false, "md5_digest": "ec9a012c5dc38bffc6d0d3ba5c2ce545", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13551, "upload_time": "2019-09-11T00:28:11", "url": "https://files.pythonhosted.org/packages/bc/22/ae7d2ec23ebd9d0051dd214abe3475753516ae38d6d3d5fb63e136ad763b/LPBkg-0.1.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "8ab68478e76f13b8a3516ce9987a8ba4", "sha256": "c9b572035c3922a9afa8f85d8d9ab0e24dac171816afe38699dceb8ea563d96e" }, "downloads": -1, "filename": "LPBkg-0.1.2-py3-none-any.whl", "has_sig": false, "md5_digest": "8ab68478e76f13b8a3516ce9987a8ba4", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 25444, "upload_time": "2019-09-11T00:28:09", "url": "https://files.pythonhosted.org/packages/1c/08/df3a9406ae1ce4f725230ee6d9ca9bcad72bcaba73952c63a7c775d5c3a2/LPBkg-0.1.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ec9a012c5dc38bffc6d0d3ba5c2ce545", "sha256": "b75554dfa2621e3b817d98baba25cee892cd0eaab47f14be3db98f00b8f2620c" }, "downloads": -1, "filename": "LPBkg-0.1.2.tar.gz", "has_sig": false, "md5_digest": "ec9a012c5dc38bffc6d0d3ba5c2ce545", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13551, "upload_time": "2019-09-11T00:28:11", "url": "https://files.pythonhosted.org/packages/bc/22/ae7d2ec23ebd9d0051dd214abe3475753516ae38d6d3d5fb63e136ad763b/LPBkg-0.1.2.tar.gz" } ] }