{ "info": { "author": "Jason L Weirather", "author_email": "jason.weirather@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Intended Audience :: Science/Research", "License :: OSI Approved :: Apache Software License", "Topic :: Scientific/Engineering :: Bio-Informatics" ], "description": "# pythologist\n\n*Read and analyze cell image data.*\n\n## Intro\n\nPythologist 1) reads exports from InForm software or other sources into a common storage format, and 2) extracts basic analysis features from cell image data. This software is generally intended to be run from a jupyter notebook and provides hooks into the image data so that the user can have the flexability to execute analyses they design or find in the primary literature.\n\n[List of large-scale image analysis publications](https://github.com/jason-weirather/pythologist/wiki/list-of-large-scale-image-analysis-publications)\n\n\nPythologist is based on [**IrisSpatialFeatures**](https://github.com/gusef/IrisSpatialFeatures) (C.D. Carey, ,D. Gusenleitner, M. Lipshitz, et al. Blood. 2017) https://doi.org/10.1182/blood-2017-03-770719, and is implemented in the python programming language. \n\nFeatures Pythologist add are:\n\n* An common CellProjectGeneric storage class, and classical inheritance conventions to organize the importation of different data types.\n* A mutable CellDataFrame class that can be used for slicing, and combining projects.\n* The ability to add binary features to cells based on cell-cell contacts or cell proximity.\n* Customizable images based on the cell segmentation or heatmaps spaninng the cartesian coordinates.\n* Specify cell populations through a SubsetLogic syntax for quick selection of mutually exclusive phenotypes or binary features\n* A set of Quality Check functions to identify potential issues in imported data.\n\n## Module documentation\n\n* `pythologist` CellDataFrame class to modify and execute analysses [[Read the Docs](https://jason-weirather.github.io/pythologist/#modules)] [[source](https://github.com/jason-weirather/pythologist)]\n* `pythologist-reader` CellProject Storage Object [[Read the Docs](https://jason-weirather.github.io/pythologist-reader/)] [[source](https://github.com/jason-weirather/pythologist-reader)]\n* `pythologist-test-images` Example data [[source](https://github.com/jason-weirather/pythologist-test-images)]\n* `pythologist-image-utilities` Helper functions to work with images [[Read the Docs](https://jason-weirather.github.io/pythologist-image-utilities/)] [[source](https://github.com/jason-weirather/pythologist-image-utilities)] \n\n# Quickstart\n\nTo start a jupyter lab notebook with the required software as your user in your current drectory you can use the following command \n\n`docker run --rm -p 8888:8888 --user $(id -u):$(id -g) -v $(pwd):/work vacation/pythologist:latest`\n\nThis will start jupyter lab on port 8888 as your user and group. \n\nAny of the test data examples should work fine in this environment.\n\n# Installation\n\n## Docker jupyter labs quickstart\n\nTo start a jupyter notebook in the current working directory on port 8885 you can use the following docker command.\n\n**First build a docker image that will use your own user/group name and id.**\n\n```\n$ docker build -t pythologist:latest --build-arg user=$USERNAME \\\n --build-arg group=$GROUPNAME \\\n --build-arg user_id=$USERID \\\n --build-arg group_id=$GROUPID .\n```\n\n**Now start the docker image.**\n\n```\n$ docker run --rm -p 8885:8888 -v $(pwd):/home/$USERNAME/work pythologist:latest\n```\n\nwhere `$USERNAME`, `$GROUPNAME`, `$USERID`, `$GROUPID` correspond to your user/group name/id.\n\n## Install by pip\n\n```\n$ pip install pythologist\n```\n\n# Common tasks\n\n### Reading in a project composed of InForm exports\n\n#### Basic\n\nThe assumption here is that the exports are grouped so that sample folders contain one or more image exports, and that sample name can be inferred from the last folder name.\n\n```python\nfrom pythologist_test_images import TestImages\nfrom pythologist_reader.formats.inform.sets import CellProjectInForm\nimport matplotlib.pyplot as plt\n\n# Get the path of the test dataset\npath = TestImages().raw('IrisSpatialFeatures')\n# Create the storage opbject where the project will be saved\ncpi = CellProjectInForm('pythologist.h5',mode='w')\n# Read the project data\ncpi.read_path(path,require=False,verbose=True,microns_per_pixel=0.496,sample_name_index=-1)\n# Display one of the cell map images\nfor f in cpi.frame_iter():\n break\nprint(f.frame_name)\nplt.imshow(f.cell_map_image(),origin='upper')\nplt.show()\n```\n\n> MEL2_7\n>\n> ![MEL2_7_cell_map](https://github.com/jason-weirather/pythologist/blob/master/images/MEL2_7_cell_map.png?raw=true)\n\n#### Custom region annotations from tumor and invasive margin image drawings\n\nAnother format supported for a project import is one with a custom tumor and invasive margin definition. Similar to above, the project is organized into sample folders, and each image within each sample folder has a *tif* file defining the tumor and invasive margin. These come in the form of a `_Tumor.tif` and `_Invasive_Margin.tif` for each image. The `_Tumor.tif` is an area filled in where the tumor is, and transparent elsewhere. The `_Invasive_Margin.tif` is a drawn line of a known width. `steps` is used to grow the margin out that many pixels in each direction to establish an invasive margin region. Here we also rename some markers during read-in to clean up the syntax of thresholding on binary features.\n\n\n```python\nfrom pythologist_test_images import TestImages\nfrom pythologist_reader.formats.inform.custom import CellProjectInFormLineArea\n\n# Get the path of the test dataset\npath = TestImages().raw('IrisSpatialFeatures')\n# Specify where the data read-in will be stored as an h5 object\ncpi = CellProjectInFormLineArea('test.h5',mode='w')\n# Read in the data (gets stored on the fly into the h5 object)\ncpi.read_path(path,\n sample_name_index=-1,\n verbose=True,\n steps=76,\n project_name='IrisSpatialFeatures',\n microns_per_pixel=0.496)\nfor f in cpi.frame_iter():\n break\nprint(f.frame_name)\nprint('hand drawn margin')\nplt.imshow(f.get_image(f.get_data('custom_images').\\\n set_index('custom_label').loc['Drawn','image_id']),origin='upper')\nplt.show()\nprint('hand drawn tumor area')\nplt.imshow(f.get_image(f.get_data('custom_images').\\\n set_index('custom_label').loc['Area','image_id']),origin='upper')\nplt.show()\nprint('Mutually exclusive Margin, Tumor, and Stroma')\nplt.imshow(f.get_image(f.get_data('regions').\\\n set_index('region_label').loc['Margin','image_id']),origin='upper')\nplt.show()\nplt.imshow(f.get_image(f.get_data('regions').\\\n set_index('region_label').loc['Tumor','image_id']),origin='upper')\nplt.show()\nplt.imshow(f.get_image(f.get_data('regions').\\\n set_index('region_label').loc['Stroma','image_id']),origin='upper')\nplt.show()\n``` \n> MEL2_2\n>\n> hand drawn margin\n>\n> ![MEL2_2_drawn_line](https://github.com/jason-weirather/pythologist/blob/master/images/MEL2_2_drawn.png?raw=true)\n>\n> hand drawn tumor area\n>\n> ![MEL2_2_drawn_line](https://github.com/jason-weirather/pythologist/blob/master/images/MEL2_2_area.png?raw=true)\n>\n> Mutually exclusive Margin, Tumor, and Stroma\n>\n> ![MEL2_2_margin](https://github.com/jason-weirather/pythologist/blob/master/images/MEL2_2_Margin.png?raw=true)\n> ![MEL2_2_tumor](https://github.com/jason-weirather/pythologist/blob/master/images/MEL2_2_Tumor.png?raw=true)\n> ![MEL2_2_stroma](https://github.com/jason-weirather/pythologist/blob/master/images/MEL2_2_Stroma.png?raw=true)\n\n\n### Read a project with a custom tumor mask (but no margin line)\n\nHere we will use the mask, but not expand or subtract from it.\n\n```python\nfrom pythologist_test_images import TestImages\nfrom pythologist_reader.formats.inform.custom import CellProjectInFormCustomMask\nimport matplotlib.pyplot as plt\npath = TestImages().raw('IrisSpatialFeatures')\ncpi = CellProjectInFormCustomMask('test.h5',mode='w')\ncpi.read_path(path,\n microns_per_pixel=0.496,\n sample_name_index=-1,\n verbose=True,\n custom_mask_name='Tumor',\n other_mask_name='Not-Tumor')\nfor f in cpi.frame_iter():\n rs = f.get_data('regions').set_index('region_label')\n for r in rs.index:\n print(r)\n plt.imshow(f.get_image(rs.loc[r]['image_id']),origin='upper')\n plt.show()\n break\n```\n> MEL2_2\n>\n> Tumor\n>\n> ![MEL2_2_tumor](https://github.com/jason-weirather/pythologist/blob/master/images/MEL2_2_tumor-b.png?raw=true)\n> \n> Not-Tumor\n>\n> ![MEL2_2_not_tumor](https://github.com/jason-weirather/pythologist/blob/master/images/MEL2_2_not-tumor-b.png?raw=true) \n\n### Quality check samples\n\nCheck general status of the CellDataFrame\n\n```python\ncdf = cpi.cdf\ncdf.db = cpi\ncdf.qc(verbose=True).print_results()\n```\n\n*prints the following QC metrics to stdout*\n\n```\n==========\nCheck microns per pixel attribute\nPASS\nMicrons per pixel is 0.496\n==========\nCheck storage object is set\nPASS\nh5 object is set\n==========\nIs there a 1:1 correspondence between sample_name and sample_id?\nPASS\nGood concordance.\nIssue count: 0/2\n==========\nIs there a 1:1 correspondence between frame_name and frame_id?\nPASS\nGood concordance.\nIssue count: 0/4\n==========\nIs there a 1:1 correspondence between project_name and project_id?\nPASS\nGood concordance.\nIssue count: 0/1\n==========\nIs the same frame name present in multiple samples?\nPASS\nframe_name's are all in their own samples\nIssue count: 0/4\n==========\nAre the same phenotypes listed and following rules for mutual exclusion?\nPASS\nphenotype_calls and phenotype_label follows expected rules\n==========\nAre the same phenotypes included on all images?\nPASS\nConsistent phenotypes\nIssue count: 0/4\n==========\nAre the same scored names included on all images?\nPASS\nConsistent scored_names\nIssue count: 0/4\n==========\nAre the same regions represented the same with an image and across images?\nPASS\nConsistent regions\nIssue count: 0/5\n==========\nAre the same regions listed matching a valid region_label\nPASS\nregions and region_label follows expected rules\n==========\nDo we have any region sizes so small they should consider being excluded?\nWARNING\n[\n \"Very small non-zero regions are included in the data['IrisSpatialFeatures', 'MEL2', 'MEL2_7', {'Margin': 495640, 'Tumor': 947369, 'Stroma': 116}]\"\n]\nIssue count: 1/2\n```\n\n### View density plots based on cell phenotype frequencies. \n\nThe cell phenotypes set prior to calling `cartesian` are the phenotypes available to plot.\n\n```python\nfrom pythologist_test_images import TestImages\nfrom plotnine import *\nproj = TestImages().project('IrisSpatialFeatures')\ncdf = TestImages().celldataframe('IrisSpatialFeatures')\ncdf.db = proj\ncart = cdf.cartesian(verbose=True,step_pixels=50,max_distance_pixels=75)\ndf,cols = cart.rgb_dataframe(red='CD8+',green='SOX10+')\nshape = cdf.iloc[0]['frame_shape']\n(ggplot(df,aes(x='frame_x',y='frame_y',fill='color_str'))\n + geom_point(shape='h',size=4.5,color='#777777',stroke=0.2)\n + geom_vline(xintercept=-1,color=\"#555555\")\n + geom_vline(xintercept=shape[1],color=\"#555555\")\n + geom_hline(yintercept=-1,color=\"#555555\")\n + geom_hline(yintercept=shape[0],color=\"#555555\")\n + facet_wrap('frame_name')\n + scale_fill_manual(cols,guide=False)\n + theme_bw()\n + theme(figure_size=(8,8))\n + theme(aspect_ratio=shape[0]/shape[1])\n + scale_y_reverse()\n)\n```\n\n> ![Density Example](https://github.com/jason-weirather/pythologist/blob/master/images/density_plots.png?raw=true)\n\n\n### View histograms of pixel intensity and the scoring of binary markers on each image\n\n```python\nfrom pythologist_test_images import TestImages\nfrom plotnine import *\nproj = TestImages().project('IrisSpatialFeatures')\ncdf = TestImages().celldataframe('IrisSpatialFeatures')\ncdf.db = proj\nch = cdf.db.qc().channel_histograms()\nsub = ch.loc[(~ch['threshold_value'].isna())&(ch['channel_label']=='PDL1')]\n(ggplot(sub,aes(x='bins',y='counts'))\n + geom_bar(stat='identity')\n + facet_wrap('frame_name')\n + geom_vline(aes(xintercept='threshold_value'),color='red')\n + theme_bw()\n + ggtitle('Thresholding of PDL1\\ngiven image pixel intensities')\n)\n```\n\n*The original component images were not available for IrisSpatialFeatures example, so pixel intensities are simulated and don't necessarily match the those which would have been used to set the original threshold values.*\n\n> ![Histogram Example](https://github.com/jason-weirather/pythologist/blob/master/images/histogram_example.png?raw=true)\n\n### View cell-cell contacts\n\n```python\nfrom pythologist_test_images import TestImages\nfrom pythologist_reader.formats.inform.custom import CellProjectInFormCustomMask\nfrom pythologist import SubsetLogic as SL\ncpi = TestImages().project('IrisSpatialFeatures')\ncdf = cpi.cdf\ncdf.db = cpi\nsub = cdf.loc[cdf['frame_name']=='MEL2_7'].dropna()\ncont = sub.contacts().threshold('CD8+','CD8+/contact').contacts().threshold('SOX10+','SOX10+/contact')\ncont = cont.threshold('CD8+','SOX10+/contact',\n positive_label='CD8+ contact',\n negative_label='CD8+').\\\n threshold('SOX10+','CD8+/contact',\n positive_label='SOX10+ contact',\n negative_label='SOX10+')\nschema = [\n {'subset_logic':SL(phenotypes=['OTHER']),\n 'edge_color':(50,50,50,255),\n 'watershed_steps':0,\n 'fill_color':(0,0,0,255)\n },\n {'subset_logic':SL(phenotypes=['SOX10+']),\n 'edge_color':(166,206,227,255),\n 'watershed_steps':0,\n 'fill_color':(0,0,0,0)\n },\n {'subset_logic':SL(phenotypes=['CD8+']),\n 'edge_color':(253,191,111,255),\n 'watershed_steps':0,\n 'fill_color':(0,0,0,0)\n },\n {'subset_logic':SL(phenotypes=['CD8+ contact']),\n 'edge_color':(253,191,111,255),\n 'watershed_steps':0,\n 'fill_color':(255,127,0,255)\n },\n {'subset_logic':SL(phenotypes=['SOX10+ contact']),\n 'edge_color':(166,206,227,255),\n 'watershed_steps':0,\n 'fill_color':(31,120,180,255)\n }\n]\nsio = cont.segmentation_images().build_segmentation_image(schema,background=(0,0,0,255))\nsio.write_to_path('test_edges',overwrite=True)\n```\n\n> MEL2_7\n>\n> ![Visualize Contacts](https://github.com/jason-weirather/pythologist/blob/master/images/MEL2_7-contacts.png?raw=true)\n\n*Image is zoomed-in and cropped to show the contours better.*\n\n### Merge CellDataFrames that have the same image segmentations but different scored calls\n\nThis happens frequently because current InForm exports only permit two features to be scored per export\n\n```python\nmerged,fail = cdf1.merge_scores(cdf2,on=['sample_name','frame_name','x','y'])\n```\n\n\n### Show names of the binary 'scored_calls'\n```python\ncdf.scored_names\n```\n\n> ['PD1', 'PDL1']\n\n### Show phenotypes\n```python\ncdf.phenotypes\n```\n\n> ['CD8+', 'OTHER', 'SOX10+']\n\n### Show regions\n```python\ncdf.regions\n```\n\n> ['Margin', 'Stroma', 'Tumor']\n\n### Combine two or more phenotypes into one or rename a phenotype\n```python\ncollapsed = cdf.collapse_phenotypes(['CD8+','OTHER'],'non-Tumor')\ncollapsed.phenotypes\n```\n\n> ['SOX10+', 'non-Tumor']\n\n### Rename a region\n\nRename *TUMOR* to *Tumor*\n\n```python\nrenamed = cdf.rename_region('TUMOR','Tumor')\n```\n\n### Rename scored phenotypes\n\n```python\nrenamed = cdf.rename_scored_calls({'PDL1 (Opal 520)':'PDL1'})\n```\n\n### Threshold a phenotype\n\nMake *CYTOK* into *CYTOK PDL1+* and *CYTOK PDL1-*\n\n```python\nraw_thresh = raw.threshold('CYTOK','PDL1')\n```\n\n### Double threshold\n\n```python\nCD68_CD163 = raw.threshold('CD68','CD163').\\\n threshold('CD68 CD163+','PDL1').\\\n threshold('CD68 CD163-','PDL1')\n```\n\n### Get per frame counts\n\ngenerate counts and fractions of the current phenotypes and export them to a csv\n\n```python\ncdf.counts().frame_counts().to_csv('my_frame_counts.csv')\n```\n\n### Get per sample counts\n\ngenerate counts and fractions of the current phenotypes and export them to a csv\n\n```python\ncdf.counts().sample_counts().to_csv('my_sample_counts.csv')\n```\n\n### Identify cells that are in contact with a phenotype\n\nThe follow command creates a new CellDataFrame that has an additional binary feature representative of the contact with 'T cell' phenotype cells.\n\n```python\ncdf = cdf.contacts().threshold('T cell')\n```\n\n### Identify cells that are within some proximity of a phenotype of interest\n\nThe follow command creates a new CellDataFrame that has an additional binary feature representative of being inside or outisde 75 microns of 'T cell' phenotype cells.\n\n```python\ncdf = cdf.nearestneighbors().threshold('T cell','T cell/within 75um',distance_um=75)\n```\n\n### Create an image of cell-cell contacts between features of interest\n\n```python\n\n```\n\n# Check outputs against IrisSpatialFeatures outputs\n\nTo ensure we are generating expected outs we can check against the outputs of IrisSpatialFeatures [[github](https://github.com/gusef/IrisSpatialFeatures)]. \n\n* Jupyter Notebook: [Test against IrisSpatialFeatures outputs](https://github.com/jason-weirather/pythologist/blob/master/notebooks/Test%20against%20IrisSpatialFeatures%20outputs.ipynb)\n\n\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/jason-weirather/pythologist", "keywords": "bioinformatics", "license": "Apache License, Version 2.0", "maintainer": "", "maintainer_email": "", "name": "pythologist", "package_url": "https://pypi.org/project/pythologist/", "platform": "", "project_url": "https://pypi.org/project/pythologist/", "project_urls": { "Homepage": "https://github.com/jason-weirather/pythologist" }, "release_url": "https://pypi.org/project/pythologist/1.0.2/", "requires_dist": [ "pandas (>=0.23.0)", "numpy", "scipy", "h5py", "imageio", "tables", "pythologist-image-utilities (>=1.0.2)", "pythologist-test-images ; extra == 'test'" ], "requires_python": "", "summary": "inForm PerkinElmer Reader - Python interface to read outputs of the PerkinElmer inForm software", "version": "1.0.2" }, "last_serial": 5139243, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "3d5eb256831a00e1ad9c37792675043e", "sha256": "41f2c9085e61d962b1c670cfc62ca2dc21f502ee61f5292512086d5bd354d33a" }, "downloads": -1, "filename": "pythologist-0.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "3d5eb256831a00e1ad9c37792675043e", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 21861, "upload_time": "2018-05-23T16:42:02", "url": "https://files.pythonhosted.org/packages/d8/a1/5fb4cd9b9bf3d575dd21ff1f0b7ef36b59bf39b5c961365d39a61b0f0f99/pythologist-0.1.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "e2322cd4de213c1e7e6b030e8bec734a", "sha256": "1b5063a71594363b0171c6e71356a4ab458e207fd3605ebcb08deff17da593ca" }, "downloads": -1, "filename": "pythologist-0.1.0.tar.gz", "has_sig": false, "md5_digest": "e2322cd4de213c1e7e6b030e8bec734a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18621, "upload_time": "2018-05-23T16:42:03", "url": "https://files.pythonhosted.org/packages/ae/1f/360b89c741018a06066fc7516801ccb6a61d4774cfd5f881e343ab453765/pythologist-0.1.0.tar.gz" } ], "0.1.10": [ { "comment_text": "", "digests": { "md5": "1e94bcf44089422ca014f16646844937", "sha256": "35ae7e99769738e733849ff3689dd0d7d2ca97558503e3b0e2d586e16adc39d0" }, "downloads": -1, "filename": "pythologist-0.1.10-py3-none-any.whl", "has_sig": false, "md5_digest": "1e94bcf44089422ca014f16646844937", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 21216, "upload_time": "2018-08-31T16:57:54", "url": "https://files.pythonhosted.org/packages/05/52/64cb36af44b17f8077f1c96963737f11ba74d0d63cbd34aced21b3105453/pythologist-0.1.10-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "c51f04c2e37bbdebdb0b642f315b3c42", "sha256": "c89667a7ff73b2378892b138e238f9a56130bdae90b80b39405c685b64aae938" }, "downloads": -1, "filename": "pythologist-0.1.10.tar.gz", "has_sig": false, "md5_digest": "c51f04c2e37bbdebdb0b642f315b3c42", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18577, "upload_time": "2018-08-31T16:57:55", "url": "https://files.pythonhosted.org/packages/fd/e1/9a839669a428dbab37f15f72e9f2950ae8f100513a991ee2fdfc79251d63/pythologist-0.1.10.tar.gz" } ], "0.1.11": [ { "comment_text": "", "digests": { "md5": "8cb65f5ac2c0c5cded12acbc21d7fad9", "sha256": "306c243027b2593aaeebb3f6a4cb3c1ccb01e4e14e170145f533e54e77e13ccf" }, "downloads": -1, "filename": "pythologist-0.1.11-py3-none-any.whl", "has_sig": false, "md5_digest": "8cb65f5ac2c0c5cded12acbc21d7fad9", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 26168, "upload_time": "2019-02-18T19:04:54", "url": "https://files.pythonhosted.org/packages/69/9f/243e1ec8ebb0b866e6c71ea2e91c44e41d3e49c0f6ba9af20a1fb631d449/pythologist-0.1.11-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "5dcd73cf707bbd202d788ff63dce3d25", "sha256": "2b32b77402e1dd112fefbe2c16a85f6f6fb1be019dd833cb0411676b9a779f9d" }, "downloads": -1, "filename": "pythologist-0.1.11.tar.gz", "has_sig": false, "md5_digest": "5dcd73cf707bbd202d788ff63dce3d25", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18236, "upload_time": "2019-02-18T19:04:56", "url": "https://files.pythonhosted.org/packages/72/a4/1c6717ab92b271a9b0a9259728fee2fd7974c48e58a07523cdae88c9f36c/pythologist-0.1.11.tar.gz" } ], "0.1.5": [ { "comment_text": "", "digests": { "md5": "e3079ab9aef6a282e8098531aedecfab", "sha256": "49e838aa56e0e8f06a1878571c0d8da525d8f364bc43b13106149a08976cca8c" }, "downloads": -1, "filename": "pythologist-0.1.5-py3-none-any.whl", "has_sig": false, "md5_digest": "e3079ab9aef6a282e8098531aedecfab", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 22094, "upload_time": "2018-05-23T21:09:17", "url": "https://files.pythonhosted.org/packages/6c/73/1a50c02fbcfa5e0b4e774e5f29229ac5151d97fa421aabdda4a428c80477/pythologist-0.1.5-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ca1f2a0b4020572aaa9e3c4123865cb9", "sha256": "38dc2cc95e9b1a0c32cbe90562c6da030942aa31ade74011483059d497b1c529" }, "downloads": -1, "filename": "pythologist-0.1.5.tar.gz", "has_sig": false, "md5_digest": "ca1f2a0b4020572aaa9e3c4123865cb9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18841, "upload_time": "2018-05-23T21:09:18", "url": "https://files.pythonhosted.org/packages/5c/1f/6adf0e6c26df055688d0ffac1c63e071142121204d014c4f53e51b8eb5d5/pythologist-0.1.5.tar.gz" } ], "0.1.6": [ { "comment_text": "", "digests": { "md5": "b526865f8610ea64e87f73876f395634", "sha256": "9dedd2c53547c965f781380f7782e17a340478dfc0a6833b75f8581f76d8d6de" }, "downloads": -1, "filename": "pythologist-0.1.6-py3-none-any.whl", "has_sig": false, "md5_digest": "b526865f8610ea64e87f73876f395634", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 22113, "upload_time": "2018-05-24T02:36:59", "url": "https://files.pythonhosted.org/packages/27/cd/a27d1457d2982fed7d8de30323c1a7a238341f84d425294b08f7700545dd/pythologist-0.1.6-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "28c4415bc02984c4899f940291156b54", "sha256": "f39ecd66de94c8390172c60debbaf2c9c7485d47b4ebbec26600627017c3f621" }, "downloads": -1, "filename": "pythologist-0.1.6.tar.gz", "has_sig": false, "md5_digest": "28c4415bc02984c4899f940291156b54", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18865, "upload_time": "2018-05-24T02:37:00", "url": "https://files.pythonhosted.org/packages/5f/4d/a038846990b340db7677786681c69fb4cfa0ddaa3298e9f9357101df31b0/pythologist-0.1.6.tar.gz" } ], "0.1.7": [ { "comment_text": "", "digests": { "md5": "9a475b8e00118552ab531193e23952a9", "sha256": "b3d63bd46859df430f54b13b40395bf127e71768a4df7d931f0428f590de4c6e" }, "downloads": -1, "filename": "pythologist-0.1.7-py3-none-any.whl", "has_sig": false, "md5_digest": "9a475b8e00118552ab531193e23952a9", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 22133, "upload_time": "2018-06-07T17:15:48", "url": "https://files.pythonhosted.org/packages/b4/93/146a2ee17a8c5b730e1671922aad1b62a1fddd1d1b7a80e972b7b2fa433c/pythologist-0.1.7-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "cba6707e6973b691082cf7fc09ae50d2", "sha256": "cce9ff125869ac8892dcdb087f02192d72ed69321d0e78b08fb3c6bf784221f6" }, "downloads": -1, "filename": "pythologist-0.1.7.tar.gz", "has_sig": false, "md5_digest": "cba6707e6973b691082cf7fc09ae50d2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18885, "upload_time": "2018-06-07T17:15:49", "url": "https://files.pythonhosted.org/packages/ff/79/a58ffa030d9c2f6ae569ebb8319547806a26d25bf3c674c78803ee714d32/pythologist-0.1.7.tar.gz" } ], "1.0.2": [ { "comment_text": "", "digests": { "md5": "715f8de319347d501b25b7baf4361d73", "sha256": "9bc6d387767ff7d97531979eb34fc4b9bcceb28d3768780d4349666a94c96868" }, "downloads": -1, "filename": "pythologist-1.0.2-py3.7.egg", "has_sig": false, "md5_digest": "715f8de319347d501b25b7baf4361d73", "packagetype": "bdist_egg", "python_version": "3.7", "requires_python": null, "size": 58536, "upload_time": "2019-04-13T21:39:21", "url": "https://files.pythonhosted.org/packages/c6/00/4f1daa1db0232658ce04b96642bef602c5b491db9cbb37a41a7045e29635/pythologist-1.0.2-py3.7.egg" }, { "comment_text": "", "digests": { "md5": "794d43644c35bda1d2b45765800ce409", "sha256": "c9edfeec70e27a97fa7f0b0a34ee9f2c7bb2e8071f9e2542c38decd2fdfb872b" }, "downloads": -1, "filename": "pythologist-1.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "794d43644c35bda1d2b45765800ce409", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 30549, "upload_time": "2019-04-13T21:39:20", "url": "https://files.pythonhosted.org/packages/2d/e2/72108d109c7af86da59d8db036cad8b5f7d15fcd3b3d40916dab8e6ddbcb/pythologist-1.0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "70a109f37658f8a83587006ef2c1f2a3", "sha256": "d4c334067ae417741def8bc86ec1bd20ad81755be6bb255f7c7bb9f14598c2b3" }, "downloads": -1, "filename": "pythologist-1.0.2.tar.gz", "has_sig": false, "md5_digest": "70a109f37658f8a83587006ef2c1f2a3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 23154, "upload_time": "2019-04-13T21:39:22", "url": "https://files.pythonhosted.org/packages/2e/4b/276b0c04211f782ca68edf2fc4a6693559cea8eeaeefeeb38e66423320c4/pythologist-1.0.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "715f8de319347d501b25b7baf4361d73", "sha256": "9bc6d387767ff7d97531979eb34fc4b9bcceb28d3768780d4349666a94c96868" }, "downloads": -1, "filename": "pythologist-1.0.2-py3.7.egg", "has_sig": false, "md5_digest": "715f8de319347d501b25b7baf4361d73", "packagetype": "bdist_egg", "python_version": "3.7", "requires_python": null, "size": 58536, "upload_time": "2019-04-13T21:39:21", "url": "https://files.pythonhosted.org/packages/c6/00/4f1daa1db0232658ce04b96642bef602c5b491db9cbb37a41a7045e29635/pythologist-1.0.2-py3.7.egg" }, { "comment_text": "", "digests": { "md5": "794d43644c35bda1d2b45765800ce409", "sha256": "c9edfeec70e27a97fa7f0b0a34ee9f2c7bb2e8071f9e2542c38decd2fdfb872b" }, "downloads": -1, "filename": "pythologist-1.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "794d43644c35bda1d2b45765800ce409", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 30549, "upload_time": "2019-04-13T21:39:20", "url": "https://files.pythonhosted.org/packages/2d/e2/72108d109c7af86da59d8db036cad8b5f7d15fcd3b3d40916dab8e6ddbcb/pythologist-1.0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "70a109f37658f8a83587006ef2c1f2a3", "sha256": "d4c334067ae417741def8bc86ec1bd20ad81755be6bb255f7c7bb9f14598c2b3" }, "downloads": -1, "filename": "pythologist-1.0.2.tar.gz", "has_sig": false, "md5_digest": "70a109f37658f8a83587006ef2c1f2a3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 23154, "upload_time": "2019-04-13T21:39:22", "url": "https://files.pythonhosted.org/packages/2e/4b/276b0c04211f782ca68edf2fc4a6693559cea8eeaeefeeb38e66423320c4/pythologist-1.0.2.tar.gz" } ] }