Skip to content

Commit

Permalink
test
Browse files Browse the repository at this point in the history
  • Loading branch information
NikolaiPetukhov committed Sep 29, 2023
1 parent ea5864c commit c38943c
Show file tree
Hide file tree
Showing 82 changed files with 6,025 additions and 3,187 deletions.
57 changes: 57 additions & 0 deletions edges.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
[
{
"id": "169143702805114",
"output": {
"node": "data_1",
"interface": "destination"
},
"input": {
"node": "if_3",
"interface": "source"
}
},
{
"id": "169143703364517",
"output": {
"node": "if_3",
"interface": "destination_true"
},
"input": {
"node": "approx_vector_2",
"interface": "source"
}
},
{
"id": "169143703561020",
"output": {
"node": "if_3",
"interface": "destination_false"
},
"input": {
"node": "duplicate_objects_4",
"interface": "source"
}
},
{
"id": "169143704716225",
"output": {
"node": "approx_vector_2",
"interface": "destination"
},
"input": {
"node": "save_5",
"interface": "source"
}
},
{
"id": "169143704898828",
"output": {
"node": "duplicate_objects_4",
"interface": "destination"
},
"input": {
"node": "save_5",
"interface": "source"
}
}
]
50 changes: 50 additions & 0 deletions graph.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
[
{
"action": "data",
"src": [
"Lemons for exam PRED/*"
],
"dst": "$data_1",
"settings": {
"classes_mapping": "default"
}
},
{
"action": "if",
"src": [
"$data_1"
],
"dst": [
"$if_2_true",
"$if_2_false"
],
"settings": {
"condition": {
"probability": 0.66
}
}
},
{
"action": "drop_obj_by_class",
"src": [
"$if_2_true"
],
"dst": "$drop_obj_by_class_3",
"settings": {
"classes": [
"kiwi"
]
}
},
{
"action": "save",
"src": [
"$if_2_false",
"$drop_obj_by_class_3"
],
"dst": "lemons_transformed",
"settings": {
"visualize": true
}
}
]
431 changes: 431 additions & 0 deletions nodes.json

Large diffs are not rendered by default.

47 changes: 47 additions & 0 deletions nodes_state.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"data_1": {
"Info": null,
"source_text": "Source",
"src": "src1",
"classes_mapping_text": "Classes Mapping",
"classes_mapping": "\"default\""
},
"data_2": {
"Info": null,
"source_text": "Source",
"src": "src2",
"classes_mapping_text": "Classes Mapping",
"classes_mapping": "{\"cls2\":\"cls2_copy\"}"
},
"if_3": {
"Info": null,
"condition_text": "Condition",
"condition": "probability",
"condition_value_text": "Condition Value",
"condition_value": "0.8"
},
"approx_vector_4": {
"Info": null,
"classes_text": "Classes",
"classes": "cls1",
"epsilon_text": "Epsilon",
"epsilon": 3
},
"bitmap2lines_5": {
"Info": null,
"min_points_cnt_text": "Min Points Count",
"min_points_cnt": 2,
"classes_mapping_text": "Classes Mapping",
"classes_mapping": "{\"cls1\": \"cls1_line\"}"
},
"find_contours_6": {
"Info": null,
"classes_mapping_text": "Classes Mapping",
"classes_mapping": "{\"cls2_copy\":\"cls2_copy_cont\"}"
},
"supervisely_7": {
"Info": null,
"destination_text": "Destination",
"dst": "result"
}
}
4 changes: 3 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ git+https://github.com/supervisely/supervisely.git@NikolaiPetukhov
jsonschema
networkx
scikit-image>=0.17.1, <1.0.0
cacheout
cacheout
markdown
json2html
126 changes: 83 additions & 43 deletions src/compute/Layer.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from supervisely.imaging.color import hex2rgb

from src.compute.classes_utils import ClassConstants
from src.exceptions import CustomException, GraphError, CreateMetaError, UnexpectedError


def maybe_wrap_in_list(v):
Expand All @@ -26,9 +27,9 @@ def maybe_wrap_in_list(v):

def check_connection_name(connection_name):
if len(connection_name) == 0:
raise RuntimeError("Connection name should be non empty.")
raise GraphError("Connection name should be non empty.")
if connection_name[0] != "$" and connection_name != Layer.null:
raise RuntimeError('Connection name should be "%s" or start with "$".' % Layer.null)
raise GraphError(f'Connection name should be "{Layer.null}" or start with "$".')


class Layer:
Expand Down Expand Up @@ -84,9 +85,16 @@ def __init__(self, config):
self.output_meta = None

