Skip to content

Commit

Permalink
#15 request: cast type, add range. UI: clicker
Browse files Browse the repository at this point in the history
  • Loading branch information
funkchaser committed May 1, 2024
1 parent a7bddf3 commit a8f0473
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 49 deletions.
12 changes: 12 additions & 0 deletions src/aixd_grasshopper/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,18 @@ def get_dataobject_names_from_block():
return response


@app.route("/get_dataobject_types", methods=["POST"])
def get_dataobject_types():
data = request.data
data = json.loads(data)
session_id = data["session_id"]
sc = SessionController.create(session_id)

result = sc.get_dataobject_types()
response = json.dumps(result, cls=DataEncoder)
return response


@app.route("/plot_distrib_attributes", methods=["POST"])
def plot_distrib_attributes():
data = request.data
Expand Down
33 changes: 19 additions & 14 deletions src/aixd_grasshopper/components/aixd_DataObjectsNames/code.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# this code has been inspired by a forum post by "chanley" (2018.11.02) https://discourse.mcneel.com/t/can-i-instantiate-specific-component-on-the-canvas-with-a-script-python/74204/8
# flake8: noqa

# this code has been inspired by a forum post by "chanley" (2018.11.02)
# https://discourse.mcneel.com/t/can-i-instantiate-specific-component-on-the-canvas-with-a-script-python/74204/8

import Grasshopper
import System.Drawing as sd
Expand All @@ -9,21 +12,22 @@
comp = ghenv.Component
ghdoc = comp.OnPingDocument()


def make_Panel(NickName, UserText, Pivot, Bounds):
try:
Panel = Grasshopper.Kernel.Special.GH_Panel()
Panel.NickName = NickName
Panel.UserText = UserText
Panel.Properties.Colour = sd.Color.White
#Panel.Properties.Font = sd.Font("Trebuchet MS", 10)
# Panel.Properties.Font = sd.Font("Trebuchet MS", 10)
Panel.Properties.Multiline = False
Panel.Properties.DrawIndices = False
Panel.Properties.DrawPaths = False
ghdoc.AddObject(Panel,False,ghdoc.ObjectCount+1)
ghdoc.AddObject(Panel, False, ghdoc.ObjectCount + 1)
Panel.Attributes.Pivot = Pivot
Panel.Attributes.Bounds = Bounds
except Exception, ex:
ghenv.Component.AddRuntimeMessage(Grasshopper.Kernel.GH_RuntimeMessageLevel.Warning,str(ex))
except Exception(ex):
ghenv.Component.AddRuntimeMessage(Grasshopper.Kernel.GH_RuntimeMessageLevel.Warning, str(ex))


x = ghenv.Component.Attributes.DocObject.Attributes.Bounds.Right
Expand All @@ -36,20 +40,21 @@ def make_Panel(NickName, UserText, Pivot, Bounds):
errors = ""

if not datablock:
datablock = [ "design_parameters","performance_attributes","inputML","outputML"] #all datablock names
datablock = ["design_parameters", "performance_attributes", "inputML", "outputML"] # all datablock names

if get_names:

for i, datablock_nickname in enumerate(datablock):
panel_title = datablock_nickname
response = get_dataobject_names_from_block(session_id(),datablock_nickname)
text_items = response['names']
response = get_dataobject_names_from_block(session_id(), datablock_nickname)
text_items = response["names"]
if text_items:
text_str= "\n".join(text_items)
pt = sd.PointF(x + gap + i*gap, y + i*gap)
rect = sd.RectangleF(0,0,w,h)
text_str = "\n".join(text_items)
pt = sd.PointF(x + gap + i * gap, y + i * gap)
rect = sd.RectangleF(0, 0, w, h)
make_Panel(panel_title, text_str, pt, rect)
else:
errors+=response['msg']+"\n"
errors += response["msg"] + "\n"

if errors: ghenv.Component.AddRuntimeMessage(Grasshopper.Kernel.GH_RuntimeMessageLevel.Warning,str(errors))
if errors:
ghenv.Component.AddRuntimeMessage(Grasshopper.Kernel.GH_RuntimeMessageLevel.Warning, str(errors))
89 changes: 62 additions & 27 deletions src/aixd_grasshopper/components/aixd_Generator/code.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
# flake8: noqa

# reformat request data
# original input should be a list of strings
# each string should have a form: attribute_name:value
from aixd_grasshopper.gh_ui import request_designs, get_dataobject_types
from aixd_grasshopper.gh_ui_helper import session_id, component_id
from scriptcontext import sticky as st

cid = component_id(session_id(), ghenv.Component, "run_generation")
item = component_id(session_id(), ghenv.Component, "pick_sample")

"""
requested_values: a multiline string with variable_name:values tuples.
"""

if not n_designs or n_designs < 1:
n_designs = 1

request_ok = True
try:
request_dict = {}
for rv in requested_values:
rv = rv.strip()
k, v = rv.split(":")
v = float(v)
request_dict[k] = v
print(request_dict)
request_ok = True

except:
request_ok = False
# raise ValueError("Request could not be processed")

# -------------------------------------------------------------------------------
def recast_type(value, typename):
if typename == "real":
return float(value)
if typename == "integer":
return int(value)
if typename == "categorical":
return str(value)
if typename == "bool":
return bool(value)


class wrapper:
Expand All @@ -33,23 +35,56 @@ def __repr__(self):
return "Generated design"


