-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
# This is a combination of 5 commits.
# This is the 1st commit message: add a query notebook that points at the copy of the points table # This is the commit message #2: add what the point data table linking could look like, including what adding an object might look like # This is the commit message #3: Example of how the realtionship might look # This is the commit message #4: attempt at having many-to-many with observers # This is the commit message #5: assuming we don't need back populate on instrument relationships
- Loading branch information
1 parent
6f4fbef
commit 9879dd0
Showing
1 changed file
with
283 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,283 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 1, | ||
"id": "30e47587-c53d-4fa7-aa39-b233997afec9", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Imports\n", | ||
"from snowexsql.data import PointData, SingleLocationData, Measurement, Base\n", | ||
"from snowexsql.api import PointMeasurements\n", | ||
"from sqlalchemy import Column, Date, DateTime, Float, Integer, String, Time, Table\n", | ||
"from sqlalchemy.orm import Mapped\n", | ||
"from sqlalchemy.orm import mapped_column\n", | ||
"from typing import List" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "ccc0ce03-2e31-49ab-b906-dd0cc9830220", | ||
"metadata": {}, | ||
"source": [ | ||
"## Extend the data model\n", | ||
" * Make a new data model that uses the new `points_prototype` table with the copied over `Points` information" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 2, | ||
"id": "c6714db5-db2f-44b2-b5d8-ae253d0c39d2", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# points_prototype\n", | ||
"\n", | ||
"\n", | ||
"class PointDataOriginal(SingleLocationData, Measurement, Base):\n", | ||
" \"\"\"\n", | ||
" Class representing the points table. This table holds all point data.\n", | ||
" Here a single data entry is a single coordinate pair with a single value\n", | ||
" e.g. snow depths\n", | ||
" \"\"\"\n", | ||
" __tablename__ = 'points_original'\n", | ||
" __table_args__ = {\"schema\": \"public\"}\n", | ||
"\n", | ||
" version_number = Column(Integer)\n", | ||
" equipment = Column(String(50))\n", | ||
" value = Column(Float)\n", | ||
"\n", | ||
" __mapper_args__ = {\n", | ||
" 'polymorphic_identity': 'Points',\n", | ||
" }\n", | ||
"\n", | ||
"\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "d3bc5746-2eb8-4f0c-8192-fd0556b47ab3", | ||
"metadata": {}, | ||
"source": [ | ||
"## Make a new api class\n", | ||
" * Extend the API class and use the new points prototype data model " | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 3, | ||
"id": "c832fcaa-55a5-46f6-bd4a-1f370d6670d3", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"class PointsMeasurementsOriginal(PointMeasurements):\n", | ||
" \"\"\"\n", | ||
" Extend the points api class for the new data model\n", | ||
" \"\"\"\n", | ||
" DB_NAME = \"snow:[email protected]/snowex\"\n", | ||
" MODEL = PointDataOriginal\n", | ||
" " | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "646d7faf-6934-4054-aec9-11d3c2d682e0", | ||
"metadata": {}, | ||
"source": [ | ||
"## Use our new api class" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "6d207811-aa91-44aa-88d8-2dc86d9bcdac", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"PointsMeasurementsOriginal().all_instruments" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "d26d0853-67c8-4bc4-915a-edc86c01d37c", | ||
"metadata": {}, | ||
"source": [ | ||
"## make a new table class that includes foreign keys" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 4, | ||
"id": "85ccfd8c-1a41-4569-86ad-c6342a9add0f", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# points_prototype\n", | ||
"from sqlalchemy import Column, Date, DateTime, Float, Integer, String, Time, ForeignKey\n", | ||
"from sqlalchemy.orm import relationship, sessionmaker\n", | ||
"\n", | ||
"\n", | ||
"# Create a association table for the many-to-many relationship\n", | ||
"point_observers = Table(\n", | ||
" \"point_observers\",\n", | ||
" Base.metadata,\n", | ||
" Column(\"point_id\", ForeignKey(\"points_prototype.id\"), primary_key=True),\n", | ||
" Column(\"observer_id\", ForeignKey(\"observers.id\"), primary_key=True),\n", | ||
" extend_existing=True\n", | ||
")\n", | ||
"\n", | ||
"\n", | ||
"# Create an Observer table class\n", | ||
"class Observer(Base):\n", | ||
" __tablename__ = 'observers'\n", | ||
" __table_args__ = {\"schema\": \"public\"}\n", | ||
" # this seems important\n", | ||
" __mapper_args__ = {\n", | ||
" 'polymorphic_identity': 'Observer',\n", | ||
" }\n", | ||
" # id is mapped column for many-to-many \n", | ||
" id: Mapped[int] = mapped_column(primary_key=True)\n", | ||
" # Name of the instrument\n", | ||
" first_name = Column(String(255))\n", | ||
" last_name = Column(String(255))\n", | ||
" email = Column(String(255))\n", | ||
"\n", | ||
"\n", | ||
"# Create an instruments table class\n", | ||
"class Instument(Base):\n", | ||
" __tablename__ = 'instrument'\n", | ||
" __table_args__ = {\"schema\": \"public\"}\n", | ||
" # this seems important\n", | ||
" __mapper_args__ = {\n", | ||
" 'polymorphic_identity': 'Instrument',\n", | ||
" }\n", | ||
" # auto created id\n", | ||
" id = Column(Integer, primary_key=True)\n", | ||
" # Name of the instrument\n", | ||
" name = Column(String(50), nullable=False)\n", | ||
"\n", | ||
" # Link each table that use instrument (bi-directional)\n", | ||
" # points = relationship('PointDataPrototype', back_populates='instrument')\n", | ||
"\n", | ||
"\n", | ||
"# Create a new points table class that links to \n", | ||
"class PointDataPrototype(SingleLocationData, Base):\n", | ||
" __tablename__ = 'points_prototype'\n", | ||
" __table_args__ = {\"schema\": \"public\"}\n", | ||
" # this seems important\n", | ||
" __mapper_args__ = {\n", | ||
" 'polymorphic_identity': 'Points',\n", | ||
" }\n", | ||
"\n", | ||
" version_number = Column(Integer)\n", | ||
" equipment = Column(String(50))\n", | ||
" value = Column(Float)\n", | ||
"\n", | ||
" # bring these in instead of Measurement\n", | ||
" type = Column(String(50))\n", | ||
" units = Column(String(50))\n", | ||
"\n", | ||
" # This should be the foreign key\n", | ||
" # instrument = Column(String(50))\n", | ||
" # Link the instrument id with a foreign key\n", | ||
" instrument_id = Column(Integer, ForeignKey('instrument.id'))\n", | ||
" # Link the Instrument class\n", | ||
" instrument = relationship('Instrument')\n", | ||
"\n", | ||
" # id is a mapped column for many-to-many with observers\n", | ||
" id: Mapped[int] = mapped_column(primary_key=True)\n", | ||
" observers: Mapped[List[Observer]] = relationship(secondary=point_observers)\n", | ||
" \n", | ||
"\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 5, | ||
"id": "f68aac71-a04e-42a4-ae3f-2d9f2710f2f5", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"class PointsMeasurementsPrototype(PointMeasurements):\n", | ||
" \"\"\"\n", | ||
" Extend the points api class for the new data model\n", | ||
" \"\"\"\n", | ||
" DB_NAME = \"snow:[email protected]/snowex\"\n", | ||
" MODEL = PointDataPrototype" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "cc87534b-ee80-47f0-857d-ae2e1ee23a3f", | ||
"metadata": {}, | ||
"source": [ | ||
"## Example of adding a new point, this doens't work yet" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 6, | ||
"id": "32397550-4d52-4564-baa4-795b515c0040", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"def add_entry(instrument_name, observer_names, **kwargs):\n", | ||
" # Check if the instrument already exists\n", | ||
" instrument = session.query(Instrument).filter_by(name=instrument_name).first()\n", | ||
" # observer = session.query(Observer).filter_by(name=observer_name).first()\n", | ||
" \n", | ||
" if not instrument:\n", | ||
" # If the instrument does not exist, create it\n", | ||
" instrument = Instrument(name=instrument_name)\n", | ||
" session.add(instrument)\n", | ||
" session.commit() # Commit to ensure instrument is saved and has an ID\n", | ||
"\n", | ||
" observer_list = []\n", | ||
" for obs_name in observer_names:\n", | ||
" observer = session.query(Observer).filter_by(last_name=observer_name).first()\n", | ||
" if not observer:\n", | ||
" # If the instrument does not exist, create it\n", | ||
" instrument = Observer(last_name=instrument_name)\n", | ||
" session.add(observer)\n", | ||
" session.commit() # Commit to ensure instrument is saved and has an ID\n", | ||
" observer_list.append(observer)\n", | ||
" \n", | ||
" \n", | ||
" # Now that the instrument exists, create the entry, notice we only need the instrument object\n", | ||
" new_entry = PointDataPrototype(**kwargs, instrument=instrument, observers=observer_list)\n", | ||
" session.add(new_entry)\n", | ||
" session.commit()" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "354ae291-30f8-4541-8c3e-80f78f7aee7e", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 3 (ipykernel)", | ||
"language": "python", | ||
"name": "python3" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 3 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython3", | ||
"version": "3.10.4" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 5 | ||
} |