Skip to content

Commit

Permalink
Merge pull request #103 from SnowEx/break_up_tables
Browse files Browse the repository at this point in the history
Refactor table to object mapping into dedicated classes.
  • Loading branch information
jomey authored Aug 22, 2024
2 parents 97f23c6 + 30330df commit 8974297
Show file tree
Hide file tree
Showing 11 changed files with 163 additions and 143 deletions.
12 changes: 6 additions & 6 deletions snowexsql/api.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import logging
from contextlib import contextmanager
from sqlalchemy.sql import func

import geoalchemy2.functions as gfunc
import geopandas as gpd
from shapely.geometry import box
from geoalchemy2.shape import from_shape
import geoalchemy2.functions as gfunc
from geoalchemy2.types import Raster
from shapely.geometry import box
from sqlalchemy.sql import func

from snowexsql.db import get_db
from snowexsql.data import PointData, LayerData, ImageData
from snowexsql.conversions import query_to_geopandas, raster_to_rasterio

from snowexsql.db import get_db
from snowexsql.tables import ImageData, LayerData, PointData

LOG = logging.getLogger(__name__)
DB_NAME = 'snow:[email protected]/snowex'
Expand Down
5 changes: 1 addition & 4 deletions snowexsql/conversions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,14 @@
filetypes, datatypes, etc. Many tools here will be useful for most end users
of the database.
"""
from os.path import basename, dirname, join

import geopandas as gpd
import pandas as pd
import numpy as np
import rasterio
from geoalchemy2.shape import to_shape
from rasterio import MemoryFile
from sqlalchemy.dialects import postgresql

from .data import PointData
from snowexsql.tables import PointData


def points_to_geopandas(results):
Expand Down
127 changes: 0 additions & 127 deletions snowexsql/data.py

This file was deleted.

3 changes: 2 additions & 1 deletion snowexsql/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
"""

import json

from sqlalchemy import MetaData, create_engine
from sqlalchemy.orm import sessionmaker

from .data import Base
from snowexsql.tables import Base


def initialize(engine):
Expand Down
16 changes: 16 additions & 0 deletions snowexsql/tables/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from .base import Base, Measurement, SingleLocationData, SnowData
from .image_data import ImageData
from .layer_data import LayerData
from .point_data import PointData
from .site_data import SiteData

__all__ = [
'Base',
'ImageData',
'LayerData',
'Measurement',
'PointData',
'SingleLocationData',
'SiteData'
'SnowData',
]
51 changes: 51 additions & 0 deletions snowexsql/tables/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""
Module contains all the data models for the database. Classes here actually
represent tables where columns are mapped as attributed. Any class inheriting
from Base is a real table in the database. This is called Object Relational
Mapping in the sqlalchemy or ORM.
"""

from geoalchemy2 import Geometry
from sqlalchemy import Column, Date, DateTime, Float, Integer, String, Time
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.sql import func

Base = declarative_base()


class SnowData(object):
"""
Base class for which all data will have these attributes
"""
site_name = Column(String(250))
date = Column(Date)
time_created = Column(DateTime(timezone=True), server_default=func.now())
time_updated = Column(DateTime(timezone=True), onupdate=func.now())
id = Column(Integer, primary_key=True)
doi = Column(String(50))
date_accessed = Column(Date)


class SingleLocationData(SnowData):
"""
Base class for points and profiles
"""
latitude = Column(Float)
longitude = Column(Float)
northing = Column(Float)
easting = Column(Float)
elevation = Column(Float)
utm_zone = Column(Integer)
geom = Column(Geometry("POINT"))
time = Column(Time(timezone=True))
site_id = Column(String(50))


class Measurement(object):
"""
Base Class providing attributes required for a measurement of any kind
"""
instrument = Column(String(50))
type = Column(String(50))
units = Column(String(50))
observers = Column(String(100))
14 changes: 14 additions & 0 deletions snowexsql/tables/image_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from geoalchemy2 import Raster
from sqlalchemy import Column, String

from .base import Base, Measurement, SnowData


class ImageData(SnowData, Measurement, Base):
"""
Class representing the images table. This table holds all images/rasters
"""
__tablename__ = 'images'
__table_args__ = {"schema": "public"}
raster = Column(Raster)
description = Column(String(1000))
25 changes: 25 additions & 0 deletions snowexsql/tables/layer_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from sqlalchemy import Column, Float, String

from .base import Base, Measurement, SingleLocationData


class LayerData(SingleLocationData, Measurement, Base):
"""
Class representing the layers table. This table holds all layers or
profile data. Here a single data entry is a single value at depth in the
snowpack and a single coordinate pair. e.g. SMP profiles, Hand hardness,
temperature etc...
"""
__tablename__ = 'layers'
__table_args__ = {"schema": "public"}

depth = Column(Float)
site_id = Column(String(50))
pit_id = Column(String(50))
bottom_depth = Column(Float)
comments = Column(String(1000))
sample_a = Column(String(20))
sample_b = Column(String(20))
sample_c = Column(String(20))
value = Column(String(50))
flags = Column(String(20))
17 changes: 17 additions & 0 deletions snowexsql/tables/point_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from sqlalchemy import Column, Float, Integer, String

from .base import Base, Measurement, SingleLocationData


class PointData(SingleLocationData, Measurement, Base):
"""
Class representing the points table. This table holds all point data.
Here a single data entry is a single coordinate pair with a single value
e.g. snow depths
"""
__tablename__ = 'points'
__table_args__ = {"schema": "public"}

version_number = Column(Integer)
equipment = Column(String(50))
value = Column(Float)
28 changes: 28 additions & 0 deletions snowexsql/tables/site_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from sqlalchemy import Column, Float, String

from .base import Base, SingleLocationData


class SiteData(SingleLocationData, Base):
"""
Table for storing pit site meta data, This table doesn't represent any
main data record but only support data for each site
"""
__tablename__ = 'sites'
__table_args__ = {"schema": "public"}

pit_id = Column(String(50))
slope_angle = Column(Float)
aspect = Column(Float)
air_temp = Column(Float)
total_depth = Column(Float)
weather_description = Column(String(500))
precip = Column(String(100))
sky_cover = Column(String(100))
wind = Column(String(100))
ground_condition = Column(String(100))
ground_roughness = Column(String(100))
ground_vegetation = Column(String(100))
vegetation_height = Column(String(100))
tree_canopy = Column(String(100))
site_notes = Column(String(1000))
8 changes: 3 additions & 5 deletions tests/test_db.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
from os import remove
from os.path import dirname, join
from os.path import join

import pytest
from sqlalchemy import MetaData, Table, inspect
from sqlalchemy import Table

from snowexsql.data import ImageData, LayerData, PointData, SiteData
from snowexsql.db import *

from snowexsql.tables import ImageData, LayerData, PointData, SiteData
from .sql_test_base import DBSetup


Expand Down

0 comments on commit 8974297

Please sign in to comment.