diff --git a/README.md b/README.md index 30adee9..64884be 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,33 @@ Maintainer: Jess Robertson (jesse.robertson _at_ csiro.au) ### So why would I want to use this? -Gonna come up with a good reason for this here.... +Say you wanted to know how many samples have been submitted to IEDA by your colleague named Dr Barnes: + +```python +>>> from earthchem.query import RESTClientQuery +>>> q = RESTClientQuery(author='barnes') +>>> q.count() + +4902 +``` + +That's a lot of samples. Can we see the compositions of the first 50 say? + +```python +>>> df = q.dataframe() +>>> df.head() +``` + +![Table output](https://github.com/jesserobertson/earthchem-pyclient/raw/develop/docs/resources/table_output.png) + + +Great, so now I can make some little plots right? + +```python +>>> df.plot('al2o3', 'sio2', 'scatter') +``` + +![Plot output](https://github.com/jesserobertson/earthchem-pyclient/raw/develop/docs/resources/plot_output.png) ### Great, I'm sold. How do I get it? diff --git a/docs/resources/plot_output.png b/docs/resources/plot_output.png new file mode 100644 index 0000000..ff5e41f Binary files /dev/null and b/docs/resources/plot_output.png differ diff --git a/docs/resources/table_output.png b/docs/resources/table_output.png new file mode 100644 index 0000000..c4c484f Binary files /dev/null and b/docs/resources/table_output.png differ diff --git a/earthchem/__init__.py b/earthchem/__init__.py index adece65..0dce754 100644 --- a/earthchem/__init__.py +++ b/earthchem/__init__.py @@ -1,5 +1,7 @@ from . import documentation, query +from .query import Query + # Versioneer imports from ._version import get_versions __version__ = get_versions()['version'] diff --git a/earthchem/query.py b/earthchem/query.py index 277d4c2..7f10f87 100644 --- a/earthchem/query.py +++ b/earthchem/query.py @@ -33,7 +33,7 @@ def make_query_docstring(): docstr += '\n' + wrapper.fill('{0} - {1}'.format(*item)) return docstr -class RESTClientQuery(dict): +class Query(dict): __doc__ = make_query_docstring() docdict = get_documentation() @@ -48,7 +48,7 @@ def __init__(self, **kwargs): def __repr__(self): kwargs = ', '.join('{0}={1}'.format(*it) for it in self.items()) - return 'RESTClientQuery({})'.format(kwargs) + return 'Query({})'.format(kwargs) def __setitem__(self, key, value): """ Sets a particular query term, making sure that the values @@ -83,10 +83,16 @@ def count(self): else: raise IOError("Couldn't get data from network") - def dataframe(self, standarditems=True): + def dataframe(self, standarditems=True, drop_empty=True): """ Get the actual data in a dataframe Note that this doesn't do pagination yet... + + Parameters: + standarditems - if True, returns the Earthchem + standard items in the table + drop_empty - if True, drops columns for which there + is no data """ # Add the proper search type keys to the query self['searchtype'] = 'rowdata' @@ -97,7 +103,23 @@ def dataframe(self, standarditems=True): # Return the result if resp.ok: try: - return pandas.read_json(StringIO(resp.text)) + # Create a dataframe + df = pandas.read_json(StringIO(resp.text)) + + # Convert numerical values + string_values = { # things to keep as strings + 'sample_id', 'source', 'url', 'title', 'author', 'journal', + 'method', 'material', 'type', 'composition', 'rock_name' + } + for key in df.keys(): + if key not in string_values: + df[key] = pandas.to_numeric(df[key]) + + # Drop empty columns + if drop_empty: + df.dropna(axis='columns', how='all', inplace=True) + return df + except ValueError: if resp.text == 'no results found': print("Didn't find any records, returning None") diff --git a/examples/rest_queries.ipynb b/examples/rest_queries.ipynb index 8304a3a..7595e55 100644 --- a/examples/rest_queries.ipynb +++ b/examples/rest_queries.ipynb @@ -8,7 +8,7 @@ { "data": { "text/plain": [ - "'0.0.1+6.g32caee3.dirty'" + "'0.0.2+10.g6c92ed4.dirty'" ] }, "execution_count": 1, @@ -21,9 +21,16 @@ "earthchem.__version__" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Make a rest client" + ] + }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 2, "metadata": {}, "outputs": [ { @@ -32,42 +39,26 @@ "'http://ecp.iedadata.org/restsearchservice?outputtype=json&author=klump'" ] }, - "execution_count": 11, + "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "from earthchem.documentation import *\n", - "from earthchem.query import RESTClientQuery\n", - "\n", - "q = RESTClientQuery(author='klump')\n", + "q = earthchem.Query(author='klump')\n", "q.url" ] }, { - "cell_type": "code", - "execution_count": 17, + "cell_type": "markdown", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'RESTClientQuery(author=barnes)'" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], "source": [ - "q.__repr__()" + "How many records have we found?" ] }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 3, "metadata": {}, "outputs": [ { @@ -76,7 +67,7 @@ "0" ] }, - "execution_count": 12, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } @@ -87,7 +78,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 4, "metadata": {}, "outputs": [ { @@ -102,9 +93,44 @@ "q.dataframe()" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's try another author" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "4902" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "q = earthchem.Query(author='barnes')\n", + "q.count()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get the first 50 records" + ] + }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -128,196 +154,331 @@ " \n", " \n", " \n", - " ag\n", " al2o3\n", - " as\n", - " au\n", " author\n", - " b\n", - " ba\n", - " be\n", - " be10_be\n", - " bi\n", + " cao\n", + " cl\n", + " composition\n", + " feot\n", + " journal\n", + " k\n", + " k2o\n", + " latitude\n", " ...\n", + " mno\n", + " na2o\n", + " p2o5\n", + " rock_name\n", + " sample_id\n", + " sio2\n", + " source\n", + " tio2\n", + " title\n", " type\n", - " u\n", - " u235_pb207\n", - " u238_pb206\n", - " v\n", - " w\n", - " y\n", - " yb\n", - " zn\n", - " zr\n", " \n", " \n", " \n", " \n", " 0\n", - " \n", - " \n", - " \n", - " \n", + " NaN\n", " BARNES, J. D.; STRAUB, S. M.\n", - " \n", - " \n", - " \n", - " \n", - " \n", + " NaN\n", + " 647.0\n", + " unknown\n", + " NaN\n", + " CHEM. GEOL.\n", + " NaN\n", + " NaN\n", + " 18.0448\n", " ...\n", + " NaN\n", + " NaN\n", + " NaN\n", + " not-given\n", + " 64DS\n", + " NaN\n", + " GEOROC\n", + " NaN\n", + " CHLORINE STABLE ISOTOPE VARIATIONS IN IZU BONI...\n", " volcanic\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", " \n", " \n", " 1\n", - " \n", " 13.3\n", - " \n", - " \n", " BARNES, J. D.; STRAUB, S. M.\n", - " \n", - " \n", - " \n", - " \n", - " \n", + " 9.37\n", + " 560.0\n", + " unknown\n", + " 12.63\n", + " CHEM. GEOL.\n", + " NaN\n", + " 0.30\n", + " 30.8610\n", " ...\n", + " 0.31\n", + " 2.20\n", + " 0.10\n", + " not-given\n", + " 125-782A-29X3-42-46\n", + " 48.47\n", + " GEOROC\n", + " 1.02\n", + " CHLORINE STABLE ISOTOPE VARIATIONS IN IZU BONI...\n", " volcanic\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", " \n", " \n", " 2\n", - " \n", " 14.2\n", - " \n", - " \n", " BARNES, J. D.; STRAUB, S. M.\n", - " \n", - " \n", - " \n", - " \n", - " \n", + " 8.84\n", + " 960.0\n", + " unknown\n", + " 10.78\n", + " CHEM. GEOL.\n", + " NaN\n", + " 0.33\n", + " 30.8610\n", " ...\n", + " 0.38\n", + " 2.60\n", + " 0.10\n", + " not-given\n", + " 125-782A-29X3-42-46\n", + " 52.00\n", + " GEOROC\n", + " 0.86\n", + " CHLORINE STABLE ISOTOPE VARIATIONS IN IZU BONI...\n", " volcanic\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", " \n", " \n", " 3\n", - " \n", " 13.6\n", - " \n", - " \n", " BARNES, J. D.; STRAUB, S. M.\n", - " \n", - " \n", - " \n", - " \n", - " \n", + " 9.30\n", + " 1170.0\n", + " unknown\n", + " 12.43\n", + " CHEM. GEOL.\n", + " NaN\n", + " 0.26\n", + " 30.8610\n", " ...\n", + " 0.22\n", + " 2.27\n", + " 0.11\n", + " not-given\n", + " 125-782A-29X3-42-46\n", + " 49.72\n", + " GEOROC\n", + " 0.98\n", + " CHLORINE STABLE ISOTOPE VARIATIONS IN IZU BONI...\n", " volcanic\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", " \n", " \n", " 4\n", - " \n", " 14.3\n", - " \n", - " \n", " BARNES, J. D.; STRAUB, S. M.\n", - " \n", - " \n", - " \n", - " \n", - " \n", + " 6.39\n", + " 1870.0\n", + " unknown\n", + " 8.02\n", + " CHEM. GEOL.\n", + " NaN\n", + " 0.64\n", + " 30.8610\n", " ...\n", + " 0.22\n", + " 3.77\n", + " 0.15\n", + " not-given\n", + " 125-782A-29X3-42-46\n", + " 57.82\n", + " GEOROC\n", + " 0.83\n", + " CHLORINE STABLE ISOTOPE VARIATIONS IN IZU BONI...\n", " volcanic\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", " \n", " \n", "\n", - "

