-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement object based "add" API in Python #760
Labels
python
Relates to one of the Ribasim python packages
Comments
Let's wait for #912 to be merged first. |
See #588 (comment) |
WIP by @visr and me: basin = ribasim.Basin([
{
"profile": pd.DataFrame(data={"area": [1.0,3.0], "level": [1.1, 2.2]}),
"static": pd.DataFrame(data={"precipitation": [1.0,3.0], "control_state": [1.1, 2.2]}),
# use dictionaries [str:sequence],
# later consider accepting pd.DataFrame or dicts with numpy arrays
"static": {"precipitation": [1.0,3.0], "control_state": [1.1, 2.2]},
# later accept more timestamp types
# only support either static or time per node_id
# "time": {"time": [pd.Timestamp(2020), pd.Timestamp(2021)], "precipitation": [1.0,3.0]},
"node": {
# allow tuples, call gpd.points_from_xy ourselves
"geometry": (2.0,3.6),
"name": "IJsselmeer",
"allocation_network_id": 5,
}
}
])
# autoincrement fid at object creation
# generate on demand
model.network.node.df
model.basins.geometry.df
class Basin:
static: DataFrame
time: DataFrame
profile: DataFrame
node: DataFrame
# add a node
basin.add({})
# and connect it
edge.add(basin[-1], terminal[-1])
terminal
# show
terminal.plot()
#
model.basin
basins[0]
basins[node_id]
iterate(basins)
# connect
# connect(basins[2], pumps[1])
ribasim.Edges([
{
"type": "flow",
"from": basins[0],
"to": pumps[0],
"geometry": ...,
"name": ...,
"allocation_network_id": ...,
}
]) |
And the newest iteration, assuming we now require ids to only be unique per node_type: basin = ribasim.Basin([
{
"profile": pd.DataFrame(data={"area": [1.0,3.0], "level": [1.1, 2.2]}),
"static": pd.DataFrame(data={"precipitation": [1.0,3.0], "control_state": [1.1, 2.2]}),
# use dictionaries [str:sequence],
# later consider accepting pd.DataFrame or dicts with numpy arrays
"static": {"precipitation": [1.0,3.0], "control_state": [1.1, 2.2]},
# later accept more timestamp types
# only support either static or time per node_id
# "time": {"time": [pd.Timestamp(2020), pd.Timestamp(2021)], "precipitation": [1.0,3.0]},
"node": {
# allow tuples, call gpd.points_from_xy ourselves
"geometry": (2.0,3.6),
"name": "IJsselmeer",
"allocation_network_id": 5,
}
}
])
# autoincrement fid at object creation
# generate on demand
model.network.node.df
model.basins.geometry.df
class Basin:
static: DataFrame
time: DataFrame
profile: DataFrame
node: DataFrame
# add a node
basin.add({})
# and connect it
edge.add(basin[-1], terminal[-1])
terminal
# show
terminal.plot()
#
model.basin
basins[0]
basins[node_id]
iterate(basins)
# connect
# connect(basins[2], pumps[1])
ribasim.Edges([
{
"type": "flow",
"from": basins[0],
"to": pumps[0],
"geometry": ...,
"name": ...,
"allocation_network_id": ...,
}
]) |
Latest version: import ribasim
model = ribasim.Model(starttime=starttime, endtime=endtime)
model.basin = ribasim.Basin(
[
{
# use dictionaries [str:sequence],
"profile": {"area": [1.0, 3.0], "level": [1.1, 2.2]},
"static": {"precipitation": [1.0, 3.0], "control_state": [1.1, 2.2]},
# later consider accepting pd.DataFrame or dicts with numpy arrays
# "static": pd.DataFrame(data={"precipitation": [1.0,3.0], "control_state": [1.1, 2.2]}),
# later accept more timestamp types
# only support either static or time per node_id
# "time": {"time": [pd.Timestamp(2020), pd.Timestamp(2021)], "precipitation": [1.0,3.0]},
"node": {
"id": 2,
# allow tuples, call gpd.points_from_xy ourselves
"geometry": (2.0, 3.6),
"name": "IJsselmeer",
"allocation_network_id": 5,
},
}
]
)
model.basin.add({...})
model.basins.replace(basin_id)
model.remove(ribasim.Basin, 2) # can remove edges
model.replace(ribasim.Basin, 2, ribasim.Pump([{...}])) # can remove edges
# the node table becomes a virtual concat of the node tables of all node types
# that is constructed on demand
class Basin:
static: DataFrame
time: DataFrame
profile: DataFrame
node: DataFrame
class Model:
basin: Basin
pump: Pump
# connect it
# TODO edge ID stability?
# TODO use (ribasim.Basin, 10) or ribasim.BasinID(10) or something else?
model.edge.add(
{
"id": 10,
"type": "flow",
"from": (ribasim.Basin, 10),
"to": (ribasim.Terminal, 20),
}
)
model.edge.remove(ribasim.Basin, 10, ribasim.Terminal, 20)
terminal
# show
terminal.plot()
#
model.basin
basin[3] # basin ID #3
basin.plot()
pump.plot()
ribasim.Edges(
[
{
"type": "flow",
"from": basins[0],
"to": pumps[0],
"geometry": ...,
"name": ...,
"allocation_network_id": ...,
}
]
)
## Remove a pump (and its associated edges?)
## Replace a pump with a pump, keeping edges (and node_id?) intact
## Replace a pump with an outlet, keeping edges (and node_id?) intact
## Add a pump and connect to an ID
## Can we drop global ID altogether in favor of a node specific ID? Probably. |
Latest version: import ribasim
model = ribasim.Model(starttime=starttime, endtime=endtime)
model.basin.add(
ribasim.Basin(
# use dictionaries [str:sequence],
profile=Dataframe({"area": [1.0, 3.0], "level": [1.1, 2.2]}),
static=DataFrame{"precipitation": [1.0, 3.0], "control_state": [1.1, 2.2]}),
# later accept more timestamp types
# only support either static or time per node_id
# "time": DataFrame({"time": [pd.Timestamp(2020), pd.Timestamp(2021)], "precipitation": [1.0,3.0]}),
node={
"id": 2,
# allow tuples, call gpd.points_from_xy ourselves
"geometry": (2.0, 3.6),
"name": "IJsselmeer",
"allocation_network_id": 5,
}
))
model.basins.replace(basin_id)
model.remove(ribasim.Basin, 2) # can remove edges
model.replace(ribasim.Basin, 2, ribasim.Pump([{...}])) # can remove edges
# the node table becomes a virtual concat of the node tables of all node types
# that is constructed on demand
# connect it
# TODO edge ID stability?
# TODO use (ribasim.Basin, 10) or ribasim.BasinID(10) or something else?
model.edges.add(
edge_id=10,
edge_type="flow",
from_node_type=ribasim.Basin,
from_node_id=10,
to_node_type=ribasim.Terminal,
to_node_id=20
)
model.edge.remove(ribasim.Basin, 10, ribasim.Terminal, 20)
## Remove a pump (and its associated edges?)
## Replace a pump with a pump, keeping edges (and node_id?) intact
## Replace a pump with an outlet, keeping edges (and node_id?) intact
## Add a pump and connect to an ID
## Can we drop global ID altogether in favor of a node specific ID? Probably. |
import ribasim
model = ribasim.Model(starttime=starttime, endtime=endtime)
model.basins.add(Node(node_id=1, geometry=point),
[basin.Profile(area=[0.01, 1000.0], level=[0.0, 1.0]),
basin.State(level=[1.0])])
model.basins.replace(basin_id)
model.remove(ribasim.Basin, 2) # can remove edges
model.replace(ribasim.Basin, 2, ribasim.Pump([{...}])) # can remove edges
# the node table becomes a virtual concat of the node tables of all node types
# that is constructed on demand
# connect it
# TODO edge ID stability?
# TODO use (ribasim.Basin, 10) or ribasim.BasinID(10) or something else?
model.edges.add(
from_node=model.basins[1],
to_node=model.manning_resistances[2],
edge_type="flow",
)
model.edge.remove(model.basins[1], model.manning_resistances[2])
## Remove a pump (and its associated edges?)
## Replace a pump with a pump, keeping edges (and node_id?) intact
## Replace a pump with an outlet, keeping edges (and node_id?) intact
## Add a pump and connect to an ID
## Can we drop global ID altogether in favor of a node specific ID? Probably. |
visr
added a commit
that referenced
this issue
Mar 12, 2024
Fixes #760 Fixes #252 Follow ups: - More validation - Avoid blocking of database by qgis - Plotting of control edges - Reading of model --------- Co-authored-by: Martijn Visser <[email protected]> Co-authored-by: Hofer-Julian <[email protected]>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Will be longer than sprint 10, probably done in 12.
The text was updated successfully, but these errors were encountered: