From 5a70943dea09dcabf54c8ea5e2b87b0a0a2d2564 Mon Sep 17 00:00:00 2001 From: stephanie Date: Tue, 16 Aug 2016 13:20:42 -0600 Subject: [PATCH 1/5] fix naming of result objects to be consistant --- odm2api/ODM2/models.py | 124 ++++++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 58 deletions(-) diff --git a/odm2api/ODM2/models.py b/odm2api/ODM2/models.py index ef66405..0f66190 100644 --- a/odm2api/ODM2/models.py +++ b/odm2api/ODM2/models.py @@ -1523,10 +1523,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 +1549,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 +1564,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 +1596,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 +1621,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 +1657,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 +1681,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 +1703,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 +1732,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 +1756,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 +1769,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 +1791,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 +1814,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 +1842,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 +1866,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 +1886,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 +1927,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 +1945,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): From 1dce75425ae0e648cb2f6fdbe216c66eda5f23e4 Mon Sep 17 00:00:00 2001 From: stephanie Date: Fri, 19 Aug 2016 11:55:57 -0600 Subject: [PATCH 2/5] update APIDemo.ipynb --- Examples/APIDemo.ipynb | 247 +++++++---------------------------------- 1 file changed, 42 insertions(+), 205 deletions(-) diff --git a/Examples/APIDemo.ipynb b/Examples/APIDemo.ipynb index b4f6182..6b0b3a6 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,23 +42,12 @@ "source": [ "_session = session_factory.getSession()\n", "\n", - "read = ReadODM2(session_factory)\n" + "read = ReadODM2(session_factory)" ] }, { "cell_type": "code", - "execution_count": 4, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "# dir (read)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, + "execution_count": 32, "metadata": { "collapsed": false }, @@ -66,62 +56,7 @@ "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" + "USU3: Battery voltage\nUSU4: Turbidity\nUSU5: Turbidity\nUSU6: Turbidity\nUSU7: Turbidity\nUSU8: Turbidity\nUSU9: Turbidity\nUSU10: Temperature\nUSU13: Gage height\nUSU14: Temperature\nUSU15: Relative humidity\nUSU16: Precipitation\nUSU17: Battery voltage\nUSU18: Wind speed\nUSU19: Wind direction\nUSU20: Wind direction\nUSU21: Barometric pressure\nUSU22: Radiation, incoming shortwave\nUSU23: Battery voltage\nUSU24: Wind speed\nUSU25: Temperature\nUSU26: Temperature\nUSU27: Temperature\nUSU28: Relative humidity\nUSU29: Barometric pressure\nUSU30: Precipitation\nUSU31: Radiation, incoming shortwave\nUSU32: Oxygen, dissolved\nUSU33: Oxygen, dissolved percent of saturation\nUSU34: Specific conductance\nUSU35: pH\nUSU36: Temperature\nUSU37: Turbidity\nUSU39: Phosphorus, total\nUSU40: Phosphorus, total dissolved\nUSU41: Solids, total Suspended\nUSU44: Discharge\nUSU47: Solids, total suspended\nUSU48: Phosphorus, total\nUSU49: Distance\nUSU50: Snow Depth\nUSU51: Distance\nUSU52: Distance\nUSU53: Distance\nUSU54: Snow Depth\nUSU55: Snow Depth\nUSU56: Snow Depth\nUSU57: Volumetric water content\nUSU58: Electrical conductivity\nUSU59: Temperature\nUSU60: Temperature\nUSU61: Real dielectric constant\nUSU62: Imaginary dielectric constant\nUSU63: Alkalinity, carbonate plus bicarbonate\nUSU64: Nitrogen, total dissolved\nUSU65: Nitrogen, total\ntester: Wind speed\nTN: Nitrogen, total\nTP: Phosphorus, total\nTcoliform: Coliform, total\nE-coli: E-coli\nD180: delta-18O of H2O\nD2H: delta-D of H2O\n" ] } ], @@ -132,12 +67,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 +81,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,17 +94,16 @@ "\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 }, @@ -188,20 +112,7 @@ "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" + "\n-------- Information about an SamplingFeature of type 'Site'---------\nUSU-LBR-Mendon: Little Bear River at Mendon Road near Mendon, Utah\nUSU-LBR-SFWeather: Little Bear River South Fork Weather Station near Avon, Utah\nUnable to demo getSamplingFeaturesByType cannot concatenate 'str' and 'NoneType' objects\n\n-------- Information about an individual SamplingFeature ---------\nThe following are some of the attributes of a SamplingFeature retrieved using getSamplingFeatureByCode(): \n\nSamplingFeatureCode: USU-LBR-Mendon\nSamplingFeatureName: Little Bear River at Mendon Road near Mendon, Utah\nSamplingFeatureDescription: Located below county road bridge at Mendon Road crossing\nSamplingFeatureGeotypeCV: Point\nSamplingFeatureGeometry: \u0000\u0000\u0000\u0000\u0001\u0001\u0000\u0000\u0000ž·±Ù‘ü[ÀŽ\u0007[ìöÛD@\nElevation_m: 1345.0\n" ] } ], @@ -209,7 +120,7 @@ "# 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 +131,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,15 +142,12 @@ " 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 }, @@ -248,9 +156,7 @@ "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" + "\n------------ Create Sampling Feature --------- \nnew sampling feature added to database \n" ] } ], @@ -279,7 +185,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 34, "metadata": { "collapsed": false }, @@ -288,32 +194,16 @@ "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" + "\n------------ Foreign Key Example --------- \nUnable to demo Foreign Key Example: 'ReadODM2' object has no attribute 'getResult'\n" ] } ], "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 +214,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 +228,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,27 +236,28 @@ "# 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 }, @@ -387,48 +266,16 @@ "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" + "\n-------- Example of Retrieving Time Series Result Values ---------\n ValueID ResultID DataValue ValueDateTime ValueDateTimeUTCOffset \\\n0 2240358 1 12.51435 2007-09-01 00:00:00 -7 \n1 2240541 1 12.51519 2007-09-01 00:30:00 -7 \n2 2350031 1 12.50344 2007-09-01 01:00:00 -7 \n3 2234346 1 12.49085 2007-09-01 01:30:00 -7 \n4 2344012 1 12.48413 2007-09-01 02:00:00 -7 \n\n CensorCodeCV QualityCodeCV TimeAggregationInterval \\\n0 Not censored Unknown 30.0 \n1 Not censored Unknown 30.0 \n2 Not censored Unknown 30.0 \n3 Not censored Unknown 30.0 \n4 Not censored Unknown 30.0 \n\n TimeAggregationIntervalUnitsID \n0 102 \n1 102 \n2 102 \n3 102 \n4 102 \nUnable to demo plotting of tsValues: name 'plt' is not defined\n" ] - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" } ], "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 +288,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 +299,8 @@ " 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 - }, - "outputs": [], - "source": [] } ], "metadata": { @@ -475,7 +312,7 @@ "language_info": { "codemirror_mode": { "name": "ipython", - "version": 2 + "version": 2.0 }, "file_extension": ".py", "mimetype": "text/x-python", @@ -487,4 +324,4 @@ }, "nbformat": 4, "nbformat_minor": 0 -} +} \ No newline at end of file From 0f08ae5b707e97a7915e91f5ef2fb588ebfd0d79 Mon Sep 17 00:00:00 2001 From: Stephanie Reeder Date: Fri, 26 Aug 2016 10:21:35 -0600 Subject: [PATCH 3/5] remove any reference to Feature Geometry. remove geoalchemy dependency --- Examples/APIDemo.ipynb | 59 ++++++++++-------------------------------- Examples/Sample.py | 6 ++--- odm2api/ODM2/models.py | 43 +++--------------------------- requirements.txt | 2 +- 4 files changed, 22 insertions(+), 88 deletions(-) diff --git a/Examples/APIDemo.ipynb b/Examples/APIDemo.ipynb index 6b0b3a6..c2f5518 100644 --- a/Examples/APIDemo.ipynb +++ b/Examples/APIDemo.ipynb @@ -51,15 +51,7 @@ "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "USU3: Battery voltage\nUSU4: Turbidity\nUSU5: Turbidity\nUSU6: Turbidity\nUSU7: Turbidity\nUSU8: Turbidity\nUSU9: Turbidity\nUSU10: Temperature\nUSU13: Gage height\nUSU14: Temperature\nUSU15: Relative humidity\nUSU16: Precipitation\nUSU17: Battery voltage\nUSU18: Wind speed\nUSU19: Wind direction\nUSU20: Wind direction\nUSU21: Barometric pressure\nUSU22: Radiation, incoming shortwave\nUSU23: Battery voltage\nUSU24: Wind speed\nUSU25: Temperature\nUSU26: Temperature\nUSU27: Temperature\nUSU28: Relative humidity\nUSU29: Barometric pressure\nUSU30: Precipitation\nUSU31: Radiation, incoming shortwave\nUSU32: Oxygen, dissolved\nUSU33: Oxygen, dissolved percent of saturation\nUSU34: Specific conductance\nUSU35: pH\nUSU36: Temperature\nUSU37: Turbidity\nUSU39: Phosphorus, total\nUSU40: Phosphorus, total dissolved\nUSU41: Solids, total Suspended\nUSU44: Discharge\nUSU47: Solids, total suspended\nUSU48: Phosphorus, total\nUSU49: Distance\nUSU50: Snow Depth\nUSU51: Distance\nUSU52: Distance\nUSU53: Distance\nUSU54: Snow Depth\nUSU55: Snow Depth\nUSU56: Snow Depth\nUSU57: Volumetric water content\nUSU58: Electrical conductivity\nUSU59: Temperature\nUSU60: Temperature\nUSU61: Real dielectric constant\nUSU62: Imaginary dielectric constant\nUSU63: Alkalinity, carbonate plus bicarbonate\nUSU64: Nitrogen, total dissolved\nUSU65: Nitrogen, total\ntester: Wind speed\nTN: Nitrogen, total\nTP: Phosphorus, total\nTcoliform: Coliform, total\nE-coli: E-coli\nD180: delta-18O of H2O\nD2H: delta-D of H2O\n" - ] - } - ], + "outputs": [], "source": [ "# Run some basic sample queries.\n", "# ------------------------------\n", @@ -107,15 +99,7 @@ "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n-------- Information about an SamplingFeature of type 'Site'---------\nUSU-LBR-Mendon: Little Bear River at Mendon Road near Mendon, Utah\nUSU-LBR-SFWeather: Little Bear River South Fork Weather Station near Avon, Utah\nUnable to demo getSamplingFeaturesByType cannot concatenate 'str' and 'NoneType' objects\n\n-------- Information about an individual SamplingFeature ---------\nThe following are some of the attributes of a SamplingFeature retrieved using getSamplingFeatureByCode(): \n\nSamplingFeatureCode: USU-LBR-Mendon\nSamplingFeatureName: Little Bear River at Mendon Road near Mendon, Utah\nSamplingFeatureDescription: Located below county road bridge at Mendon Road crossing\nSamplingFeatureGeotypeCV: Point\nSamplingFeatureGeometry: \u0000\u0000\u0000\u0000\u0001\u0001\u0000\u0000\u0000ž·±Ù‘ü[ÀŽ\u0007[ìöÛD@\nElevation_m: 1345.0\n" - ] - } - ], + "outputs": [], "source": [ "# Get all of the SamplingFeatures from the database that are Sites\n", "\n", @@ -151,15 +135,7 @@ "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n------------ Create Sampling Feature --------- \nnew sampling feature added to database \n" - ] - } - ], + "outputs": [], "source": [ "#add sampling feature\n", "print \"\\n------------ Create Sampling Feature --------- \\n\",\n", @@ -189,15 +165,7 @@ "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n------------ Foreign Key Example --------- \nUnable to demo Foreign Key Example: 'ReadODM2' object has no attribute 'getResult'\n" - ] - } - ], + "outputs": [], "source": [ "# Drill down and get objects linked by foreign keys\n", "print \"\\n------------ Foreign Key Example --------- \\n\",\n", @@ -261,15 +229,7 @@ "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n-------- Example of Retrieving Time Series Result Values ---------\n ValueID ResultID DataValue ValueDateTime ValueDateTimeUTCOffset \\\n0 2240358 1 12.51435 2007-09-01 00:00:00 -7 \n1 2240541 1 12.51519 2007-09-01 00:30:00 -7 \n2 2350031 1 12.50344 2007-09-01 01:00:00 -7 \n3 2234346 1 12.49085 2007-09-01 01:30:00 -7 \n4 2344012 1 12.48413 2007-09-01 02:00:00 -7 \n\n CensorCodeCV QualityCodeCV TimeAggregationInterval \\\n0 Not censored Unknown 30.0 \n1 Not censored Unknown 30.0 \n2 Not censored Unknown 30.0 \n3 Not censored Unknown 30.0 \n4 Not censored Unknown 30.0 \n\n TimeAggregationIntervalUnitsID \n0 102 \n1 102 \n2 102 \n3 102 \n4 102 \nUnable to demo plotting of tsValues: name 'plt' is not defined\n" - ] - } - ], + "outputs": [], "source": [ "# Get the values for a particular TimeSeriesResult\n", "print \"\\n-------- Example of Retrieving Time Series Result Values ---------\"\n", @@ -301,6 +261,15 @@ "except Exception as e:\n", " print \"Unable to demo plotting of tsValues: \", e" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "" + ] } ], "metadata": { 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/odm2api/ODM2/models.py b/odm2api/ODM2/models.py index 0f66190..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' diff --git a/requirements.txt b/requirements.txt index 236293e..f2b37c8 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 +#-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. From 5ea299f793979b72dcf5dbce6c0ef622381fd04a Mon Sep 17 00:00:00 2001 From: Stephanie Reeder Date: Fri, 26 Aug 2016 10:44:17 -0600 Subject: [PATCH 4/5] remove shapely dependency --- condaenvironment_1.yml | 3 +-- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) 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/requirements.txt b/requirements.txt index f2b37c8..d78fe04 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,6 +2,6 @@ pyodbc six sqlalchemy #-e git+https://github.com/ODM2/geoalchemy.git@v0.7.4#egg=geoalchemy-0.7.4 -shapely +#shapely pandas #psycopg2 # Commented out because I could not pip install it. From beb170b2fa2e5b86167a216fbe1edf5e2f94c43f Mon Sep 17 00:00:00 2001 From: Stephanie Reeder Date: Fri, 26 Aug 2016 10:57:04 -0600 Subject: [PATCH 5/5] update imports so they are static --- odm2api/ODM1_1_1/services/__init__.py | 6 +++--- odm2api/ODM1_1_1/services/edit_service.py | 2 +- odm2api/ODM2/LikeODM1/__init__.py | 2 +- odm2api/ODM2/services/__init__.py | 8 ++++---- odm2api/ODM2/services/createService.py | 2 +- odm2api/ODMconnection.py | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) 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/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