diff --git a/Examples/APIDemo.ipynb b/Examples/APIDemo.ipynb index b4f6182..c2f5518 100644 --- a/Examples/APIDemo.ipynb +++ b/Examples/APIDemo.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": 30, "metadata": { "collapsed": false }, @@ -15,7 +15,8 @@ "\n", "import matplotlib.pyplot as plt\n", "from matplotlib import dates\n", - "%matplotlib inline\n", + "%matplotlib notebook\n", + "# inline\n", "\n", "from odm2api.ODMconnection import dbconnection\n", "from odm2api.ODM2.services.readService import *\n", @@ -28,12 +29,12 @@ "session_factory = dbconnection.createConnection('mysql', 'localhost', 'ODM2', 'ODM', 'odm')#mysql\n", "#session_factory = dbconnection.createConnection('connection type: sqlite|mysql|mssql|postgresql', '/your/path/to/db/goes/here', 2.0)#sqlite\n", "# session_factory= dbconnection.createConnection('mssql', \"(local)\", \"LBRODM2\", \"ODM\", \"odm\")#win MSSQL\n", - "# session_factory= dbconnection.createConnection('mssql', \"odm2\", \"\", \"ODM\", \"odm\")#mac/linux MSSQL\n" + "# session_factory= dbconnection.createConnection('mssql', \"odm2\", \"\", \"ODM\", \"odm\")#mac/linux MSSQL" ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 31, "metadata": { "collapsed": false }, @@ -41,90 +42,16 @@ "source": [ "_session = session_factory.getSession()\n", "\n", - "read = ReadODM2(session_factory)\n" + "read = ReadODM2(session_factory)" ] }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 32, "metadata": { "collapsed": false }, "outputs": [], - "source": [ - "# dir (read)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "USU3: Battery voltage\n", - "USU4: Turbidity\n", - "USU5: Turbidity\n", - "USU6: Turbidity\n", - "USU7: Turbidity\n", - "USU8: Turbidity\n", - "USU9: Turbidity\n", - "USU10: Temperature\n", - "USU13: Gage height\n", - "USU14: Temperature\n", - "USU15: Relative humidity\n", - "USU16: Precipitation\n", - "USU17: Battery voltage\n", - "USU18: Wind speed\n", - "USU19: Wind direction\n", - "USU20: Wind direction\n", - "USU21: Barometric pressure\n", - "USU22: Radiation, incoming shortwave\n", - "USU23: Battery voltage\n", - "USU24: Wind speed\n", - "USU25: Temperature\n", - "USU26: Temperature\n", - "USU27: Temperature\n", - "USU28: Relative humidity\n", - "USU29: Barometric pressure\n", - "USU30: Precipitation\n", - "USU31: Radiation, incoming shortwave\n", - "USU32: Oxygen, dissolved\n", - "USU33: Oxygen, dissolved percent of saturation\n", - "USU34: Specific conductance\n", - "USU35: pH\n", - "USU36: Temperature\n", - "USU37: Turbidity\n", - "USU39: Phosphorus, total\n", - "USU40: Phosphorus, total dissolved\n", - "USU41: Solids, total Suspended\n", - "USU44: Discharge\n", - "USU47: Solids, total suspended\n", - "USU48: Phosphorus, total\n", - "USU49: Distance\n", - "USU50: Snow Depth\n", - "USU51: Distance\n", - "USU52: Distance\n", - "USU53: Distance\n", - "USU54: Snow Depth\n", - "USU55: Snow Depth\n", - "USU56: Snow Depth\n", - "USU57: Volumetric water content\n", - "USU58: Electrical conductivity\n", - "USU59: Temperature\n", - "USU60: Temperature\n", - "USU61: Real dielectric constant\n", - "USU62: Imaginary dielectric constant\n", - "USU63: Alkalinity, carbonate plus bicarbonate\n", - "USU64: Nitrogen, total dissolved\n", - "USU65: Nitrogen, total\n" - ] - } - ], "source": [ "# Run some basic sample queries.\n", "# ------------------------------\n", @@ -132,12 +59,12 @@ "allVars = read.getVariables()\n", "\n", "for x in allVars:\n", - " print x.VariableCode + \": \" + x.VariableNameCV\n" + " print x.VariableCode + \": \" + x.VariableNameCV" ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 9, "metadata": { "collapsed": false }, @@ -146,21 +73,11 @@ "name": "stdout", "output_type": "stream", "text": [ - "Jeff Horsburgh\n", - "Nancy Mesner\n", - "Amber Spackman\n", - "\n", - "-------- Information about an Affiliation ---------\n", - "Jeff: 1\n", - "Jeff: 2\n", - "Amber: 3\n", - "Nancy: 4\n", - "Amber: 6\n" + "Jeff Horsburgh\nNancy Mesner\nAmber Spackman\nErin Jones\nJanet Barnette\nJason Bahr\nChris Cox\nUnknown Person\nLisa Ward\n\n-------- Information about an Affiliation ---------\nJeff: 1\nJeff: 2\nAmber: 3\nNancy: 4\nAmber: 6\nJeff: 6\nErin: 46\nJanet: 48\nJason: 45\nChris: 45\nUnknown: 45\nLisa: 47\n" ] } ], "source": [ - "\n", "# Get all of the people from the database\n", "allPeople = read.getPeople()\n", "\n", @@ -169,47 +86,25 @@ "\n", "try:\n", " print \"\\n-------- Information about an Affiliation ---------\"\n", - " allaff = read.getAllAffiliations()\n", + " allaff = read.getAffiliations()\n", " for x in allaff:\n", " print x.PersonObj.PersonFirstName + \": \" + str(x.OrganizationID)\n", "except Exception as e:\n", - " print \"Unable to demo getAllAffiliations\", e\n", - "\n" + " print \"Unable to demo getAllAffiliations\", e" ] }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 33, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "-------- Information about an SamplingFeature of type 'Site'---------\n", - "USU-LBR-Mendon: Little Bear River at Mendon Road near Mendon, Utah\n", - "USU-LBR-SFWeather: Little Bear River South Fork Weather Station near Avon, Utah\n", - "\n", - "-------- Information about an individual SamplingFeature ---------\n", - "The following are some of the attributes of a SamplingFeature retrieved using getSamplingFeatureByCode(): \n", - "\n", - "SamplingFeatureCode: USU-LBR-Mendon\n", - "SamplingFeatureName: Little Bear River at Mendon Road near Mendon, Utah\n", - "SamplingFeatureDescription: Located below county road bridge at Mendon Road crossing\n", - "SamplingFeatureGeotypeCV: Point\n", - "SamplingFeatureGeometry: \u0000\u0000\u0000\u0000\u0001\u0001\u0000\u0000\u0000ž·±Ù‘ü[ÀŽ\u0007[ìöÛD@\n", - "Elevation_m: 1345.0\n" - ] - } - ], + "outputs": [], "source": [ "# Get all of the SamplingFeatures from the database that are Sites\n", "\n", "try:\n", - " siteFeatures = read.getSamplingFeaturesByType('Site')\n", + " siteFeatures = read.getSamplingFeatures(type='Site')\n", " numSites = len(siteFeatures)\n", " print \"\\n-------- Information about an SamplingFeature of type 'Site'---------\"\n", " for x in siteFeatures:\n", @@ -220,7 +115,7 @@ "\n", "# Now get the SamplingFeature object for a SamplingFeature code\n", "try:\n", - " sf = read.getSamplingFeatureByCode('USU-LBR-Mendon')\n", + " sf = read.getSamplingFeatures(codes= ['USU-LBR-Mendon'])[0]\n", " \n", " print \"\\n-------- Information about an individual SamplingFeature ---------\"\n", " print \"The following are some of the attributes of a SamplingFeature retrieved using getSamplingFeatureByCode(): \\n\"\n", @@ -231,29 +126,16 @@ " print \"SamplingFeatureGeometry: %s\" % sf.FeatureGeometry\n", " print \"Elevation_m: %s\" % str(sf.Elevation_m)\n", "except Exception as e:\n", - " print \"Unable to demo getSamplingFeatureByCode: \", e\n", - "\n", - "\n", - "\n" + " print \"Unable to demo getSamplingFeatureByCode: \", e" ] }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 14, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "------------ Create Sampling Feature --------- \n", - "new sampling feature added to database error adding a sampling feature: 'str' object has no attribute 'geom_wkb'\n" - ] - } - ], + "outputs": [], "source": [ "#add sampling feature\n", "print \"\\n------------ Create Sampling Feature --------- \\n\",\n", @@ -279,41 +161,17 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 34, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "------------ Foreign Key Example --------- \n", - "The FeatureAction object for the Result is: \n", - "The Action object for the Result is: \n", - "\n", - "The following are some of the attributes for the Action that created the Result: \n", - "ActionTypeCV: Observation\n", - "ActionDescription: Sensor deployment and \r\n", - "\tobservation. This is a generic Observation Action created for a Time Series \r\n", - "\tResult loaded into ODM2\tfrom an ODM 1.1.1 database.\n", - "BeginDateTime: 2007-09-01 00:00:00\n", - "EndDateTime: 2007-09-30 23:30:00\n", - "MethodName: Battery voltage measured by Campbell Scientific CR206 datalogger.\n", - "MethodDescription: Battery voltage measured by Campbell Scientific CR206 datalogger.\n" - ] - } - ], + "outputs": [], "source": [ - "\n", "# Drill down and get objects linked by foreign keys\n", "print \"\\n------------ Foreign Key Example --------- \\n\",\n", "try:\n", " # Call getResults, but return only the first result\n", - " firstResult = read.getResults()[0]\n", + " firstResult = read.getResult()[0]\n", " print \"The FeatureAction object for the Result is: \", firstResult.FeatureActionObj\n", " print \"The Action object for the Result is: \", firstResult.FeatureActionObj.ActionObj\n", " print (\"\\nThe following are some of the attributes for the Action that created the Result: \\n\" +\n", @@ -324,15 +182,12 @@ " \"MethodName: \" + firstResult.FeatureActionObj.ActionObj.MethodObj.MethodName + \"\\n\" +\n", " \"MethodDescription: \" + firstResult.FeatureActionObj.ActionObj.MethodObj.MethodDescription)\n", "except Exception as e:\n", - " print \"Unable to demo Foreign Key Example: \", e\n", - "\n", - "\n", - "\n" + " print \"Unable to demo Foreign Key Example: \", e" ] }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 28, "metadata": { "collapsed": false }, @@ -341,16 +196,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "\n", - "------- Example of Retrieving Attributes of a Time Series Result -------\n", - "The following are some of the attributes for the TimeSeriesResult retrieved using getTimeSeriesResultByResultID(): \n", - "ResultTypeCV: Time series coverage\n", - "ProcessingLevel: Raw data\n", - "SampledMedium: Not applicable\n", - "Variable: USU3: Battery voltage\n", - "AggregationStatistic: Minimum\n", - "Elevation_m: 1345.0\n", - "SamplingFeature: USU-LBR-Mendon - Little Bear River at Mendon Road near Mendon, Utah\n" + "\n------- Example of Retrieving Attributes of a Time Series Result -------\nThe following are some of the attributes for the TimeSeriesResult retrieved using getTimeSeriesResultByResultID(): \nResultTypeCV: Time series coverage\nProcessingLevel: Raw data\nSampledMedium: Not applicable\nVariable: USU3: Battery voltage\nAggregationStatistic: Minimum\nElevation_m: 1345.0\nSamplingFeature: USU-LBR-Mendon - Little Bear River at Mendon Road near Mendon, Utah\n" ] } ], @@ -358,77 +204,38 @@ "# Now get a particular Result using a ResultID\n", "print \"\\n------- Example of Retrieving Attributes of a Time Series Result -------\"\n", "try:\n", - " tsResult = read.getTimeSeriesResultByResultId(1)\n", + " #tsResult = read.getTimeSeriesResultByResultId(1)\n", + " tsResult = read.getResults(ids = [1])[0]\n", " print (\n", " \"The following are some of the attributes for the TimeSeriesResult retrieved using getTimeSeriesResultByResultID(): \\n\" +\n", - " \"ResultTypeCV: \" + tsResult.ResultObj.ResultTypeCV + \"\\n\" +\n", + " \"ResultTypeCV: \" + tsResult.ResultTypeCV + \"\\n\" +\n", " # Get the ProcessingLevel from the TimeSeriesResult's ProcessingLevel object\n", - " \"ProcessingLevel: \" + tsResult.ResultObj.ProcessingLevelObj.Definition + \"\\n\" +\n", - " \"SampledMedium: \" + tsResult.ResultObj.SampledMediumCV + \"\\n\" +\n", + " \"ProcessingLevel: \" + tsResult.ProcessingLevelObj.Definition + \"\\n\" +\n", + " \"SampledMedium: \" + tsResult.SampledMediumCV + \"\\n\" +\n", " # Get the variable information from the TimeSeriesResult's Variable object\n", - " \"Variable: \" + tsResult.ResultObj.VariableObj.VariableCode + \": \" + tsResult.ResultObj.VariableObj.VariableNameCV + \"\\n\"\n", + " \"Variable: \" + tsResult.VariableObj.VariableCode + \": \" + tsResult.VariableObj.VariableNameCV + \"\\n\"\n", " \"AggregationStatistic: \" + tsResult.AggregationStatisticCV + \"\\n\" +\n", " \"Elevation_m: \" + str(sf.Elevation_m) + \"\\n\" +\n", " # Get the site information by drilling down\n", - " \"SamplingFeature: \" + tsResult.ResultObj.FeatureActionObj.SamplingFeatureObj.SamplingFeatureCode + \" - \" +\n", - " tsResult.ResultObj.FeatureActionObj.SamplingFeatureObj.SamplingFeatureName)\n", + " \"SamplingFeature: \" + tsResult.FeatureActionObj.SamplingFeatureObj.SamplingFeatureCode + \" - \" +\n", + " tsResult.FeatureActionObj.SamplingFeatureObj.SamplingFeatureName)\n", "except Exception as e:\n", " print \"Unable to demo Example of retrieving Attributes of a time Series Result: \", e" ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 27, "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "-------- Example of Retrieving Time Series Result Values ---------\n", - " \n", - " ValueID ResultID DataValue ValueDateTime ValueDateTimeUTCOffset \\\n", - "0 1947519 1 11.71689 2007-09-30 04:30:00 -7 \n", - "1 1948350 1 11.73368 2007-09-30 02:30:00 -7 \n", - "2 1952427 1 11.79663 2007-09-29 22:30:00 -7 \n", - "3 1955496 1 11.83189 2007-09-29 19:00:00 -7 \n", - "4 1957822 1 11.86547 2007-09-29 16:30:00 -7 \n", - "\n", - " CensorCodeCV QualityCodeCV TimeAggregationInterval \\\n", - "0 Not censored Unknown 30.0 \n", - "1 Not censored Unknown 30.0 \n", - "2 Not censored Unknown 30.0 \n", - "3 Not censored Unknown 30.0 \n", - "4 Not censored Unknown 30.0 \n", - "\n", - " TimeAggregationIntervalUnitsID \n", - "0 102 \n", - "1 102 \n", - "2 102 \n", - "3 102 \n", - "4 102 \n" - ] - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "# Get the values for a particular TimeSeriesResult\n", "print \"\\n-------- Example of Retrieving Time Series Result Values ---------\"\n", "\n", - "tsValues = read.getTimeSeriesResultValuesByResultId(1) # Return type is a pandas dataframe\n", "\n", + "tsValues = read.getResultValues(resultid =1) # Return type is a pandas dataframe\n", "# Print a few Time Series Values to the console\n", "try:\n", " print tsValues.head()\n", @@ -441,9 +248,9 @@ " fig = plt.figure()\n", " ax = fig.add_subplot(111)\n", " tsValues.plot(x='ValueDateTime', y='DataValue', kind='line',\n", - " title=tsResult.ResultObj.VariableObj.VariableNameCV + \" at \" + tsResult.ResultObj.FeatureActionObj.SamplingFeatureObj.SamplingFeatureName,\n", + " title=tsResult.VariableObj.VariableNameCV + \" at \" + tsResult.FeatureActionObj.SamplingFeatureObj.SamplingFeatureName,\n", " ax=ax)\n", - " ax.set_ylabel(tsResult.ResultObj.VariableObj.VariableNameCV + \" (\" + tsResult.ResultObj.UnitsObj.UnitsAbbreviation + \")\")\n", + " ax.set_ylabel(tsResult.VariableObj.VariableNameCV + \" (\" + tsResult.UnitsObj.UnitsAbbreviation + \")\")\n", " ax.set_xlabel(\"Date/Time\")\n", " ax.xaxis.set_minor_locator(dates.MonthLocator())\n", " ax.xaxis.set_minor_formatter(dates.DateFormatter('%b'))\n", @@ -452,18 +259,17 @@ " ax.grid(True)\n", " plt.show()\n", "except Exception as e:\n", - " print \"Unable to demo plotting of tsValues: \", e\n", - "\n" + " print \"Unable to demo plotting of tsValues: \", e" ] }, { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], - "source": [] + "source": [ + "" + ] } ], "metadata": { @@ -475,7 +281,7 @@ "language_info": { "codemirror_mode": { "name": "ipython", - "version": 2 + "version": 2.0 }, "file_extension": ".py", "mimetype": "text/x-python", @@ -487,4 +293,4 @@ }, "nbformat": 4, "nbformat_minor": 0 -} +} \ No newline at end of file diff --git a/Examples/Sample.py b/Examples/Sample.py index 95d7f02..c4798b6 100644 --- a/Examples/Sample.py +++ b/Examples/Sample.py @@ -2,7 +2,7 @@ -# import matplotlib.pyplot as plt +#import matplotlib.pyplot as plt @@ -17,8 +17,8 @@ #connect to database # createconnection (dbtype, servername, dbname, username, password) # session_factory = dbconnection.createConnection('connection type: sqlite|mysql|mssql|postgresql', '/your/path/to/db/goes/here', 2.0)#sqlite -session_factory = dbconnection.createConnection('mysql', 'localhost', 'odm2', 'ODM', 'odm')#mysql -# session_factory= dbconnection.createConnection('mssql', "(local)", "LBRODM2", "ODM", "odm")#win MSSQL +# session_factory = dbconnection.createConnection('mysql', 'localhost', 'odm2', 'ODM', 'odm')#mysql +session_factory= dbconnection.createConnection('mssql', "(local)", "ODM2", "ODM", "odm")#win MSSQL # session_factory= dbconnection.createConnection('mssql', "arroyoodm2", "", "ODM", "odm")#mac/linux MSSQL # session_factory = dbconnection.createConnection('sqlite', '/Users/stephanie/DEV/ODM2/usecases/WOF_to_ODM2/ODM2.sqlite', 2.0) diff --git a/condaenvironment_1.yml b/condaenvironment_1.yml index 325b37e..69189a2 100644 --- a/condaenvironment_1.yml +++ b/condaenvironment_1.yml @@ -4,7 +4,7 @@ channels: dependencies: - python=2.7 - pip - - ipython-notebook + - jupyter - scipy - pandas - seaborn @@ -12,4 +12,3 @@ dependencies: - psycopg2 - pymysql - pyodbc - - shapely diff --git a/odm2api/ODM1_1_1/services/__init__.py b/odm2api/ODM1_1_1/services/__init__.py index 3635c4a..0797c25 100644 --- a/odm2api/ODM1_1_1/services/__init__.py +++ b/odm2api/ODM1_1_1/services/__init__.py @@ -1,8 +1,8 @@ __author__ = 'stephanie' # from cv_service import CVService, refreshDB -from series_service import ODM, SeriesService -from edit_service import EditService -from export_service import ExportService +from odm2api.ODM1_1_1.services.series_service import ODM, SeriesService +from odm2api.ODM1_1_1.services.edit_service import EditService +from odm2api.ODM1_1_1.services.export_service import ExportService __all__ = [ 'SeriesService', 'EditService', 'ExportService', 'ODM'] # 'CVService', diff --git a/odm2api/ODM1_1_1/services/edit_service.py b/odm2api/ODM1_1_1/services/edit_service.py index 352296e..725c393 100644 --- a/odm2api/ODM1_1_1/services/edit_service.py +++ b/odm2api/ODM1_1_1/services/edit_service.py @@ -1,7 +1,7 @@ import sqlite3 #from ...versionSwitcher import ODM -from series_service import SeriesService +from odm2api.ODM1_1_1.services import SeriesService #from odmtools.odmdata import series as series_module diff --git a/odm2api/ODM2/LikeODM1/__init__.py b/odm2api/ODM2/LikeODM1/__init__.py index 426015b..8ba2a65 100644 --- a/odm2api/ODM2/LikeODM1/__init__.py +++ b/odm2api/ODM2/LikeODM1/__init__.py @@ -31,7 +31,7 @@ from series import copy_series from data_value import copy_data_value ''' -import models +import odm2api.ODM1_1_1.models __all__ = [ 'Base', diff --git a/odm2api/ODM2/models.py b/odm2api/ODM2/models.py index ef66405..aa693cb 100644 --- a/odm2api/ODM2/models.py +++ b/odm2api/ODM2/models.py @@ -1,15 +1,9 @@ -from sqlalchemy import BigInteger, Column, Date, DateTime, Float, ForeignKey, Integer, String, Boolean, BLOB, case +from sqlalchemy import BigInteger, Column, Date, DateTime, Float, ForeignKey, Integer, String, Boolean, case from sqlalchemy.orm import relationship from sqlalchemy.dialects import postgresql, mysql, sqlite -# from sqlalchemy.dialects.sqlite import BIT -from geoalchemy import GeometryDDL, GeometryColumn -from geoalchemy.geometry import Geometry -from shapely import wkb, wkt - from odm2api.base import modelBase -# from apiCustomType import Geometry Base = modelBase.Base @@ -18,8 +12,8 @@ BigIntegerType = BigIntegerType.with_variant(postgresql.BIGINT(), 'postgresql') BigIntegerType = BigIntegerType.with_variant(mysql.BIGINT(), 'mysql') -# BooleanType = Boolean() -# BooleanType =BooleanType.with_variant(sqlite.BIT(), 'sqlite') + + def is_hex(s): @@ -279,9 +273,8 @@ class SamplingFeatures(Base): index=True) Elevation_m = Column('elevation_m', Float(53)) ElevationDatumCV = Column('elevationdatumcv', ForeignKey(CVElevationDatum.Name), index=True) - FeatureGeometry = Column('featuregeometry', String(50))#Geometry) # + #FeatureGeometry = Column('featuregeometry', String(50)) FeatureGeometryWKT = Column('featuregeometrywkt', String(50)) - # FeatureGeometry = Column('featuregeometry', BLOB) # custom geometry queries __mapper_args__ = { # 'polymorphic_on': SamplingFeatureTypeCV, "polymorphic_on":case([ @@ -293,33 +286,7 @@ class SamplingFeatures(Base): } - - # def shape(self): - # """ - # Method name based on shapely shapely.geometry.shape() function. - # Returns a shapely geometry object - # :return geomshape: - # """ - # _FeatureGeometry = self.FeatureGeometry - # geomshape = None - # if _FeatureGeometry is not None: - # print _FeatureGeometry - # print _FeatureGeometry.geom_wkb - # if is_hex(_FeatureGeometry.geom_wkb): - # # to parse wkb hex string directly - # geomshape = wkb.loads(_FeatureGeometry.geom_wkb, hex=True) - # # _FeatureGeometry = GeometryColumn('featuregeometry', Geometry) - # else: - # geomshape = wkt.loads(str(_FeatureGeometry.geom_wkb)) - # - # return geomshape - def __repr__(self): - # geom = self.shape() - # if geom is not None: - # geomkt = geom.wkt - # else: - # geomkt = None return "" % ( self.SamplingFeatureCode, self.SamplingFeatureName, self.SamplingFeatureDescription, @@ -327,8 +294,6 @@ def __repr__(self): self.Elevation_m, self.FeatureGeometryWKT) -# GeometryDDL(SamplingFeatures.__table__) # Geoalchemy1 - class FeatureActions(Base): __tablename__ = u'featureactions' @@ -1523,10 +1488,10 @@ class PointCoverageResults(Results): TimeAggregationInterval = Column('timeaggregationinterval', Float(53), nullable=False) TimeAggregationIntervalUnitsID = Column('timeaggregationintervalunitsid', Integer, nullable=False) - XUnitObj = relationship(Units, primaryjoin='PointCoverageResults.IntendedXSpacingUnitsID == Units.UnitsID') - YUnitObj = relationship(Units, primaryjoin='PointCoverageResults.IntendedYSpacingUnitsID == Units.UnitsID') + IntendedXSpacingUnitsObj = relationship(Units, primaryjoin='PointCoverageResults.IntendedXSpacingUnitsID == Units.UnitsID') + IntendedYSpacingUnitsObj = relationship(Units, primaryjoin='PointCoverageResults.IntendedYSpacingUnitsID == Units.UnitsID') SpatialReferenceObj = relationship(SpatialReferences) - ZUnitObj = relationship(Units, primaryjoin='PointCoverageResults.ZLocationUnitsID == Units.UnitsID') + ZLocationUnitsObj = relationship(Units, primaryjoin='PointCoverageResults.ZLocationUnitsID == Units.UnitsID') # ResultObj = relationship(Results, primaryjoin='PointCoverageResults.ResultID == Results.ResultID') __mapper_args__ = {'polymorphic_identity':'Point coverage'} @@ -1549,11 +1514,11 @@ class ProfileResults(Results): AggregationStatisticCV = Column('aggregationstatisticcv', ForeignKey(CVAggregationStatistic.Name), nullable=False, index=True) - TimeUnitObj = relationship(Units, primaryjoin='ProfileResults.IntendedTimeSpacingUnitsID == Units.UnitsID') - ZUnitObj = relationship(Units, primaryjoin='ProfileResults.IntendedZSpacingUnitsID == Units.UnitsID') + IntendedTimeSpacingUnitsObj = relationship(Units, primaryjoin='ProfileResults.IntendedTimeSpacingUnitsID == Units.UnitsID') + IntendedZSpacingUnitsObj = relationship(Units, primaryjoin='ProfileResults.IntendedZSpacingUnitsID == Units.UnitsID') SpatialReferenceObj = relationship(SpatialReferences) - XUnitObj = relationship(Units, primaryjoin='ProfileResults.XLocationUnitsID == Units.UnitsID') - YUnitObj = relationship(Units, primaryjoin='ProfileResults.YLocationUnitsID == Units.UnitsID') + XLocationUnitsObj = relationship(Units, primaryjoin='ProfileResults.XLocationUnitsID == Units.UnitsID') + YLocationUnitsObj = relationship(Units, primaryjoin='ProfileResults.YLocationUnitsID == Units.UnitsID') # ResultObj = relationship(Results, primaryjoin='ProfileResults.ResultID == Results.ResultID') __mapper_args__ = {'polymorphic_identity':'Profile Coverage'} @@ -1564,15 +1529,19 @@ class CategoricalResults(Results): ResultID = Column('resultid', ForeignKey(Results.ResultID), primary_key=True) XLocation = Column('xlocation', Float(53)) - XLocationUnitsID = Column('xlocationunitsid', Integer) + XLocationUnitsID = Column('xlocationunitsid', Integer, ForeignKey(Units.UnitsID)) YLocation = Column('ylocation', Float(53)) - YLocationUnitsID = Column('ylocationunitsid', Integer) + YLocationUnitsID = Column('ylocationunitsid', Integer, ForeignKey(Units.UnitsID)) ZLocation = Column('zlocation', Float(53)) - ZLocationUnitsID = Column('zlocationunitsid', Integer) + ZLocationUnitsID = Column('zlocationunitsid', Integer, ForeignKey(Units.UnitsID)) SpatialReferenceID = Column('spatialreferenceid', ForeignKey(SpatialReferences.SpatialReferenceID)) QualityCodeCV = Column('qualitycodecv', ForeignKey(CVQualityCode.Name), nullable=False, index=True) SpatialReferenceObj = relationship(SpatialReferences) + XLocationUnitsObj = relationship(Units, primaryjoin='CategoricalResults.XLocationUnitsID == Units.UnitsID') + YLocationUnitsObj = relationship(Units, primaryjoin='CategoricalResults.YLocationUnitsID == Units.UnitsID') + ZLocationUnitsObj = relationship(Units, primaryjoin='CategoricalResults.ZLocationUnitsID == Units.UnitsID') + # ResultObj = relationship(Results, primaryjoin='CategoricalResults.ResultID == Results.ResultID') __mapper_args__ = {'polymorphic_identity':'Category coverage'} @@ -1592,10 +1561,10 @@ class TransectResults(Results): AggregationStatisticCV = Column('aggregationstatisticcv', ForeignKey(CVAggregationStatistic.Name), nullable=False, index=True) - TimeUnitObj = relationship(Units, primaryjoin='TransectResults.IntendedTimeSpacingUnitsID == Units.UnitsID') - TransectUnitObj = relationship(Units, primaryjoin='TransectResults.IntendedTransectSpacingUnitsID == Units.UnitsID') + IntendedTimeSpacingUnitsObj = relationship(Units, primaryjoin='TransectResults.IntendedTimeSpacingUnitsID == Units.UnitsID') + IntendedTransectSpacingUnitsObj = relationship(Units, primaryjoin='TransectResults.IntendedTransectSpacingUnitsID == Units.UnitsID') SpatialReferenceObj = relationship(SpatialReferences) - ZUnitObj = relationship(Units, primaryjoin='TransectResults.ZLocationUnitsID == Units.UnitsID') + ZLocationUnitsObj = relationship(Units, primaryjoin='TransectResults.ZLocationUnitsID == Units.UnitsID') # ResultObj = relationship(Results, primaryjoin='TransectResults.ResultID == Results.ResultID') __mapper_args__ = {'polymorphic_identity':'Transect Coverage'} @@ -1617,11 +1586,11 @@ class SpectraResults(Results): AggregationStatisticCV = Column('aggregationstatisticcv', ForeignKey(CVAggregationStatistic.Name), nullable=False, index=True) - WaveUnitObj = relationship(Units, primaryjoin='SpectraResults.IntendedWavelengthSpacingUnitsID == Units.UnitsID') + IntendedWavelengthSpacingUnitsObj = relationship(Units, primaryjoin='SpectraResults.IntendedWavelengthSpacingUnitsID == Units.UnitsID') SpatialReferenceObj = relationship(SpatialReferences) - XUnitObj = relationship(Units, primaryjoin='SpectraResults.XLocationUnitsID == Units.UnitsID') - YUnitObj = relationship(Units, primaryjoin='SpectraResults.YLocationUnitsID == Units.UnitsID') - ZUnitObj = relationship(Units, primaryjoin='SpectraResults.ZLocationUnitsID == Units.UnitsID') + XLocationUnitsObj = relationship(Units, primaryjoin='SpectraResults.XLocationUnitsID == Units.UnitsID') + YLocationUnitsObj = relationship(Units, primaryjoin='SpectraResults.YLocationUnitsID == Units.UnitsID') + ZLocationUnitsObj = relationship(Units, primaryjoin='SpectraResults.ZLocationUnitsID == Units.UnitsID') # ResultObj = relationship(Results, primaryjoin='SpectraResults.ResultID == Results.ResultID') __mapper_args__ = {'polymorphic_identity':'Spectra coverage'} @@ -1653,12 +1622,11 @@ class TimeSeriesResults(Results): # ResultObj = relationship(Results, primaryjoin='TimeSeriesResults.ResultID == Results.ResultID') __mapper_args__ = {'polymorphic_identity':'Time series coverage'} - def __repr__(self): - return "" % \ - ( self.FeatureActionID, self.ProcessingLevelID, self.VariableID, self.ProcessinglevelID, - self.self.XLocation, self.YLocation, - self.ResultTypeCV, - self.IntendedTimeSpacing, self.AggregationStatisticCV) + # def __repr__(self): + # return "" % \ + # ( self.FeatureActionID, self.ProcessingLevelID, self.VariableID, + # self.self.XLocation, self.YLocation, self.ResultTypeCV, + # self.IntendedTimeSpacing, self.AggregationStatisticCV) class SectionResults(Results): @@ -1678,11 +1646,11 @@ class SectionResults(Results): AggregationStatisticCV = Column('aggregationstatisticcv', ForeignKey(CVAggregationStatistic.Name), nullable=False, index=True) - TimeUnitObj = relationship(Units, primaryjoin='SectionResults.IntendedTimeSpacingUnitsID == Units.UnitsID') - XUnitObj = relationship(Units, primaryjoin='SectionResults.IntendedXSpacingUnitsID == Units.UnitsID') - ZUnitObj = relationship(Units, primaryjoin='SectionResults.IntendedZSpacingUnitsID == Units.UnitsID') + IntendedTimeSpacingUnitsObj = relationship(Units, primaryjoin='SectionResults.IntendedTimeSpacingUnitsID == Units.UnitsID') + IntendedXSpacingUnitsObj = relationship(Units, primaryjoin='SectionResults.IntendedXSpacingUnitsID == Units.UnitsID') + IntendedZSpacingUnitsObj = relationship(Units, primaryjoin='SectionResults.IntendedZSpacingUnitsID == Units.UnitsID') SpatialReferenceObj = relationship(SpatialReferences) - YUnitObj = relationship(Units, primaryjoin='SectionResults.YLocationUnitsID == Units.UnitsID') + YLocationUnitsObj = relationship(Units, primaryjoin='SectionResults.YLocationUnitsID == Units.UnitsID') # ResultObj = relationship(Results, primaryjoin='SectionResults.ResultID == Results.ResultID') __mapper_args__ = {'polymorphic_identity':'Section coverage'} @@ -1700,8 +1668,8 @@ class TrajectoryResults(Results): AggregationStatisticCV = Column('aggregationstatisticcv', ForeignKey(CVAggregationStatistic.Name), nullable=False, index=True) - TimeUnitObj = relationship(Units, primaryjoin='TrajectoryResults.IntendedTimeSpacingUnitsID == Units.UnitsID') - TrajectoryUnitObj = relationship(Units, + IntendedTimeSpacingUnitsObj = relationship(Units, primaryjoin='TrajectoryResults.IntendedTimeSpacingUnitsID == Units.UnitsID') + IntendedTrajectorySpacingUnitsObj = relationship(Units, primaryjoin='TrajectoryResults.IntendedTrajectorySpacingUnitsID == Units.UnitsID') SpatialReferenceObj = relationship(SpatialReferences) # ResultObj = relationship(Results, primaryjoin='TrajectoryResults.ResultID == Results.ResultID') @@ -1729,7 +1697,7 @@ class MeasurementResults(Results): nullable=False) SpatialReferenceObj = relationship(SpatialReferences) - TimeUnitObj = relationship(Units, primaryjoin='MeasurementResults.TimeAggregationIntervalUnitsID == Units.UnitsID') + TimeAggregationIntervalUnitsObj = relationship(Units, primaryjoin='MeasurementResults.TimeAggregationIntervalUnitsID == Units.UnitsID') XLocationUnitsObj = relationship(Units, primaryjoin='MeasurementResults.XLocationUnitsID == Units.UnitsID') YLocationUnitsObj = relationship(Units, primaryjoin='MeasurementResults.YLocationUnitsID == Units.UnitsID') ZLocationUnitsObj = relationship(Units, primaryjoin='MeasurementResults.ZLocationUnitsID == Units.UnitsID') @@ -1753,7 +1721,7 @@ class CategoricalResultValues(Base): ValueDateTime = Column('valuedatetime', DateTime, nullable=False) ValueDateTimeUTCOffset = Column('valuedatetimeutcoffset', Integer, nullable=False) - CategoricalResultObj = relationship(CategoricalResults) + ResultObj = relationship(CategoricalResults) class MeasurementResultValues(Base): @@ -1766,7 +1734,7 @@ class MeasurementResultValues(Base): ValueDateTime = Column('valuedatetime', DateTime, nullable=False) ValueDateTimeUTCOffset = Column('valuedatetimeutcoffset', Integer, nullable=False) - MeasurementResultObj = relationship(MeasurementResults) + ResultObj = relationship(MeasurementResults) def __repr__(self): return "" % (self.DataValue, self.ValueDateTime, self.ResultID) @@ -1788,9 +1756,9 @@ class PointCoverageResultValues(Base): CensorCodeCV = Column('censorcodecv', ForeignKey(CVCensorCode.Name), nullable=False, index=True) QualityCodeCV = Column('qualitycodecv', ForeignKey(CVQualityCode.Name), nullable=False, index=True) - PointCoverageResultObj = relationship(PointCoverageResults) - XUnitObj = relationship(Units, primaryjoin='PointCoverageResultValues.XLocationUnitsID == Units.UnitsID') - YUnitObj = relationship(Units, primaryjoin='PointCoverageResultValues.YLocationUnitsID == Units.UnitsID') + ResultObj = relationship(PointCoverageResults) + XLocationUnitsObj = relationship(Units, primaryjoin='PointCoverageResultValues.XLocationUnitsID == Units.UnitsID') + YLocationUnitsobj = relationship(Units, primaryjoin='PointCoverageResultValues.YLocationUnitsID == Units.UnitsID') class ProfileResultValues(Base): @@ -1811,9 +1779,9 @@ class ProfileResultValues(Base): TimeAggregationIntervalUnitsID = Column('timeaggregationintervalunitsid', ForeignKey(Units.UnitsID), nullable=False) - ProfileResultObj = relationship(ProfileResults) - TimeUnitObj = relationship(Units, primaryjoin='ProfileResultValues.TimeAggregationIntervalUnitsID == Units.UnitsID') - ZUnitObj = relationship(Units, primaryjoin='ProfileResultValues.ZLocationUnitsID == Units.UnitsID') + ResultObj = relationship(ProfileResults) + TimeAggregationIntervalUnitsObj = relationship(Units, primaryjoin='ProfileResultValues.TimeAggregationIntervalUnitsID == Units.UnitsID') + ZLocationUnitsObj = relationship(Units, primaryjoin='ProfileResultValues.ZLocationUnitsID == Units.UnitsID') class SectionResultValues(Base): @@ -1839,10 +1807,10 @@ class SectionResultValues(Base): TimeAggregationIntervalUnitsID = Column('timeaggregationintervalunitsid', ForeignKey(Units.UnitsID), nullable=False) - SectionResultObj = relationship(SectionResults) - TimeUnitObj = relationship(Units, primaryjoin='SectionResultValues.TimeAggregationIntervalUnitsID == Units.UnitsID') - XUnitObj = relationship(Units, primaryjoin='SectionResultValues.XLocationUnitsID == Units.UnitsID') - ZUnitObj = relationship(Units, primaryjoin='SectionResultValues.ZLocationUnitsID == Units.UnitsID') + ResultObj = relationship(SectionResults) + TimeAggregationIntervalUnitsObj = relationship(Units, primaryjoin='SectionResultValues.TimeAggregationIntervalUnitsID == Units.UnitsID') + XLocationUnitsObj = relationship(Units, primaryjoin='SectionResultValues.XLocationUnitsID == Units.UnitsID') + ZLocationUnitsObj = relationship(Units, primaryjoin='SectionResultValues.ZLocationUnitsID == Units.UnitsID') class SpectraResultValues(Base): @@ -1863,9 +1831,9 @@ class SpectraResultValues(Base): TimeAggregationIntervalUnitsID = Column('timeaggregationintervalunitsid', ForeignKey(Units.UnitsID), nullable=False) - SpectraResultObj = relationship(SpectraResults) - TimeUnitObj = relationship(Units, primaryjoin='SpectraResultValues.TimeAggregationIntervalUnitsID == Units.UnitsID') - WavelengthUnitObj = relationship(Units, primaryjoin='SpectraResultValues.WavelengthUnitsID == Units.UnitsID') + ResultObj = relationship(SpectraResults) + TimeAggregationIntervalUnitsObj = relationship(Units, primaryjoin='SpectraResultValues.TimeAggregationIntervalUnitsID == Units.UnitsID') + WavelengthUnitsObj = relationship(Units, primaryjoin='SpectraResultValues.WavelengthUnitsID == Units.UnitsID') class TimeSeriesResultValues(Base): @@ -1883,8 +1851,8 @@ class TimeSeriesResultValues(Base): TimeAggregationIntervalUnitsID = Column('timeaggregationintervalunitsid', ForeignKey(Units.UnitsID), nullable=False) - TimeSeriesResultObj = relationship(TimeSeriesResults) - TimeUnitObj = relationship(Units) + ResultObj = relationship(TimeSeriesResults) + TimeAggregationIntervalUnitsObj = relationship(Units) def get_columns(self): return ["ValueID", "ResultID", "DataValue", "ValueDateTime", "ValueDateTimeUTCOffset", @@ -1924,12 +1892,12 @@ class TrajectoryResultValues(Base): TimeAggregationIntervalUnitsID = Column('timeaggregationintervalunitsid', ForeignKey(Units.UnitsID), nullable=False) - TrajectoryResultObj = relationship(TrajectoryResults) - TimeUnitObj = relationship(Units, + ResultObj = relationship(TrajectoryResults) + TimeAggregationIntervalUnitsObj = relationship(Units, primaryjoin='TrajectoryResultValues.TimeAggregationIntervalUnitsID == Units.UnitsID') - XUnitObj = relationship(Units, primaryjoin='TrajectoryResultValues.XLocationUnitsID == Units.UnitsID') - YUnitObj = relationship(Units, primaryjoin='TrajectoryResultValues.YLocationUnitsID == Units.UnitsID') - ZUnitObj = relationship(Units, primaryjoin='TrajectoryResultValues.ZLocationUnitsID == Units.UnitsID') + XLocationUnitsObj = relationship(Units, primaryjoin='TrajectoryResultValues.XLocationUnitsID == Units.UnitsID') + YLocationUnitsObj = relationship(Units, primaryjoin='TrajectoryResultValues.YLocationUnitsID == Units.UnitsID') + ZLocationUnitsObj = relationship(Units, primaryjoin='TrajectoryResultValues.ZLocationUnitsID == Units.UnitsID') class TransectResultValues(Base): @@ -1942,20 +1910,25 @@ class TransectResultValues(Base): ValueDateTime = Column('valuedatetime', DateTime, nullable=False) ValueDateTimeUTCOffset = Column('valuedatetimeutcoffset', DateTime, nullable=False) XLocation = Column('xlocation', Float(53), nullable=False) - XLocationUnitsID = Column('xlocationunitsid', Integer, nullable=False) + XLocationUnitsID = Column('xlocationunitsid', ForeignKey(Units.UnitsID), nullable=False) YLocation = Column('ylocation', Float(53), nullable=False) - YLocationUnitsID = Column('ylocationunitsid', Integer, nullable=False) + YLocationUnitsID = Column('ylocationunitsid', ForeignKey(Units.UnitsID), nullable=False) TransectDistance = Column('transectdistance', Float(53), nullable=False) TransectDistanceAggregationInterval = Column('transectdistanceaggregationinterval', Float(53), nullable=False) - TransectDistanceUnitsID = Column('transectdistanceunitsid', Integer, nullable=False) + TransectDistanceUnitsID = Column('transectdistanceunitsid', ForeignKey(Units.UnitsID), nullable=False) CensorCodeCV = Column('censorcodecv', ForeignKey(CVCensorCode.Name), nullable=False, index=True) QualityCodeCV = Column('qualitycodecv', ForeignKey(CVQualityCode.Name), nullable=False, index=True) AggregationStatisticCV = Column('aggregationstatisticcv', ForeignKey(CVAggregationStatistic.Name), nullable=False, index=True) TimeAggregationInterval = Column('timeaggregationinterval', Float(53), nullable=False) - TimeAggregationIntervalUnitsID = Column('timeaggregationintervalunitsid', Integer, nullable=False) - - TransectResultObj = relationship(TransectResults) + TimeAggregationIntervalUnitsID = Column('timeaggregationintervalunitsid', ForeignKey(Units.UnitsID), nullable=False) + + ResultObj = relationship(TransectResults) + TimeAggregationIntervalUnitsObj = relationship(Units, + primaryjoin='TransectResultValues.TimeAggregationIntervalUnitsID == Units.UnitsID') + XLocationUnitsObj = relationship(Units, primaryjoin='TransectResultValues.XLocationUnitsID == Units.UnitsID') + YLocationUnitsObj = relationship(Units, primaryjoin='TransectResultValues.YLocationUnitsID == Units.UnitsID') + TransectDistanceUnitsObj = relationship(Units, primaryjoin='TransectResultValues.TransectDistanceUnitsID == Units.UnitsID') class CategoricalResultValueAnnotations(Base): diff --git a/odm2api/ODM2/services/__init__.py b/odm2api/ODM2/services/__init__.py index e7064de..1364652 100644 --- a/odm2api/ODM2/services/__init__.py +++ b/odm2api/ODM2/services/__init__.py @@ -38,9 +38,9 @@ 'updateExtensionProperties' ] ''' -from createService import CreateODM2 -from deleteService import DeleteODM2 -from readService import ReadODM2 -from updateService import UpdateODM2 +from odm2api.ODM2.services.createService import CreateODM2 +from odm2api.ODM2.services.deleteService import DeleteODM2 +from odm2api.ODM2.services.readService import ReadODM2 +from odm2api.ODM2.services.updateService import UpdateODM2 __all__= ['CreateODM2', 'DeleteODM2', 'ReadODM2', 'UpdateODM2' ] \ No newline at end of file diff --git a/odm2api/ODM2/services/createService.py b/odm2api/ODM2/services/createService.py index a882ef9..dfff8e2 100644 --- a/odm2api/ODM2/services/createService.py +++ b/odm2api/ODM2/services/createService.py @@ -151,7 +151,7 @@ def createSimulation(self, simulation): def createTimeSeriesResultValues(self, datavalues): try: tablename = TimeSeriesResultValues.__tablename__ - print "I am TS saving name the table name"+ tablename + #print ("I am TS saving name the table name", tablename) datavalues.to_sql(name="TimeSeriesResultValues", schema=TimeSeriesResultValues.__table_args__['schema'], if_exists='append', diff --git a/odm2api/ODMconnection.py b/odm2api/ODMconnection.py index 767cc55..897d14d 100644 --- a/odm2api/ODMconnection.py +++ b/odm2api/ODMconnection.py @@ -3,9 +3,9 @@ from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker -from .ODM2.models import Variables as Variable2, setSchema +from odm2api.ODM2.models import Variables as Variable2, setSchema #from .versionSwitcher import ODM, refreshDB #import Variable as Variable1 -from .ODM1_1_1.services import ODM#, refreshDB +from odm2api.ODM1_1_1.services import ODM#, refreshDB import urllib import sys import os diff --git a/requirements.txt b/requirements.txt index 236293e..d78fe04 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ pyodbc six sqlalchemy --e git+https://github.com/ODM2/geoalchemy.git@v0.7.4#egg=geoalchemy-0.7.4 -shapely +#-e git+https://github.com/ODM2/geoalchemy.git@v0.7.4#egg=geoalchemy-0.7.4 +#shapely pandas #psycopg2 # Commented out because I could not pip install it.