pycmap 0.2.18__tar.gz → 0.2.20__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. pycmap-0.2.20/PKG-INFO +109 -0
  2. {pycmap-0.2.18 → pycmap-0.2.20}/pycmap/__init__.py +1 -1
  3. {pycmap-0.2.18 → pycmap-0.2.20}/pycmap/rest.py +45 -8
  4. {pycmap-0.2.18 → pycmap-0.2.20}/pycmap/sample.py +82 -18
  5. pycmap-0.2.20/pycmap.egg-info/PKG-INFO +109 -0
  6. pycmap-0.2.20/pycmap.egg-info/SOURCES.txt +29 -0
  7. pycmap-0.2.18/.DS_Store +0 -0
  8. pycmap-0.2.18/.gitattributes +0 -2
  9. pycmap-0.2.18/.gitignore +0 -106
  10. pycmap-0.2.18/PKG-INFO +0 -90
  11. pycmap-0.2.18/docs/.DS_Store +0 -0
  12. pycmap-0.2.18/docs/API.ipynb +0 -104
  13. pycmap-0.2.18/docs/Catalog.ipynb +0 -97
  14. pycmap-0.2.18/docs/Climatology.ipynb +0 -215
  15. pycmap-0.2.18/docs/Columns.ipynb +0 -99
  16. pycmap-0.2.18/docs/Coverage.ipynb +0 -101
  17. pycmap-0.2.18/docs/CruiseBounds.ipynb +0 -97
  18. pycmap-0.2.18/docs/CruiseByName.ipynb +0 -102
  19. pycmap-0.2.18/docs/CruisePlan.ipynb +0 -300
  20. pycmap-0.2.18/docs/CruiseTrajectory.ipynb +0 -101
  21. pycmap-0.2.18/docs/CruiseVariables.ipynb +0 -101
  22. pycmap-0.2.18/docs/Cruises.ipynb +0 -94
  23. pycmap-0.2.18/docs/DatasetMetaData.ipynb +0 -99
  24. pycmap-0.2.18/docs/Datasets.ipynb +0 -98
  25. pycmap-0.2.18/docs/DatasetsWithAncillary.ipynb +0 -94
  26. pycmap-0.2.18/docs/DepthProfile.ipynb +0 -191
  27. pycmap-0.2.18/docs/Grid.ipynb +0 -82
  28. pycmap-0.2.18/docs/HasField.ipynb +0 -83
  29. pycmap-0.2.18/docs/Head.ipynb +0 -102
  30. pycmap-0.2.18/docs/Index.ipynb +0 -111
  31. pycmap-0.2.18/docs/Installation.ipynb +0 -65
  32. pycmap-0.2.18/docs/IsClimatology.ipynb +0 -79
  33. pycmap-0.2.18/docs/LongName.ipynb +0 -101
  34. pycmap-0.2.18/docs/MatchCruise.ipynb +0 -388
  35. pycmap-0.2.18/docs/MetaData.ipynb +0 -103
  36. pycmap-0.2.18/docs/PROSYN2022.ipynb +0 -4932
  37. pycmap-0.2.18/docs/PreSWOT.ipynb +0 -1276
  38. pycmap-0.2.18/docs/Query.ipynb +0 -185
  39. pycmap-0.2.18/docs/Resolution.ipynb +0 -101
  40. pycmap-0.2.18/docs/RetrieveDataset.ipynb +0 -82
  41. pycmap-0.2.18/docs/RetrieveDatasetWithAncillary.ipynb +0 -81
  42. pycmap-0.2.18/docs/SCOPE2019.ipynb +0 -959
  43. pycmap-0.2.18/docs/Sampling.ipynb +0 -641
  44. pycmap-0.2.18/docs/SearchCatalog.ipynb +0 -157
  45. pycmap-0.2.18/docs/SpaceTime.ipynb +0 -242
  46. pycmap-0.2.18/docs/Stat.ipynb +0 -101
  47. pycmap-0.2.18/docs/TimeSeries.ipynb +0 -207
  48. pycmap-0.2.18/docs/Unit.ipynb +0 -101
  49. pycmap-0.2.18/docs/Viz.ipynb +0 -63
  50. pycmap-0.2.18/docs/Viz_CorrelationMatrix.ipynb +0 -256
  51. pycmap-0.2.18/docs/Viz_CruiseCorrelationMatrix.ipynb +0 -228
  52. pycmap-0.2.18/docs/Viz_CruiseTrack.ipynb +0 -86
  53. pycmap-0.2.18/docs/Viz_DepthProfile.ipynb +0 -194
  54. pycmap-0.2.18/docs/Viz_Histogram.ipynb +0 -183
  55. pycmap-0.2.18/docs/Viz_RegionalMap.ipynb +0 -322
  56. pycmap-0.2.18/docs/Viz_Section.ipynb +0 -238
  57. pycmap-0.2.18/docs/Viz_TimeSeries.ipynb +0 -199
  58. pycmap-0.2.18/docs/colab-badge.svg +0 -1
  59. pycmap-0.2.18/docs/cruises/.DS_Store +0 -0
  60. pycmap-0.2.18/docs/cruises/Scenario1.csv +0 -15
  61. pycmap-0.2.18/docs/cruises/Scenario2.csv +0 -19
  62. pycmap-0.2.18/docs/cruises/Scenario3.csv +0 -18
  63. pycmap-0.2.18/docs/eScience_Jan2023.ipynb +0 -693
  64. pycmap-0.2.18/docs/figures/CMAP.png +0 -0
  65. pycmap-0.2.18/docs/figures/sql.png +0 -0
  66. pycmap-0.2.18/docs/samplingPoints.csv +0 -8
  67. pycmap-0.2.18/pycmap.egg-info/PKG-INFO +0 -90
  68. pycmap-0.2.18/pycmap.egg-info/SOURCES.txt +0 -88
  69. {pycmap-0.2.18 → pycmap-0.2.20}/LICENSE +0 -0
  70. {pycmap-0.2.18 → pycmap-0.2.20}/README.md +0 -0
  71. {pycmap-0.2.18 → pycmap-0.2.20}/pycmap/annotatedHeatmap.py +0 -0
  72. {pycmap-0.2.18 → pycmap-0.2.20}/pycmap/baseGraph.py +0 -0
  73. {pycmap-0.2.18 → pycmap-0.2.20}/pycmap/clean.py +0 -0
  74. {pycmap-0.2.18 → pycmap-0.2.20}/pycmap/cmap.py +0 -0
  75. {pycmap-0.2.18 → pycmap-0.2.20}/pycmap/colorMaps.py +0 -0
  76. {pycmap-0.2.18 → pycmap-0.2.20}/pycmap/common.py +0 -0
  77. {pycmap-0.2.18 → pycmap-0.2.20}/pycmap/deepC.py +0 -0
  78. {pycmap-0.2.18 → pycmap-0.2.20}/pycmap/export.py +0 -0
  79. {pycmap-0.2.18 → pycmap-0.2.20}/pycmap/foliumHeat.py +0 -0
  80. {pycmap-0.2.18 → pycmap-0.2.20}/pycmap/hist.py +0 -0
  81. {pycmap-0.2.18 → pycmap-0.2.20}/pycmap/map.py +0 -0
  82. {pycmap-0.2.18 → pycmap-0.2.20}/pycmap/match.py +0 -0
  83. {pycmap-0.2.18 → pycmap-0.2.20}/pycmap/section.py +0 -0
  84. {pycmap-0.2.18 → pycmap-0.2.20}/pycmap/supervised.py +0 -0
  85. {pycmap-0.2.18 → pycmap-0.2.20}/pycmap/trend.py +0 -0
  86. {pycmap-0.2.18 → pycmap-0.2.20}/pycmap/viz.py +0 -0
  87. {pycmap-0.2.18 → pycmap-0.2.20}/pycmap/w3.py +0 -0
  88. {pycmap-0.2.18 → pycmap-0.2.20}/pycmap.egg-info/dependency_links.txt +0 -0
  89. {pycmap-0.2.18 → pycmap-0.2.20}/pycmap.egg-info/requires.txt +0 -0
  90. {pycmap-0.2.18 → pycmap-0.2.20}/pycmap.egg-info/top_level.txt +0 -0
  91. {pycmap-0.2.18 → pycmap-0.2.20}/setup.cfg +0 -0
  92. {pycmap-0.2.18 → pycmap-0.2.20}/setup.py +0 -0