5 rows × 109 columns

\n", + "

5 rows × 24 columns

\n", "" ], "text/plain": [ - " ag al2o3 as au author b ba be be10_be bi ... \\\n", - "0 BARNES, J. D.; STRAUB, S. M. ... \n", - "1 13.3 BARNES, J. D.; STRAUB, S. M. ... \n", - "2 14.2 BARNES, J. D.; STRAUB, S. M. ... \n", - "3 13.6 BARNES, J. D.; STRAUB, S. M. ... \n", - "4 14.3 BARNES, J. D.; STRAUB, S. M. ... \n", + " al2o3 author cao cl composition feot \\\n", + "0 NaN BARNES, J. D.; STRAUB, S. M. NaN 647.0 unknown NaN \n", + "1 13.3 BARNES, J. D.; STRAUB, S. M. 9.37 560.0 unknown 12.63 \n", + "2 14.2 BARNES, J. D.; STRAUB, S. M. 8.84 960.0 unknown 10.78 \n", + "3 13.6 BARNES, J. D.; STRAUB, S. M. 9.30 1170.0 unknown 12.43 \n", + "4 14.3 BARNES, J. D.; STRAUB, S. M. 6.39 1870.0 unknown 8.02 \n", + "\n", + " journal k k2o latitude ... mno na2o p2o5 rock_name \\\n", + "0 CHEM. GEOL. NaN NaN 18.0448 ... NaN NaN NaN not-given \n", + "1 CHEM. GEOL. NaN 0.30 30.8610 ... 0.31 2.20 0.10 not-given \n", + "2 CHEM. GEOL. NaN 0.33 30.8610 ... 0.38 2.60 0.10 not-given \n", + "3 CHEM. GEOL. NaN 0.26 30.8610 ... 0.22 2.27 0.11 not-given \n", + "4 CHEM. GEOL. NaN 0.64 30.8610 ... 0.22 3.77 0.15 not-given \n", "\n", - " type u u235_pb207 u238_pb206 v w y yb zn zr \n", - "0 volcanic \n", - "1 volcanic \n", - "2 volcanic \n", - "3 volcanic \n", - "4 volcanic \n", + " sample_id sio2 source tio2 \\\n", + "0 64DS NaN GEOROC NaN \n", + "1 125-782A-29X3-42-46 48.47 GEOROC 1.02 \n", + "2 125-782A-29X3-42-46 52.00 GEOROC 0.86 \n", + "3 125-782A-29X3-42-46 49.72 GEOROC 0.98 \n", + "4 125-782A-29X3-42-46 57.82 GEOROC 0.83 \n", "\n", - "[5 rows x 109 columns]" + " title type \n", + "0 CHLORINE STABLE ISOTOPE VARIATIONS IN IZU BONI... volcanic \n", + "1 CHLORINE STABLE ISOTOPE VARIATIONS IN IZU BONI... volcanic \n", + "2 CHLORINE STABLE ISOTOPE VARIATIONS IN IZU BONI... volcanic \n", + "3 CHLORINE STABLE ISOTOPE VARIATIONS IN IZU BONI... volcanic \n", + "4 CHLORINE STABLE ISOTOPE VARIATIONS IN IZU BONI... volcanic \n", + "\n", + "[5 rows x 24 columns]" ] }, - "execution_count": 14, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "q = RESTClientQuery(author='barnes')\n", "df = q.dataframe()\n", "df.head()" ] }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "from collections import defaultdict" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "stuff = defaultdict(list)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "for k, c in df.items():\n", + " stuff[str(c.dtype)].append(k)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "defaultdict(list,\n", + " {'float64': ['al2o3',\n", + " 'cao',\n", + " 'cl',\n", + " 'feot',\n", + " 'k',\n", + " 'k2o',\n", + " 'latitude',\n", + " 'longitude',\n", + " 'mgo',\n", + " 'mno',\n", + " 'na2o',\n", + " 'p2o5',\n", + " 'sio2',\n", + " 'tio2'],\n", + " 'object': ['author',\n", + " 'composition',\n", + " 'journal',\n", + " 'material',\n", + " 'method',\n", + " 'rock_name',\n", + " 'sample_id',\n", + " 'source',\n", + " 'title',\n", + " 'type']})" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "stuff" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[('al2o3', 'float64'),\n", + " ('author', 'object'),\n", + " ('cao', 'float64'),\n", + " ('cl', 'float64'),\n", + " ('composition', 'object'),\n", + " ('feot', 'float64'),\n", + " ('journal', 'object'),\n", + " ('k', 'float64'),\n", + " ('k2o', 'float64'),\n", + " ('latitude', 'float64'),\n", + " ('longitude', 'float64'),\n", + " ('material', 'object'),\n", + " ('method', 'object'),\n", + " ('mgo', 'float64'),\n", + " ('mno', 'float64'),\n", + " ('na2o', 'float64'),\n", + " ('p2o5', 'float64'),\n", + " ('rock_name', 'object'),\n", + " ('sample_id', 'object'),\n", + " ('sio2', 'float64'),\n", + " ('source', 'object'),\n", + " ('tio2', 'float64'),\n", + " ('title', 'object'),\n", + " ('type', 'object')]" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "[(k, str(c.dtype)) for k, c in df.items()]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can generate a plot of this data" + ] + }, + { + "cell_type": "code", + "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "" + "" ] }, - "execution_count": 15, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" }, @@ -325,7 +486,7 @@ "data": { "image/png": "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\n", "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -338,6 +499,36 @@ "df.plot('longitude', 'latitude', 'scatter')" ] }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "from matplotlib import pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\nQmCC\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "df.plot('al2o3', 'mgo', 'scatter')\n", + "plt.savefig('plot_output.png')" + ] + }, { "cell_type": "markdown", "metadata": {}, diff --git a/examples/scratch.ipynb b/examples/scratch.ipynb index 8ad5cc9..d0d2be7 100644 --- a/examples/scratch.ipynb +++ b/examples/scratch.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ diff --git a/tests/test_client_data.py b/tests/test_client_data.py new file mode 100644 index 0000000..919d017 --- /dev/null +++ b/tests/test_client_data.py @@ -0,0 +1,32 @@ +from earthchem import Query + +import unittest + +class TestRESTClientData(unittest.TestCase): + + def setUp(self): + self.query = Query(author='barnes') + self.count = self.query.count() + self.df = self.query.dataframe() + + def test_data_type(self): + "Check the right columns are numeric" + # Expected dtypes for columns here + expected = { + 'float64': [ + 'al2o3', 'cao', 'cl', 'feot', 'k', 'k2o', 'latitude', 'longitude', 'mgo', 'mno', 'na2o', 'p2o5', 'sio2', 'tio2' + ], + 'object': [ + 'author', 'composition', 'journal', 'material', 'method', 'rock_name', 'sample_id', 'source', 'title', 'type' + ] + } + + for dtype, keys in expected.items(): + for key in keys: + try: + self.assertEqual(str(self.df[key].dtype), dtype) + except KeyError: + pass + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/tests/test_earthchem.py b/tests/test_earthchem.py index f65c56a..6b56924 100644 --- a/tests/test_earthchem.py +++ b/tests/test_earthchem.py @@ -1,5 +1,4 @@ -from earthchem.query import RESTClientQuery -from matplotlib import pyplot +from earthchem import Query import unittest @@ -8,7 +7,7 @@ class TestRESTClientQuery(unittest.TestCase): "Tests for RESTClient" def setUp(self): - self.query = RESTClientQuery() + self.query = Query() def test_set_author(self): "Check that author setting works ok" @@ -18,7 +17,7 @@ def test_set_author(self): self.assertEqual(self.query.url, 'http://ecp.iedadata.org/restsearchservice?outputtype=json&author={}'.format(auth)) self.assertEqual(repr(self.query), - 'RESTClientQuery(author={})'.format(auth)) + 'Query(author={})'.format(auth)) def test_author_count(self): "Check that we handle author counts when things are 0" @@ -45,19 +44,5 @@ def test_remove(self): with self.assertRaises(KeyError): _ = self.query['searchtype'] - -class IntegrationTestRESTClientQuery(unittest.TestCase): - - "Some integration tests to check that things are working" - - def setUp(self): - self.query = RESTClientQuery(author='barnes') - - def test_plot(self): - "Check that plotting works without any issues" - self.query.dataframe().plot('longitude', 'latitude', 'scatter') - pyplot.close() - - if __name__ == '__main__': unittest.main() \ No newline at end of file diff --git a/tests/test_integration.py b/tests/test_integration.py new file mode 100644 index 0000000..bc53561 --- /dev/null +++ b/tests/test_integration.py @@ -0,0 +1,26 @@ +from earthchem import Query + +from matplotlib import pyplot + +import unittest + +class IntegrationTestRESTClientQuery(unittest.TestCase): + + "Some integration tests to check that things are working" + + def setUp(self): + self.query = Query(author='barnes') + self.df = self.query.dataframe() + + def test_plot_latlon(self): + "Check that plotting works without any issues" + self.df.plot('longitude', 'latitude', 'scatter') + pyplot.close() + + def test_plot_data(self): + "Check that plotting works with data inputs" + self.df.plot('al2o3', 'sio2', 'scatter') + pyplot.close() + +if __name__ == '__main__': + unittest.main() \ No newline at end of file