Source code for optiwindnet.db.modelv2
# SPDX-License-Identifier: MIT
# https://gitlab.windenergy.dtu.dk/TOPFARM/OptiWindNet/
"""Database model v2 for storage of locations and route sets.
Tables:
- NodeSet: location definition
- RouteSet: routeset (i.e. a record of G)
- Method: info on algorithm & options to produce routesets
- Machine: info on machine that generated a routeset
"""
import datetime
import os
from pony.orm import Database, IntArray, Json, Optional, PrimaryKey, Required, Set
from ._core import _naive_utc_now
__all__ = ()
[docs]
def open_database(filepath: str, create_db: bool = False) -> Database:
"""Opens the sqlite database v2 file specified in `filepath`.
Args:
filepath: path to database file
create_db: True -> create a new file if it does not exist
Returns:
Database object (Pony ORM)
"""
db = Database()
define_entities(db)
db.bind(
'sqlite', os.path.abspath(os.path.expanduser(filepath)), create_db=create_db
)
db.generate_mapping(create_tables=True)
return db
def define_entities(db: Database):
class NodeSet(db.Entity):
# hashlib.sha256(VertexC + boundary).digest()
name = Required(str, unique=True)
T = Required(int) # # of non-root nodes
R = Required(int) # # of root nodes
B = Required(int) # num_border_vertices
# vertices (nodes + roots) coordinates (UTM)
# pickle.dumps(np.empty((R + T + B, 2), dtype=float)
VertexC = Required(bytes)
# the first group is the border (ccw), then obstacles (cw)
# B is sum(constraint_groups)
constraint_groups = Required(IntArray)
# indices to VertexC, concatenation of the groups' ordered vertices
constraint_vertices = Required(IntArray)
landscape_angle = Optional(float)
digest = PrimaryKey(bytes)
RouteSets = Set(lambda: RouteSet)
class RouteSet(db.Entity):
id = PrimaryKey(int, auto=True)
handle = Required(str)
valid = Optional(bool)
T = Required(int) # num_nodes
R = Required(int) # num_roots
capacity = Required(int)
length = Required(float)
is_normalized = Required(bool)
# runtime always in [s]
runtime = Optional(float)
num_gates = Required(IntArray)
# number of contour nodes
C = Optional(int, default=0)
# number of detour nodes
D = Optional(int, default=0)
# short identifier of routeset origin (redundant with Method)
creator = Optional(str)
# relative increase from undetoured routeset to the detoured one
# detoured_length = (1 + detextra)*undetoured_length
detextra = Optional(float)
num_diagonals = Optional(int)
tentative = Optional(IntArray)
rogue = Optional(IntArray)
timestamp = Optional(datetime.datetime, default=_naive_utc_now)
misc = Optional(Json)
stuntC = Optional(bytes) # coords of border stunts
# len(clone2prime) == C + D
clone2prime = Optional(IntArray)
edges = Required(IntArray)
nodes = Required(NodeSet)
method = Required(lambda: Method)
machine = Optional(lambda: Machine)
class Method(db.Entity):
solver_name = Required(str)
funname = Required(str)
# options is a dict of function parameters
options = Required(Json)
timestamp = Required(datetime.datetime, default=_naive_utc_now)
funfile = Required(str)
# hashlib.sha256(fun.__code__.co_code)
funhash = Required(bytes)
# hashlib.sha256(funhash + pickle(options)).digest()
digest = PrimaryKey(bytes)
RouteSets = Set(RouteSet)
class Machine(db.Entity):
name = Required(str, unique=True)
attrs = Optional(Json)
RouteSets = Set(RouteSet)
# class CableSet(db.Entity):
# name = Required(str)
# cableset = Required(bytes)
# RouteSets = Set(RouteSet)
# max_capacity = Required(int)
# # name = Required(str)
# # types = Required(int)
# # areas = Required(IntArray) # mm²
# # capacities = Required(IntArray) # num of wtg
# # RouteSets = Set(RouteSet)
# # max_capacity = Required(int)