pycmap-0.2.20/PKG-INFO ADDED
@@ -0,0 +1,109 @@
1
+ Metadata-Version: 2.4
2
+ Name: pycmap
3
+ Version: 0.2.20
4
+ Summary: Simons CMAP API python client
5
+ Home-page: https://github.com/simonscmap/pycmap
6
+ Author: Mohammad D. Ashkezari
7
+ Author-email: mdehghan@uw.edu
8
+ Keywords: ocean oceanography data visualization satellite model in-situ remote sensing machine learning
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3.7
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Requires-Dist: numpy
16
+ Requires-Dist: pandas
17
+ Requires-Dist: scipy
18
+ Requires-Dist: bokeh
19
+ Requires-Dist: matplotlib
20
+ Requires-Dist: cmocean
21
+ Requires-Dist: tqdm
22
+ Requires-Dist: folium
23
+ Requires-Dist: colorama
24
+ Requires-Dist: plotly
25
+ Dynamic: author
26
+ Dynamic: author-email
27
+ Dynamic: classifier
28
+ Dynamic: description
29
+ Dynamic: description-content-type
30
+ Dynamic: home-page
31
+ Dynamic: keywords
32
+ Dynamic: license-file
33
+ Dynamic: requires-dist
34
+ Dynamic: summary
35
+
36
+ [![PyPI version](https://badge.fury.io/py/pycmap.svg)](https://badge.fury.io/py/pycmap)
37
+ [![DOI](https://zenodo.org/badge/199070692.svg)](https://zenodo.org/badge/latestdoi/199070692)
38
+ ![Cover](https://github.com/simonscmap/pycmap/raw/master/docs/figures/CMAP.png)
39
+
40
+ *Mohammad Dehghani Ashkezari <mdehghan@uw.edu>*
41
+
42
+
43
+ # pycmap
44
+ Simons CMAP is an open-source data service to retrieve, visualize, and analyze oceanic datasets such as in-situ observations, multi-decade global satellite remote sensing, and model outputs. Pycmap is the python package of Simons CMAP project providing a simple and unified interface to the hosted datasets at Simons CMAP database. It enables the scientists and general public to dive into the vast, and often underutilized, ocean datasets and retrieve customized subsets of these massive datasets without going through the time-consuming process of data collection and preparation.
45
+
46
+ ## Documentation
47
+ See the *table of contents* below for pycmap documentations.
48
+ <br />The docs are written in jupyter notebook format and each notebook contains one or more example codes. Please download the `/docs` directory and run the example codes locally. Alternatively, you may run the examples on google cloud using the *Colab badge* which appears at the top of each page:
49
+ <br /><img align="left" src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open in Colab" title="Open and Execute in Google Colaboratory">
50
+
51
+
52
+ <br /><br />More detailed system documentations can be found at [https://cmap.readthedocs.io/en/latest/](https://cmap.readthedocs.io/en/latest/).
53
+
54
+ ## Website
55
+ Simons CMAP website is under active development at the moment: [https://simonscmap.com](https://simonscmap.com)
56
+
57
+ **<br />This project is supported by [Simons Foundation](https://www.simonsfoundation.org/).**
58
+
59
+
60
+
61
+
62
+ ## Table of Contents
63
+
64
+
65
+ ### [Installation](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Installation.ipynb)
66
+
67
+ ### [1. Data Retrieval (API)](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/API.ipynb)
68
+ - [Query](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Query.ipynb)
69
+ - [Catalog](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Catalog.ipynb)
70
+ - [Search Catalog](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/SearchCatalog.ipynb)
71
+ - [Datasets](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Datasets.ipynb)
72
+ - [Datasets With Ancillary](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/DatasetsWithAncillary.ipynb)
73
+ - [Dataset MetaData](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/DatasetMetaData.ipynb)
74
+ - [Variable MetaData](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/MetaData.ipynb)
75
+ - [Dataset Columns](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Columns.ipynb)
76
+ - [Dataset Head](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Head.ipynb)
77
+ - [Variable Long Name](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/LongName.ipynb)
78
+ - [Variable Unit](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Unit.ipynb)
79
+ - [Variable Resolution](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Resolution.ipynb)
80
+ - [Variable Coverage](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Coverage.ipynb)
81
+ - [Variable Stat](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Stat.ipynb)
82
+ - [If Column Exists](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/HasField.ipynb)
83
+ - [Is Gridded Product](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Grid.ipynb)
84
+ - [Is Climatology Product](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/IsClimatology.ipynb)
85
+ - [List of Cruises](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Cruises.ipynb)
86
+ - [Cruise Details by Name](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/CruiseByName.ipynb)
87
+ - [Cruise Spatio-Temporal Bounds](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/CruiseBounds.ipynb)
88
+ - [Cruise Trajectory](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/CruiseTrajectory.ipynb)
89
+ - [Cruise Variables](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/CruiseVariables.ipynb)
90
+ - [Retrieve Dataset](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/RetrieveDataset.ipynb)
91
+ - [Retrieve Dataset With Ancillary](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/RetrieveDatasetWithAncillary.ipynb)
92
+ - [Data Subset: Generic Space-Time Cut](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/SpaceTime.ipynb)
93
+ - [Data Subset: TimeSeries](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/TimeSeries.ipynb)
94
+ - [Data Subset: Depth Profile](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/DepthProfile.ipynb)
95
+ - [Compute Climatology](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Climatology.ipynb)
96
+ - [Sampling](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Sampling.ipynb)
97
+ - [Match (colocalize) Cruise Track with Datasets](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/MatchCruise.ipynb)
98
+
99
+
100
+ ### [2. Data Visualization](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Viz.ipynb)
101
+ - [Histogram Plot](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Viz_Histogram.ipynb)
102
+ - [TimeSeries Plot](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Viz_TimeSeries.ipynb)
103
+ - [Regional Map, Contour Plot, 3D Surface Plot](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Viz_RegionalMap.ipynb)
104
+ - [Section Map, Section Contour](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Viz_Section.ipynb)
105
+ - [Depth Profile](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Viz_DepthProfile.ipynb)
106
+ - [Cruise Track Plot](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Viz_CruiseTrack.ipynb)
107
+ - [Correlation Matrix](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Viz_CorrelationMatrix.ipynb)
108
+ - [Correlation Matrix Along Cruise Track](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Viz_CruiseCorrelationMatrix.ipynb)
109
+
@@ -15,6 +15,6 @@ if sys.version_info < (3, 0):
15
15
  UserWarning
16
16
  )
17
17
 
18
- __version__ = '0.2.18'
18
+ __version__ = '0.2.20'
19
19
  # __all__ = []
20
20
 
@@ -7,8 +7,7 @@ Function: Encapsulates RESTful API logic.
7
7
  """
8
8
 
9
9
 
10
- import random
11
- import requests
10
+ import sys, requests, random
12
11
  from requests.exceptions import HTTPError
13
12
  from urllib.parse import urlencode
14
13
  import numpy as np
@@ -237,6 +236,21 @@ class _REST(object):
237
236
  self.validate_sp_args(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9])
238
237
  df = self._request(route, method='GET', payload=payload)
239
238
  return df
239
+
240
+
241
+ def _validate_table_var(self, table, variable=None):
242
+ """
243
+ Check if table and variable exist in the catalog.
244
+ """
245
+ if variable:
246
+ df = self.query(f"exec uspValidate_Table_Variable '{table}', '{variable}'")
247
+ pot_msg = f"Invalid table ({table}) and/or variable names ({variable})."
248
+ else:
249
+ df = self.query(f"exec uspValidate_Table_Variable '{table}'")
250
+ pot_msg = f"Invalid table name ({table})."
251
+ pot_msg += "\nPlease make sure that the dataset is still available in the CMAP catalog (not deprecated)."
252
+ if len(df) != 1: sys.exit(pot_msg)
253
+ return len(df) == 1
240
254
 
241
255
 
242
256
  def get_catalog(self):
@@ -281,11 +295,13 @@ class _REST(object):
281
295
 
282
296
  def head(self, tableName, rows=5):
283
297
  """Returns top records of a data set."""
298
+ self._validate_table_var(tableName)
284
299
  return self.query(f"select top {rows} * from {tableName}")
285
300
 
286
301
 
287
302
  def columns(self, tableName):
288
303
  """Returns the list of data set columns."""
304
+ self._validate_table_var(tableName)
289
305
  return list(self.query(f"select top 1 * from {tableName}").columns)
290
306
 
291
307
 
@@ -299,6 +315,7 @@ class _REST(object):
299
315
  if len(df) > 1:
300
316
  halt('More than one table found. Please provide a more specific name: ')
301
317
  print(df)
318
+ self._validate_table_var(tableName)
302
319
  return df.iloc[0]['Dataset_ID']
303
320
 
304
321
 
@@ -310,6 +327,7 @@ class _REST(object):
310
327
  Note that this method does not return the dataset metadata.
311
328
  Use the 'get_dataset_metadata' method to get the dataset metadata.
312
329
  """
330
+ self._validate_table_var(tableName)
313
331
  datasetID = self.get_dataset_ID(tableName)
314
332
  maxRow = 2000000
315
333
  df = self.query("SELECT JSON_stats FROM tblDataset_Stats WHERE Dataset_ID=%d " % datasetID)
@@ -319,7 +337,7 @@ class _REST(object):
319
337
  msg = "The requested dataset has %d records.\n" % rows
320
338
  msg += "It is not recommended to retrieve datasets with more than %d rows using this method.\n" % maxRow
321
339
  msg += "For large datasets, please use the 'space_time' method and retrieve the data in smaller chunks."
322
- halt(msg)
340
+ halt(msg)
323
341
  return self.query("SELECT * FROM %s" % tableName)
324
342
 
325
343
 
@@ -330,6 +348,7 @@ class _REST(object):
330
348
  Note that this method does not return the dataset metadata.
331
349
  Use the 'get_dataset_metadata' method to get the dataset metadata.
332
350
  """
351
+ self._validate_table_var(tableName)
333
352
  datasetID = self.get_dataset_ID(tableName)
334
353
  df = self.query("SELECT JSON_stats FROM tblDataset_Stats WHERE Dataset_ID=%d " % datasetID)
335
354
  df = pd.read_json(df['JSON_stats'][0])
@@ -359,6 +378,7 @@ class _REST(object):
359
378
 
360
379
  def get_dataset_metadata(self, tableName):
361
380
  """Returns a dataframe containing the dataset metadata."""
381
+ self._validate_table_var(tableName)
362
382
  return self.query("EXEC uspDatasetMetadata '%s'" % tableName)
363
383
 
364
384
 
@@ -367,6 +387,7 @@ class _REST(object):
367
387
  Returns a single-row dataframe from tblVariables containing info associated with varName.
368
388
  This method is mean to be used internally and will not be exposed at documentations.
369
389
  """
390
+ self._validate_table_var(tableName, varName)
370
391
  query = "SELECT * FROM tblVariables WHERE Table_Name='%s' AND Short_Name='%s'" % (tableName, varName)
371
392
  return self.query(query)
372
393
 
@@ -378,40 +399,45 @@ class _REST(object):
378
399
 
379
400
  def get_var_long_name(self, tableName, varName):
380
401
  """Returns the long name of a given variable."""
402
+ self._validate_table_var(tableName, varName)
381
403
  return self.query("EXEC uspVariableLongName '%s', '%s'" % (tableName, varName)).iloc[0]['Long_Name']
382
404
 
383
405
 
384
406
  def get_unit(self, tableName, varName):
385
407
  """Returns the unit for a given variable."""
408
+ self._validate_table_var(tableName, varName)
386
409
  return ' [' + self.query("EXEC uspVariableUnit '%s', '%s'" % (tableName, varName)).iloc[0]['Unit'] + ']'
387
410
 
388
411
 
389
412
  def get_var_resolution(self, tableName, varName):
390
413
  """Returns a single-row dataframe from catalog containing the variable's spatial and temporal resolutions."""
414
+ self._validate_table_var(tableName, varName)
391
415
  return self.query("EXEC uspVariableResolution '%s', '%s'" % (tableName, varName))
392
416
 
393
417
 
394
418
  def get_var_coverage(self, tableName, varName):
395
419
  """Returns a single-row dataframe from catalog containing the variable's spatial and temporal coverage."""
420
+ self._validate_table_var(tableName, varName)
396
421
  return self.query("EXEC uspVariableCoverage '%s', '%s'" % (tableName, varName))
397
422
 
398
423
 
399
424
  def get_var_stat(self, tableName, varName):
400
425
  """Returns a single-row dataframe from catalog containing the variable's summary statistics."""
426
+ self._validate_table_var(tableName, varName)
401
427
  return self.query("EXEC uspVariableStat '%s', '%s'" % (tableName, varName))
402
428
 
403
429
 
404
430
  def has_field(self, tableName, varName, servers=["rainier"]):
405
431
  """Returns a boolean confirming whether a field (varName) exists in a table (data set)."""
406
- query = f"select top 1 {varName} from {tableName}"
432
+ self._validate_table_var(tableName)
433
+ query = f"select top 1 * from {tableName}"
407
434
  df = self.query(query, servers)
408
- hasField = False
409
- if len(df)>0: hasField = True
410
- return hasField
435
+ return len(df) > 0 and varName in df.columns
411
436
 
412
437
 
413
438
  def is_grid(self, tableName, varName):
414
439
  """Returns a boolean indicating whether the variable is a gridded product or has irregular spatial resolution."""
440
+ self._validate_table_var(tableName, varName)
415
441
  grid = True
416
442
  query = "SELECT Spatial_Res_ID, RTRIM(LTRIM(Spatial_Resolution)) AS Spatial_Resolution FROM tblVariables "
417
443
  query = query + "JOIN tblSpatial_Resolutions ON [tblVariables].Spatial_Res_ID=[tblSpatial_Resolutions].ID "
@@ -429,6 +455,7 @@ class _REST(object):
429
455
  """
430
456
  Returns True if the table represents a climatological data set.
431
457
  """
458
+ self._validate_table_var(tableName)
432
459
  df = self.query(f"SELECT * FROM tblDatasets d JOIN tblVariables v ON d.ID=v.Dataset_ID WHERE v.Table_Name='{tableName}'", servers)
433
460
  if len(df) > 0:
434
461
  return True if df.iloc[0]['Climatology'] == 1 else False
@@ -447,6 +474,7 @@ class _REST(object):
447
474
  Returns a dataframe containing the associated metadata for a single variable.
448
475
  The returned metadata does not include the list of references and articles associated with the variable.
449
476
  """
477
+ self._validate_table_var(table, variable)
450
478
  query = f"{catalog_sql()} WHERE Short_Name='{variable}' AND Table_Name='{table}'"
451
479
  return self.query(query)
452
480
 
@@ -456,6 +484,7 @@ class _REST(object):
456
484
  Returns a dataframe containing the associated metadata.
457
485
  The inputs can be string literals (if only one table, and variable is passed) or a list of string literals.
458
486
  """
487
+ self._validate_table_var(table, variable)
459
488
  if isinstance(table, str): table = [table]
460
489
  if isinstance(variable, str): variable = [variable]
461
490
  metadata = pd.DataFrame({})
@@ -513,6 +542,7 @@ class _REST(object):
513
542
 
514
543
  def subset(self, spName, table, variable, dt1, dt2, lat1, lat2, lon1, lon2, depth1, depth2, servers):
515
544
  """Returns a subset of data according to space-time constraints."""
545
+ self._validate_table_var(table, variable)
516
546
  query = f"EXEC {spName} '{table}', '{variable}', '{dt1}', '{dt2}', {lat1}, {lat2}, {lon1}, {lon2}, {depth1}, {depth2}"
517
547
  return self.query(query, servers)
518
548
 
@@ -522,6 +552,7 @@ class _REST(object):
522
552
  Returns a subset of data according to space-time constraints.
523
553
  The results are ordered by time, lat, lon, and depth (if exists).
524
554
  """
555
+ self._validate_table_var(table, variable)
525
556
  return self.subset('uspSpaceTime', table, variable, dt1, dt2, lat1, lat2, lon1, lon2, depth1, depth2, servers=servers)
526
557
 
527
558
 
@@ -549,6 +580,7 @@ class _REST(object):
549
580
  The results are aggregated by time and ordered by time, lat, lon, and depth (if exists).
550
581
  The timeseries data can be binned weekly, monthly, qurterly, or annualy, if interval variable is set (this feature is not applicable to climatological data sets).
551
582
  """
583
+ self._validate_table_var(table, variable)
552
584
  usp = self._interval_to_uspName(interval)
553
585
  if usp != 'uspTimeSeries' and self.is_climatology(table, servers):
554
586
  print_tqdm(
@@ -563,6 +595,7 @@ class _REST(object):
563
595
  Returns a subset of data according to space-time constraints.
564
596
  The results are aggregated by depth and ordered by depth.
565
597
  """
598
+ self._validate_table_var(table, variable)
566
599
  return self.subset('uspDepthProfile', table, variable, dt1, dt2, lat1, lat2, lon1, lon2, depth1, depth2, servers=servers)
567
600
 
568
601
 
@@ -571,6 +604,7 @@ class _REST(object):
571
604
  Returns a subset of data according to space-time constraints.
572
605
  The results are ordered by time, lat, lon, and depth.
573
606
  """
607
+ self._validate_table_var(table, variable)
574
608
  return self.subset('uspSectionMap', table, variable, dt1, dt2, lat1, lat2, lon1, lon2, depth1, depth2, servers=servers)
575
609
 
576
610
 
@@ -600,6 +634,7 @@ class _REST(object):
600
634
  For instance, if the dataset is a weekly-averaged product, do not set the `period` to 'dayofyear'.
601
635
  The output of this method is a Pandas DataFrame ordered by time, lat, lon, and depth (if exists), respectively.
602
636
  """
637
+ self._validate_table_var(table, variable)
603
638
  period = self._climatology_period(period)
604
639
  if self.is_climatology(table):
605
640
  print_tqdm(
@@ -641,7 +676,9 @@ class _REST(object):
641
676
  """
642
677
  Takes a cruise name and colocalizes the cruise track with the specified variable(s).
643
678
  """
644
- df = self.cruise_bounds(cruise)
679
+ for i in range(len(targetTables)):
680
+ self._validate_table_var(targetTables[i], targetVars[i])
681
+ df = self.cruise_bounds(cruise)
645
682
  return self.match(
646
683
  sourceTable='tblCruise_Trajectory',
647
684
  sourceVar=str(df.iloc[0]['ID']),
@@ -15,9 +15,52 @@ from dateutil.parser import parse
15
15
 
16
16
 
17
17
 
18
- def alias(varName, tableName):
19
- """Return an alias for a variable name."""
20
- return f"CMAP_{varName}_{tableName}"
18
+ # Friendly alias suffix to use for common SQL aggregation functions.
19
+ # Anything not listed here falls back to the lowercased function name
20
+ # (so e.g. ``"MIN"`` becomes the ``_min`` column suffix).
21
+ AGG_SUFFIX = {
22
+ "AVG": "avg",
23
+ "STDEV": "std",
24
+ "COUNT": "count",
25
+ }
26
+
27
+
28
+ def _resolve_aggregations(aggFun):
29
+ """
30
+ Normalize a user-supplied list of SQL aggregation function names into
31
+ a list of ``(suffix, sqlFunc)`` pairs.
32
+
33
+ Function names are case-insensitive on input; the SQL form is uppercased
34
+ and the column-name suffix is the lowercased function name (with a few
35
+ friendlier short forms — see ``AGG_SUFFIX``).
36
+ """
37
+ resolved = []
38
+ for fn in aggFun:
39
+ sqlFunc = fn.strip().upper()
40
+ suffix = AGG_SUFFIX.get(sqlFunc, sqlFunc.lower())
41
+ resolved.append((suffix, sqlFunc))
42
+ return resolved
43
+
44
+
45
+ def alias(varName, tableName, aggregations):
46
+ """
47
+ Return the list of column aliases produced for a single target variable.
48
+
49
+ For each aggregation in ``aggregations`` the variable contributes one
50
+ column to the output dataframe, e.g. with the default ``AVG`` only::
51
+
52
+ CMAP_sst_tblSST_AVHRR_OI_NRT_avg
53
+
54
+ or with ``["AVG", "STDEV", "COUNT"]``::
55
+
56
+ CMAP_sst_tblSST_AVHRR_OI_NRT_avg
57
+ CMAP_sst_tblSST_AVHRR_OI_NRT_std
58
+ CMAP_sst_tblSST_AVHRR_OI_NRT_count
59
+
60
+ :param list aggregations: list of ``(suffix, sqlFunc)`` pairs as produced
61
+ by ``_resolve_aggregations``.
62
+ """
63
+ return [f"CMAP_{varName}_{tableName}_{suffix}" for suffix, _ in aggregations]
21
64
 
22
65
 
23
66
  def add_target_columns(df, targets):
@@ -30,12 +73,12 @@ def add_target_columns(df, targets):
30
73
  return df
31
74
 
32
75
 
33
- def add_target_meta(api, targets, servers):
76
+ def add_target_meta(api, targets, aggregations, servers):
34
77
  """
35
78
  Adds new entries (metadata) to the `targets` dictionary including the
36
79
  temporal coverage of each environmental dataset, if it has depth field,
37
80
  and if it's a climatology dataset.
38
- """
81
+ """
39
82
  for table, env in targets.items():
40
83
  df = api.query(f"SELECT MIN([time]) startTime, MAX([time]) endTime FROM {table}", servers)
41
84
  if len(df) > 0:
@@ -43,9 +86,10 @@ def add_target_meta(api, targets, servers):
43
86
  targets[table]["endTime"] = df.loc[0, "endTime"]
44
87
  targets[table]["hasDepth"] = api.has_field(table, "depth", servers)
45
88
  targets[table]["isClimatology"] = api.is_climatology(table, servers)
89
+ targets[table]["aggregations"] = aggregations
46
90
  targets[table]["aliases"] = []
47
91
  for varName in targets[table]["variables"]:
48
- targets[table]["aliases"].append(alias(varName, table))
92
+ targets[table]["aliases"].extend(alias(varName, table, aggregations))
49
93
  return targets
50
94
 
51
95
 
@@ -87,7 +131,13 @@ def match(df, api, targets, rowIndex, totalRows, replaceWithMonthlyClimatolog, s
87
131
  startTime = env["startTime"]
88
132
  endTime = env["endTime"]
89
133
  inTimeRange = in_time_window(t, startTime, endTime)
90
- selectClause = "SELECT " + ", ".join([f"AVG({v}) {a}" for v, a in zip(variables, aliases)]) + " FROM " + table
134
+ selectClause = "SELECT " + ", ".join(
135
+ [
136
+ f"{sqlFunc}({v}) CMAP_{v}_{table}_{suffix}"
137
+ for v in variables
138
+ for suffix, sqlFunc in env["aggregations"]
139
+ ]
140
+ ) + " FROM " + table
91
141
  timeClause = f" WHERE [time] BETWEEN '{shift_dt(t, -timeTolerance)}' AND '{shift_dt(t, timeTolerance)}' "
92
142
  if (not inTimeRange and replaceWithMonthlyClimatolog) or isClimatology: timeClause = f" WHERE [month]={get_month(t)} "
93
143
  latClause = f" AND lat BETWEEN {lat-latTolerance} AND {lat+latTolerance} "
@@ -108,10 +158,9 @@ def match(df, api, targets, rowIndex, totalRows, replaceWithMonthlyClimatolog, s
108
158
  if 'depth' in df.columns: depth = df.iloc[0]["depth"]
109
159
  for table, env in targets.items():
110
160
  print(f"\rSampling {table} ... {rowIndex+1} / {totalRows}" + " " * 50, end="", flush=True)
111
- # # do the colocalization: if either the target dataset has depth field (it's not sattelite, for example) or
112
- # # the depth of source measurement is less than `MAX_SURFACE_DEPTH`
113
- # if env["hasDepth"] or depth <= MAX_SURFACE_DEPTH:
114
- if True:
161
+ # do the colocalization if either the target dataset has depth field (it's not satellite, for example) or
162
+ # the depth of source measurement is less than `MAX_SURFACE_DEPTH`
163
+ if env["hasDepth"] or depth <= MAX_SURFACE_DEPTH:
115
164
  query = construc_query(table, env, t, lat, lon, depth, replaceWithMonthlyClimatolog)
116
165
  matchedEnv = api.query(query, servers=servers)
117
166
  if len(matchedEnv)>0:
@@ -119,17 +168,17 @@ def match(df, api, targets, rowIndex, totalRows, replaceWithMonthlyClimatolog, s
119
168
  return df
120
169
 
121
170
 
122
- def Sample(source, targets, replaceWithMonthlyClimatolog, servers=["rossby"]):
171
+ def Sample(source, targets, replaceWithMonthlyClimatolog=False, agg_fun=["AVG"], servers=["rossby"]):
123
172
  """
124
173
  placeholder for the `Sample` class.
125
174
 
126
- Samples the targest datasets using the time-location of the source dataset
175
+ Samples the target datasets using the time-location of the source dataset
127
176
  Returns a dataframe containing the original source data and the joined colocalized target variables.
128
177
 
129
178
  :param dataframe source: a dataframe containing the source datasets (must have time-location columns).
130
- :param dictionary targets: dcitionary containing the target table/variables and tolerance parameters.
131
- The items in `tolerances` list are: temporal tolerance [days], meridional tolerance [deg],
132
- zonal tolerance [deg], and vertical tolerance [m], repectively.
179
+ :param dictionary targets: dictionary containing the target table/variables and tolerance parameters.
180
+ The items in `tolerances` list are: temporal tolerance [days], meridional tolerance [deg],
181
+ zonal tolerance [deg], and vertical tolerance [m], respectively.
133
182
  `targets` example:
134
183
 
135
184
  targets = {
@@ -143,11 +192,26 @@ def Sample(source, targets, replaceWithMonthlyClimatolog, servers=["rossby"]):
143
192
  }
144
193
  }
145
194
 
195
+ :param bool replaceWithMonthlyClimatolog: if True, when a source point falls outside the target dataset's
196
+ temporal range, fall back to matching by month (climatological match).
197
+ :param list agg_fun: SQL aggregation functions applied to each target variable.
198
+ Each function produces one output column per variable, named
199
+ ``CMAP_{var}_{table}_{suffix}`` where the suffix is the lowercased
200
+ function name (with friendlier short forms for the common ones:
201
+ ``AVG``->``avg``, ``STDEV``->``std``, ``COUNT``->``count``).
202
+ Case-insensitive. Defaults to ``["AVG"]`` (the historical behavior).
203
+ Example: ``["AVG", "STDEV", "COUNT"]``.
204
+ :param list servers: list of CMAP server names to query against.
205
+
146
206
  """
147
207
  if len(source) > MAX_SAMPLE_SOURCE: halt(f"Source dataset too large. Maximum allowed number of records is {MAX_SAMPLE_SOURCE}.")
208
+ aggregations = _resolve_aggregations(agg_fun)
148
209
  api = API()
149
210
  print("Gathering metadata .... ")
150
- targets = add_target_meta(api, targets, servers)
211
+ for tableName in targets.keys():
212
+ for variable in targets[tableName]["variables"]:
213
+ api._validate_table_var(tableName, variable)
214
+ targets = add_target_meta(api, targets, aggregations, servers)
151
215
  source = add_target_columns(source, targets)
152
216
  dfs = [source.loc[i].to_frame().T for i in range(len(source))]
153
217
  colocalizedList, columns = [], []
@@ -158,4 +222,4 @@ def Sample(source, targets, replaceWithMonthlyClimatolog, servers=["rossby"]):
158
222
  if len(colocalizedList) < 1: columns = list(fo.columns)
159
223
  colocalizedList.append(fo.values.tolist()[0])
160
224
  print("\rSampling finished" + " " * 100, end="")
161
- return pd.DataFrame(colocalizedList, columns=columns)
225
+ return pd.DataFrame(colocalizedList, columns=columns)
@@ -0,0 +1,109 @@
1
+ Metadata-Version: 2.4
2
+ Name: pycmap
3
+ Version: 0.2.20
4
+ Summary: Simons CMAP API python client
5
+ Home-page: https://github.com/simonscmap/pycmap
6
+ Author: Mohammad D. Ashkezari
7
+ Author-email: mdehghan@uw.edu
8
+ Keywords: ocean oceanography data visualization satellite model in-situ remote sensing machine learning
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3.7
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Requires-Dist: numpy
16
+ Requires-Dist: pandas
17
+ Requires-Dist: scipy
18
+ Requires-Dist: bokeh
19
+ Requires-Dist: matplotlib
20
+ Requires-Dist: cmocean
21
+ Requires-Dist: tqdm
22
+ Requires-Dist: folium
23
+ Requires-Dist: colorama
24
+ Requires-Dist: plotly
25
+ Dynamic: author
26
+ Dynamic: author-email
27
+ Dynamic: classifier
28
+ Dynamic: description
29
+ Dynamic: description-content-type
30
+ Dynamic: home-page
31
+ Dynamic: keywords
32
+ Dynamic: license-file
33
+ Dynamic: requires-dist
34
+ Dynamic: summary
35
+
36
+ [![PyPI version](https://badge.fury.io/py/pycmap.svg)](https://badge.fury.io/py/pycmap)
37
+ [![DOI](https://zenodo.org/badge/199070692.svg)](https://zenodo.org/badge/latestdoi/199070692)
38
+ ![Cover](https://github.com/simonscmap/pycmap/raw/master/docs/figures/CMAP.png)
39
+
40
+ *Mohammad Dehghani Ashkezari <mdehghan@uw.edu>*
41
+
42
+
43
+ # pycmap
44
+ Simons CMAP is an open-source data service to retrieve, visualize, and analyze oceanic datasets such as in-situ observations, multi-decade global satellite remote sensing, and model outputs. Pycmap is the python package of Simons CMAP project providing a simple and unified interface to the hosted datasets at Simons CMAP database. It enables the scientists and general public to dive into the vast, and often underutilized, ocean datasets and retrieve customized subsets of these massive datasets without going through the time-consuming process of data collection and preparation.
45
+
46
+ ## Documentation
47
+ See the *table of contents* below for pycmap documentations.
48
+ <br />The docs are written in jupyter notebook format and each notebook contains one or more example codes. Please download the `/docs` directory and run the example codes locally. Alternatively, you may run the examples on google cloud using the *Colab badge* which appears at the top of each page:
49
+ <br /><img align="left" src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open in Colab" title="Open and Execute in Google Colaboratory">
50
+
51
+
52
+ <br /><br />More detailed system documentations can be found at [https://cmap.readthedocs.io/en/latest/](https://cmap.readthedocs.io/en/latest/).
53
+
54
+ ## Website
55
+ Simons CMAP website is under active development at the moment: [https://simonscmap.com](https://simonscmap.com)
56
+
57
+ **<br />This project is supported by [Simons Foundation](https://www.simonsfoundation.org/).**
58
+
59
+
60
+
61
+
62
+ ## Table of Contents
63
+
64
+
65
+ ### [Installation](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Installation.ipynb)
66
+
67
+ ### [1. Data Retrieval (API)](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/API.ipynb)
68
+ - [Query](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Query.ipynb)
69
+ - [Catalog](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Catalog.ipynb)
70
+ - [Search Catalog](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/SearchCatalog.ipynb)
71
+ - [Datasets](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Datasets.ipynb)
72
+ - [Datasets With Ancillary](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/DatasetsWithAncillary.ipynb)
73
+ - [Dataset MetaData](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/DatasetMetaData.ipynb)
74
+ - [Variable MetaData](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/MetaData.ipynb)
75
+ - [Dataset Columns](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Columns.ipynb)
76
+ - [Dataset Head](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Head.ipynb)
77
+ - [Variable Long Name](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/LongName.ipynb)
78
+ - [Variable Unit](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Unit.ipynb)
79
+ - [Variable Resolution](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Resolution.ipynb)
80
+ - [Variable Coverage](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Coverage.ipynb)
81
+ - [Variable Stat](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Stat.ipynb)
82
+ - [If Column Exists](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/HasField.ipynb)
83
+ - [Is Gridded Product](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Grid.ipynb)
84
+ - [Is Climatology Product](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/IsClimatology.ipynb)
85
+ - [List of Cruises](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Cruises.ipynb)
86
+ - [Cruise Details by Name](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/CruiseByName.ipynb)
87
+ - [Cruise Spatio-Temporal Bounds](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/CruiseBounds.ipynb)
88
+ - [Cruise Trajectory](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/CruiseTrajectory.ipynb)
89
+ - [Cruise Variables](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/CruiseVariables.ipynb)
90
+ - [Retrieve Dataset](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/RetrieveDataset.ipynb)
91
+ - [Retrieve Dataset With Ancillary](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/RetrieveDatasetWithAncillary.ipynb)
92
+ - [Data Subset: Generic Space-Time Cut](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/SpaceTime.ipynb)
93
+ - [Data Subset: TimeSeries](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/TimeSeries.ipynb)
94
+ - [Data Subset: Depth Profile](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/DepthProfile.ipynb)
95
+ - [Compute Climatology](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Climatology.ipynb)
96
+ - [Sampling](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Sampling.ipynb)
97
+ - [Match (colocalize) Cruise Track with Datasets](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/MatchCruise.ipynb)
98
+
99
+
100
+ ### [2. Data Visualization](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Viz.ipynb)
101
+ - [Histogram Plot](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Viz_Histogram.ipynb)
102
+ - [TimeSeries Plot](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Viz_TimeSeries.ipynb)
103
+ - [Regional Map, Contour Plot, 3D Surface Plot](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Viz_RegionalMap.ipynb)
104
+ - [Section Map, Section Contour](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Viz_Section.ipynb)
105
+ - [Depth Profile](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Viz_DepthProfile.ipynb)
106
+ - [Cruise Track Plot](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Viz_CruiseTrack.ipynb)
107
+ - [Correlation Matrix](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Viz_CorrelationMatrix.ipynb)
108
+ - [Correlation Matrix Along Cruise Track](https://colab.research.google.com/github/simonscmap/pycmap/blob/master/docs/Viz_CruiseCorrelationMatrix.ipynb)
109
+
@@ -0,0 +1,29 @@
1
+ LICENSE
2
+ README.md
3
+ setup.cfg
4
+ setup.py
5
+ pycmap/__init__.py
6
+ pycmap/annotatedHeatmap.py
7
+ pycmap/baseGraph.py
8
+ pycmap/clean.py
9
+ pycmap/cmap.py
10
+ pycmap/colorMaps.py
11
+ pycmap/common.py
12
+ pycmap/deepC.py
13
+ pycmap/export.py
14
+ pycmap/foliumHeat.py
15
+ pycmap/hist.py
16
+ pycmap/map.py
17
+ pycmap/match.py
18
+ pycmap/rest.py
19
+ pycmap/sample.py
20
+ pycmap/section.py
21
+ pycmap/supervised.py
22
+ pycmap/trend.py
23
+ pycmap/viz.py
24
+ pycmap/w3.py
25
+ pycmap.egg-info/PKG-INFO
26
+ pycmap.egg-info/SOURCES.txt
27
+ pycmap.egg-info/dependency_links.txt
28
+ pycmap.egg-info/requires.txt
29
+ pycmap.egg-info/top_level.txt
pycmap-0.2.18/.DS_Store DELETED
Binary file