def validate(self):
jsonschema.validate(self._config, self.params)
self.validate_source_connections()
self.validate_dest_connections()
try:
jsonschema.validate(self._config, self.params)
except jsonschema.ValidationError as e:
raise GraphError("Layer not valid", error=e, extra={"layer_config": self._config})
try:
self.validate_source_connections()
self.validate_dest_connections()
except GraphError as e:
e.extra["layer_config"] = self._config
raise e

@property
def config(self):
Expand All @@ -110,7 +118,7 @@ def requires_image(self):
def validate_source_connections(self):
for src in self.srcs:
if src == Layer.null:
raise RuntimeError('"%s" cannot be in "src".' % Layer.null)
raise GraphError(f'"Layer.null" cannot be in "src"')
check_connection_name(src)

def validate_dest_connections(self):
Expand All @@ -130,17 +138,31 @@ def make_output_meta(self, input_metas_dict):
if existing_obj_class is None:
full_input_meta = full_input_meta.add_obj_class(inp_obj_class)
elif existing_obj_class.geometry_type != inp_obj_class.geometry_type:
raise RuntimeError(
f"Trying to add new class ({inp_obj_class.name}) with shape ({inp_obj_class.geometry_type.geometry_name()}). Same class with different shape ({existing_obj_class.geometry_type.geometry_name()}) exists."
raise CreateMetaError(
"Trying to add existing ObjClass with different geometry type",
extra={
"existing_class": existing_obj_class.to_json(),
"new_class": inp_obj_class.to_json(),
},
)
# raise RuntimeError(
# f"Trying to add new class ({inp_obj_class.name}) with shape ({inp_obj_class.geometry_type.geometry_name()}). Same class with different shape ({existing_obj_class.geometry_type.geometry_name()}) exists."
# )
for inp_tag_meta in inp_meta.tag_metas:
existing_tag_meta = full_input_meta.tag_metas.get(inp_tag_meta.name, None)
if existing_tag_meta is None:
full_input_meta = full_input_meta.add_tag_meta(inp_tag_meta)
elif not existing_tag_meta.is_compatible(inp_tag_meta):
raise RuntimeError(
f"Trying to add new tag ({inp_tag_meta.name}) with type ({inp_tag_meta.value_type}) and possible values ({inp_tag_meta.possible_values}). Same tag with different type ({existing_tag_meta.value_type}) or possible values ({existing_tag_meta.possible_values}) exists."
raise CreateMetaError(
"Trying to add existing TagMeta with different type or possible values",
extra={
"existing_tag_meta": existing_tag_meta.to_json(),
"new_tag_meta": inp_tag_meta.to_json(),
},
)
# raise RuntimeError(
# f"Trying to add new tag ({inp_tag_meta.name}) with type ({inp_tag_meta.value_type}) and possible values ({inp_tag_meta.possible_values}). Same tag with different type ({existing_tag_meta.value_type}) or possible values ({existing_tag_meta.possible_values}) exists."
# )

res_meta = deepcopy(full_input_meta)
in_class_titles = set((obj_class.name for obj_class in full_input_meta.obj_classes))
Expand All @@ -152,9 +174,17 @@ def make_output_meta(self, input_metas_dict):
self.cls_mapping[oclass] = self.cls_mapping[ClassConstants.OTHER]
del self.cls_mapping[ClassConstants.OTHER]

missed_classes = in_class_titles - set(self.cls_mapping.keys())
if len(missed_classes) != 0:
raise RuntimeError("Some classes in mapping are missed: {}".format(missed_classes))
missing_classes = in_class_titles - set(self.cls_mapping.keys())
if len(missing_classes) != 0:
raise CreateMetaError(
"Some classes in input meta are missing in mapping",
extra={
"missing_classes": [
res_meta.obj_classes.get(obj_class_name)
for obj_class_name in missing_classes
]
},
)

for src_class_title, dst_class in self.cls_mapping.items():
# __new__ -> [ list of classes ]
Expand All @@ -165,28 +195,37 @@ def make_output_meta(self, input_metas_dict):
new_name = new_cls_dict["title"]
new_shape = new_cls_dict["shape"]
new_geometry_type = GET_GEOMETRY_FROM_STR(new_shape)
inp_obj_class = ObjClass(new_name, new_geometry_type)
if res_meta.obj_classes.has_key(new_name):
existing_cls = res_meta.obj_classes.get(new_name)
if existing_cls.geometry_type != new_geometry_type:
existing_obj_class = res_meta.obj_classes.get(new_name)
if existing_obj_class.geometry_type != new_geometry_type:
raise CreateMetaError(
"Trying to add existing ObjClass with different geometry type",
extra={
"existing_class": existing_obj_class.to_json(),
"new_class": inp_obj_class.to_json(),
},
)
raise RuntimeError(
f"Trying to add new class ({new_name}) with shape ({new_shape}). Same class with different shape ({existing_cls.geometry_type.geometry_name()}) exists."
)
else:
new_cls = ObjClass(new_name, new_geometry_type)
res_meta = res_meta.add_obj_class(new_cls)
res_meta = res_meta.add_obj_class(inp_obj_class)

# __clone__ -> dict {parent_cls_name: child_cls_name}
elif src_class_title == ClassConstants.CLONE:
if type(dst_class) is not dict:
raise RuntimeError("Internal class mapping error in layer (CLONE spec).")

for src_title, dst_title in dst_class.items():
real_src_cls = full_input_meta.obj_classes.get(src_title, None)
real_src_cls = res_meta.obj_classes.get(src_title, None)
if real_src_cls is None:
raise RuntimeError(
'Class mapping error, source class "{}" not found.'.format(
src_title
)
raise CreateMetaError(
"Class not found in input meta",
extra={
"class_name": src_title,
"existing_classes": res_meta.obj_classes.to_json(),
},
)
real_dst_cls = real_src_cls.clone(name=dst_title)
res_meta = res_meta.add_obj_class(real_dst_cls)
Expand All @@ -198,21 +237,24 @@ def make_output_meta(self, input_metas_dict):
for cls_dct in dst_class:
title = cls_dct["title"]
existing_class = res_meta.obj_classes.get(title, None)
if existing_class is not None:
new_shape = cls_dct.get("shape", None)
new_geometry_type = (
GET_GEOMETRY_FROM_STR(new_shape) if new_shape else None
if existing_class is None:
raise CreateMetaError(
"Class not found in input meta",
extra={
"class_name": title,
"existing_classes": res_meta.obj_classes.to_json(),
},
)
new_color = cls_dct.get("color", None)
if new_color is not None and new_color[0] == "#":
new_color = hex2rgb(new_color)
new_obj_cls = existing_class.clone(
name=title, geometry_type=new_geometry_type, color=new_color
)
res_meta = res_meta.delete_obj_class(title)
res_meta = res_meta.add_obj_class(new_obj_cls)
else:
raise RuntimeError("Can not update class {}. Not found".format(title))
new_shape = cls_dct.get("shape", None)
new_geometry_type = GET_GEOMETRY_FROM_STR(new_shape) if new_shape else None
new_color = cls_dct.get("color", None)
if new_color is not None and new_color[0] == "#":
new_color = hex2rgb(new_color)
new_obj_cls = existing_class.clone(
name=title, geometry_type=new_geometry_type, color=new_color
)
res_meta = res_meta.delete_obj_class(title)
res_meta = res_meta.add_obj_class(new_obj_cls)

# smth -> __default__
elif dst_class == ClassConstants.DEFAULT:
Expand Down Expand Up @@ -244,7 +286,6 @@ def make_output_meta(self, input_metas_dict):
res_meta = res_meta.delete_obj_class(src_class_title)
res_meta = res_meta.add_obj_class(obj_cls)

# TODO switch to get added / removed tags to be TagMeta instances.
rm_imtags = [TagMeta.from_json(tag) for tag in self.get_removed_tag_metas()]
res_meta = res_meta.clone(
tag_metas=[tm for tm in res_meta.tag_metas if tm not in rm_imtags]
Expand All @@ -253,19 +294,18 @@ def make_output_meta(self, input_metas_dict):
new_imtags_exist = [
tm for tm in res_meta.tag_metas.intersection(TagMetaCollection(new_imtags))
]
# new_imtags_exist = res_meta.tags.intersection(new_imtags).to_list()
if len(new_imtags_exist) != 0:
exist_tag_names = [t.name for t in new_imtags_exist]
logger.warn("Tags {} already exist.".format(exist_tag_names))
res_meta.clone(tag_metas=new_imtags)
self.output_meta = res_meta
except CustomException as e:
raise e
except Exception as e:
logger.error(
"Meta-error occurred in layer '{}' with config: {}".format(
self.action, self._config
)
raise UnexpectedError(
"Unexpected error occurred while creating meta",
error=e,
)
raise e

return self.output_meta

Expand Down
Loading

0 comments on commit c38943c

Please sign in to comment.