# -------------------------------------------------------------------------------
def reformat_request(request_string):
types = get_dataobject_types(session_id())["dataobject_types"]
request_dict = {}

for rv in request_string:
rv = rv.strip()

# split into name:value(s)
k, v = rv.split(":")

if k not in types.keys():
raise ValueError(
"'{0}' is not a valid variable name. There is not variable with this name in the dataset.".format(k)
)

# check if a list or a single value
if v[0] == "[" and v[-1] == "]":
v = v[1:-1]
v = v.split(",")
v = [recast_type(vi, types[k]) for vi in v]
else:
v = recast_type(v, types[k])
request_dict[k] = v
return request_dict

from scriptcontext import sticky as st

from aixd_grasshopper.gh_ui import request_designs
from aixd_grasshopper.gh_ui_helper import component_id
from aixd_grasshopper.gh_ui_helper import session_id
# -------------------------------------------------------------------------------

cid = component_id(session_id(), ghenv.Component, "Generator")

if clear and cid in st.keys():
del st[cid]
st[item] = None
ghenv.Component.Message = "no samples"

if run and request_ok:
if generate and requested_values:

request_dict = reformat_request(requested_values)
st[item] = 0
ghenv.Component.Message = "Running"
st[cid] = request_designs(session_id(), request_dict, n_designs)
ghenv.Component.Message = "Finished"

if pick_previous:
st[item] -= 1
if pick_next:
st[item] += 1

if cid in st.keys():
predictions = [wrapper(x) for x in result]
ghenv.Component.Message = "Ready"
samples = st[cid]["generated"]
n = len(samples)
i = st[item] % n
sample = wrapper(samples[i])
ghenv.Component.Message = "sample {}/{}".format(i + 1, n)
31 changes: 24 additions & 7 deletions src/aixd_grasshopper/components/aixd_Generator/metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"name": "requested_values",
"description": "List of requested values, each formatted as a string with the following format: 'variable_name:value'.",
"typeHintID": "str",
"scriptParamAccess": 0
"scriptParamAccess": 1
},
{
"name": "n_designs",
Expand All @@ -22,18 +22,35 @@
"scriptParamAccess": 0
},
{
"name": "run",
"name": "generate",
"description": "Set to True to start the generation process.",
"typeHintID": "none",
"typeHintID": "bool",
"scriptParamAccess": 0
},
{
"name": "clear",
"description": "Forget the previously generated designs.",
"typeHintID": "bool",
"scriptParamAccess": 0
},
{
"name": "pick_previous",
"description": "Iterate backward through the list of generated designs, instantiate the previous sample.",
"typeHintID": "bool",
"scriptParamAccess": 0
},
{
"name": "pick_next",
"description": "Iterate forward through the list of generated designs, instantiate the next sample.",
"typeHintID": "bool",
"scriptParamAccess": 0
}
],

"outputParameters": [
{
"name": "predicions",
"description": "List of generated designs."
"name": "sample",
"description": "Selected sample to instantiate in the parametric model."
}
]
}
}
}
29 changes: 28 additions & 1 deletion src/aixd_grasshopper/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import torch
from aixd.data.data_blocks import DesignParameters
from aixd.data.data_blocks import PerformanceAttributes
from aixd.data.data_objects import DataInt
from aixd.data.data_objects import DataInt, DataBool, DataCategorical, DataReal
from aixd.data.dataset import Dataset
from aixd.data.utils_data import reformat_dataframe_to_dataframeflat
from aixd.data.utils_data import reformat_dataframeflat_to_dict
Expand Down Expand Up @@ -229,6 +229,33 @@ def get_dataobject_names_from_block(self, datablock_nickname):
return {"msg": "", "names": self.datamodule.output_ml_dblock.names_list}
return {"msg": f"Wrong block nickname: {datablock_nickname}.", "names": []}

def get_dataobject_types(self):
"""
Returns names of the data types of the dataobjects in the dataset.
"""
if not self.dataset:
error = "Dataset is not loaded."
raise ValueError(error)

all_dataobjects = self.dataset.data_objects
# cannot use this because boolean are declared as categorical
# dataobject_types = {d.name: d.type for d in all_dataobjects}

dataobject_types = {}
for d in all_dataobjects:
if isinstance(d, DataInt):
dataobject_types[d.name] = "integer"
elif isinstance(d, DataReal):
dataobject_types[d.name] = "real"
elif isinstance(d, DataCategorical):
dataobject_types[d.name] = "categorical"
elif isinstance(d, DataBool):
dataobject_types[d.name] = "boolean"
else:
dataobject_types[d.name] = "unsupported"

return {"msg": "", "dataobject_types": dataobject_types}

def get_design_parameters(self):
# TODO: rename
if not self.dataset:
Expand Down
5 changes: 5 additions & 0 deletions src/aixd_grasshopper/gh_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ def get_dataobject_names_from_block(session_id, datablock_nickname):
return http_post_request(action="get_dataobject_names_from_block", data=data)


def get_dataobject_types(session_id):
data = {"session_id": session_id}
return http_post_request(action="get_dataobject_types", data=data)


def get_one_sample(session_id, i):
data = {"session_id": session_id, "item": i}
return http_post_request(action="get_one_sample", data=data)
Expand Down

0 comments on commit a8f0473

Please sign in to comment.