From 8371e42a0a2a41b9d9c50bdf1178949d578f002d Mon Sep 17 00:00:00 2001 From: Victor Doval <10011941+vicdoval@users.noreply.github.com> Date: Fri, 7 Feb 2020 09:52:36 +0100 Subject: [PATCH 1/7] List Join numpy mode and other numpy candy --- docs/nodes/list_main/join.rst | 10 +++ nodes/list_main/join.py | 94 +++++++++++++++++------ nodes/number/random_num_gen.py | 12 ++- nodes/transforms/barycentric_transform.py | 8 +- nodes/vector/vector_out.py | 2 +- utils/listutils.py | 19 ++--- utils/sv_obj_baker.py | 6 +- 7 files changed, 111 insertions(+), 40 deletions(-) diff --git a/docs/nodes/list_main/join.rst b/docs/nodes/list_main/join.rst index e1a32aac2..f856dd973 100644 --- a/docs/nodes/list_main/join.rst +++ b/docs/nodes/list_main/join.rst @@ -4,6 +4,8 @@ List Join Functionality ------------- +This node joins different list into a single one. + level 1: [ [ (1,2,3), (4,5,6) ] ] + [ [ (7,8,9), (10,11,12) ] ] = [ [ (1,2,3), (4,5,6), (7,8,9), (10,11,12) ] ] @@ -40,6 +42,14 @@ Parameters **wrap** to wrap additional level **levels** level of joining +Advanced Parameters +------------------- + +In the N-Panel (and on the right-click menu) you can find: + +**NumPy Mode**: When enabled the node will expect and produce lists of NumPy arrays. It will be faster when joining NumPy Arrays but due the nature of the implementation it will fail when trying to join arrays with different axis number. + + Outputs ------- diff --git a/nodes/list_main/join.py b/nodes/list_main/join.py index 31339c09e..2d20b9b46 100644 --- a/nodes/list_main/join.py +++ b/nodes/list_main/join.py @@ -1,4 +1,4 @@ -# This file is part of project Sverchok. It's copyrighted by the contributors + # This file is part of project Sverchok. It's copyrighted by the contributors # recorded in the version control history of the file, available from # its original location https://github.com/nortikin/sverchok/commit/master # @@ -9,9 +9,50 @@ import bpy from bpy.props import BoolProperty, IntProperty, StringProperty from sverchok.node_tree import SverchCustomTreeNode -from sverchok.data_structure import (changable_sockets, multi_socket, updateNode) +from sverchok.data_structure import (multi_socket, updateNode) from sverchok.utils.listutils import joiner, myZip_2, wrapper_2 +import numpy as np + + +def python_join(slots, level, mix, wrap): + if wrap: + if mix: + list_mix = myZip_2(slots, level) + list_wrap_mix = wrapper_2(slots, list_mix, level) + result = list_wrap_mix.copy() + else: + list_result = joiner(slots, level) + list_wrap = wrapper_2(slots, list_result, level) + result = list_wrap.copy() + else: + if mix: + list_mix = myZip_2(slots, level) + result = list_mix.copy() + else: + list_result = joiner(slots, level) + result = list_result.copy() + return result + +def numpy_join(slots, level, mix): + if level == 1: + if mix: + result = [l for s in zip(*slots) for l in s] + else: + result = [np.array(l) for s in slots for l in s] + elif level == 2: + if mix: + result = [np.concatenate([l for s in zip(*slots) for l in zip(*s)], axis=0)] + else: + result = [np.concatenate([l for s in slots for l in s], axis=0)] + elif level == 3: + if mix: + result = [np.concatenate([sl for s in zip(*slots) for l in zip(*s) for sl in zip(*l)], axis=0)] + else: + result = [np.concatenate([sl for s in slots for l in s for sl in l], axis=0)] + else: + result = python_join(slots, level, mix, False) + return result class ListJoinNode(bpy.types.Node, SverchCustomTreeNode): ''' ListJoin node ''' @@ -22,7 +63,7 @@ class ListJoinNode(bpy.types.Node, SverchCustomTreeNode): JoinLevel: IntProperty( name='JoinLevel', description='Choose join level of data (see help)', - default=1, min=1, update=updateNode) + default=1, min=1, update=updateNode) mix_check: BoolProperty( name='mix', description='Grouping similar to zip()', @@ -32,9 +73,14 @@ class ListJoinNode(bpy.types.Node, SverchCustomTreeNode): name='wrap', description='Grouping similar to append(list)', default=False, update=updateNode) + numpy_mode: BoolProperty( + name='NumPy Mode', description='better to work with lists of NumPy arrays', + default=False, update=updateNode) + typ: StringProperty(name='typ', default='') newsock: BoolProperty(name='newsock', default=False) + base_name = 'data ' multi_socket_type = 'SvStringsSocket' @@ -43,10 +89,21 @@ class ListJoinNode(bpy.types.Node, SverchCustomTreeNode): self.outputs.new('SvStringsSocket', 'data') def draw_buttons(self, context, layout): + layout.prop(self, "mix_check", text="mix") - layout.prop(self, "wrap_check", text="wrap") + if not self.numpy_mode: + layout.prop(self, "wrap_check", text="wrap") layout.prop(self, "JoinLevel", text="JoinLevel lists") + def draw_buttons_ext(self, context, layout): + self.draw_buttons(context, layout) + layout.prop(self, "numpy_mode", toggle=False, text='NumPy mode') + + def rclick_menu(self, context, layout): + self.draw_buttons(context, layout) + layout.prop(self, "numpy_mode", toggle=True, text='NumPy mode') + + def update(self): if len(self.outputs) > 0: @@ -65,19 +122,10 @@ class ListJoinNode(bpy.types.Node, SverchCustomTreeNode): if len(slots) == 0: return - list_result = joiner(slots, self.JoinLevel) - result = list_result.copy() - if self.mix_check: - list_mix = myZip_2(slots, self.JoinLevel) - result = list_mix.copy() - - if self.wrap_check: - list_wrap = wrapper_2(slots, list_result, self.JoinLevel) - result = list_wrap.copy() - - if self.mix_check: - list_wrap_mix = wrapper_2(slots, list_mix, self.JoinLevel) - result = list_wrap_mix.copy() + if self.numpy_mode: + result = numpy_join(slots, self.JoinLevel, self.mix_check) + else: + result = python_join(slots, self.JoinLevel, self.mix_check, self.wrap_check) self.outputs[0].sv_set(result) @@ -87,12 +135,13 @@ class ListJoinNode(bpy.types.Node, SverchCustomTreeNode): to a generic SvStringsSocket type 2) if all input sockets where sv_get is successful are of identical bl_idname then set the output socket type to match that. - 3) no op if current output socket matches proposed new socket type. + 3) no op if current output socket matches proposed new socket type. """ - if not slot_bl_idnames: return + if not slot_bl_idnames: + return - num_bl_idnames = len(set(slot_bl_idnames)) + num_bl_idnames = len(set(slot_bl_idnames)) new_socket_type = slot_bl_idnames[0] if num_bl_idnames == 1 else "SvStringsSocket" if self.outputs[0].bl_idname != new_socket_type: @@ -101,9 +150,10 @@ class ListJoinNode(bpy.types.Node, SverchCustomTreeNode): def draw_label(self): """ this gives quick param display for when the node is minimzed """ mixing = "M" if self.mix_check else "" - wrapping = "W" if self.wrap_check else "" + wrapping = "W" if self.wrap_check and not self.numpy_mode else "" + numpy_m = "NP " if self.numpy_mode else "" level = str(self.JoinLevel) - fstr = " Lv={0} {1}{2}".format(level, mixing, wrapping) + fstr = " Lv={0} {1}{2}{3}".format(level, numpy_m, mixing, wrapping) return self.name + fstr diff --git a/nodes/number/random_num_gen.py b/nodes/number/random_num_gen.py index 784748176..35eed017c 100644 --- a/nodes/number/random_num_gen.py +++ b/nodes/number/random_num_gen.py @@ -196,7 +196,17 @@ class SvRndNumGen(bpy.types.Node, SverchCustomTreeNode): def draw_buttons_ext(self, context, layout): self.buttons(layout) - layout.prop(self, "as_list") + layout.prop(self, "as_list", invert_checkbox=True, text="Output NumPy") + + def rclick_menu(self, context, layout): + layout.prop_menu_enum(self, "type_selected_mode", text="Number Type: "+ self.type_selected_mode) + if self.type_selected_mode == "Int": + layout.prop(self, "unique", toggle=True ) + layout.prop(self, "weighted", toggle=True) + else: + layout.prop_menu_enum(self, "distribute_mode") + layout.prop(self, "as_list", toggle=True, invert_checkbox=True, text="Output NumPy") + def int_random_range(self, *params): if len(params) < 5: diff --git a/nodes/transforms/barycentric_transform.py b/nodes/transforms/barycentric_transform.py index 9767315a3..9ede6d798 100644 --- a/nodes/transforms/barycentric_transform.py +++ b/nodes/transforms/barycentric_transform.py @@ -76,10 +76,10 @@ def compute_barycentric_transform_np(params, matched_index, result, out_numpy, e for v_id, edge_id, tri_src_id, tri_dest_id in zip(*matched_index): - - barycentric_co = dot(inverted_matrix_s[tri_src_id], (np_verts[v_id] - tri3_src[tri_src_id]).T) + + barycentric_co = dot(inverted_matrix_s[tri_src_id], (np_verts[v_id] - tri3_src[tri_src_id]).T) cartesian_co = dot(barycentric_co.T, matrix_transform_d[tri_dest_id]) + tri3_dest[tri_dest_id] - + result[0].append(cartesian_co if out_numpy else cartesian_co.tolist()) if edg_pol_data: result[1].append(egde_pol[edge_id]) @@ -149,7 +149,7 @@ class SvBarycentricTransformNode(bpy.types.Node, SverchCustomTreeNode): '''right click sv_menu items''' layout.prop_menu_enum(self, "implementation", text="Implementation") if self.implementation == "NumPy": - layout.prop(self, "output_numpy", toggle=False) + layout.prop(self, "output_numpy", toggle=True) layout.prop_menu_enum(self, "list_match", text="List Match") def get_data(self): diff --git a/nodes/vector/vector_out.py b/nodes/vector/vector_out.py index 78eec1e96..52a7f863c 100644 --- a/nodes/vector/vector_out.py +++ b/nodes/vector/vector_out.py @@ -53,7 +53,7 @@ class VectorsOutNode(bpy.types.Node, SverchCustomTreeNode): layout.prop(self, "output_numpy", toggle=True) def process(self): - if self.inputs['Vectors'].is_linked: + if self.inputs['Vectors'].is_linked and any(s.is_linked for s in self.outputs): xyz = self.inputs['Vectors'].sv_get(deepcopy=False) data = dataCorrect_np(xyz) diff --git a/utils/listutils.py b/utils/listutils.py index ad4b5f064..9c3b049ec 100644 --- a/utils/listutils.py +++ b/utils/listutils.py @@ -18,6 +18,7 @@ from functools import reduce +from numpy import ndarray ##################################################### #################### lists magic #################### ##################################################### @@ -116,7 +117,7 @@ def myZip_2(list_all, level, level2=1): def subDown(list_a, level): list_b = [] for l2 in list_a: - if type(l2) in [list, tuple]: + if type(l2) in [list, tuple, ndarray]: list_b.extend(l2) else: list_b.append(l2) @@ -125,7 +126,7 @@ def myZip_2(list_all, level, level2=1): return list_b list_tmp = [] - if type(list_all) in [list, tuple]: + if type(list_all) in [list, tuple, ndarray]: for l in list_all: list_b = subDown(l, level-1) list_tmp.append(list_b) @@ -141,7 +142,7 @@ def myZip_2(list_all, level, level2=1): l_min = [] for el in list_tmp: - if type(el) not in [list, tuple]: + if type(el) not in [list, tuple, ndarray]: break l_min.append(len(el)) @@ -165,9 +166,9 @@ def joiner(list_all, level, level2=1): list_tmp = [] if level > level2: - if type(list_all) in [list, tuple]: + if type(list_all) in [list, tuple, ndarray]: for list_a in list_all: - if type(list_a) in [list, tuple]: + if type(list_a) in [list, tuple, ndarray]: list_tmp.extend(list_a) else: list_tmp.append(list_a) @@ -178,9 +179,9 @@ def joiner(list_all, level, level2=1): list_tmp = [list_res] if level == level2: - if type(list_all) in [list, tuple]: + if type(list_all) in [list, tuple, ndarray]: for list_a in list_all: - if type(list_a) in [list, tuple]: + if type(list_a) in [list, tuple, ndarray]: list_tmp.extend(list_a) else: list_tmp.append(list_a) @@ -188,7 +189,7 @@ def joiner(list_all, level, level2=1): list_tmp.append(list_all) if level < level2: - if type(list_all) in [list, tuple]: + if type(list_all) in [list, tuple, ndarray]: for l in list_all: list_tmp.append(l) else: @@ -218,7 +219,7 @@ def wrapper_2(l_etalon, list_a, level): def subWrap_2(l_etalon, len_l, level): len_r = len_l - if type(l_etalon) in [list, tuple]: + if type(l_etalon) in [list, tuple, ndarray]: len_r = len(l_etalon) * len_l if level > 1: len_r = subWrap_2(l_etalon[0], len_r, level-1) diff --git a/utils/sv_obj_baker.py b/utils/sv_obj_baker.py index f4cc7b448..275c2ac57 100644 --- a/utils/sv_obj_baker.py +++ b/utils/sv_obj_baker.py @@ -1,7 +1,7 @@ # This file is part of project Sverchok. It's copyrighted by the contributors # recorded in the version control history of the file, available from # its original location https://github.com/nortikin/sverchok/commit/master -# +# # SPDX-License-Identifier: GPL3 # License-Filename: LICENSE @@ -10,7 +10,7 @@ import bpy from bpy.props import StringProperty from mathutils import Vector, Matrix -from sverchok.data_structure import node_id, dataCorrect +from sverchok.data_structure import node_id, dataCorrect, dataCorrect_np cache_viewer_baker = {} @@ -63,7 +63,7 @@ class SvObjBakeMK3(bpy.types.Operator): if matrix_cache and not vertex_cache: return {'CANCELLED'} - v = dataCorrect(vertex_cache) + v = dataCorrect_np(vertex_cache) e = self.dataCorrect3(edg_cache) p = self.dataCorrect3(pol_cache) m = self.dataCorrect2(matrix_cache, v) -- GitLab From 7be77d110bc7717644aeaab0789e83dcaa03076b Mon Sep 17 00:00:00 2001 From: Victor Doval <10011941+vicdoval@users.noreply.github.com> Date: Fri, 7 Feb 2020 17:17:40 +0100 Subject: [PATCH 2/7] improved level 2 join --- nodes/list_main/join.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/nodes/list_main/join.py b/nodes/list_main/join.py index 2d20b9b46..901ef323b 100644 --- a/nodes/list_main/join.py +++ b/nodes/list_main/join.py @@ -37,14 +37,23 @@ def python_join(slots, level, mix, wrap): def numpy_join(slots, level, mix): if level == 1: if mix: - result = [l for s in zip(*slots) for l in s] + result = [np.array(l) for s in zip(*slots) for l in s] else: result = [np.array(l) for s in slots for l in s] elif level == 2: if mix: result = [np.concatenate([l for s in zip(*slots) for l in zip(*s)], axis=0)] + joined = np.concatenate(slots, axis=2) + ln = len(slots[0][0][0]) + result = [joined.reshape(-1, ln)] else: result = [np.concatenate([l for s in slots for l in s], axis=0)] + joined = np.concatenate(slots, axis=0) + ln = len(slots[0][0][0]) + result = [joined.reshape(-1, ln)] + # result = [joined] + # result = [np.concatenate(slots, axis=2)] + print(joined.shape, ln, slots[0][0][0]) elif level == 3: if mix: result = [np.concatenate([sl for s in zip(*slots) for l in zip(*s) for sl in zip(*l)], axis=0)] -- GitLab From 3e6292ee107d7c84ceccd706ace822806733b52e Mon Sep 17 00:00:00 2001 From: Victor Doval <10011941+vicdoval@users.noreply.github.com> Date: Fri, 7 Feb 2020 20:47:29 +0100 Subject: [PATCH 3/7] Working on level 1 --- data_structure.py | 2 ++ nodes/list_main/join.py | 34 +++++++++++++++++++++++++++------- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/data_structure.py b/data_structure.py index 6e115c57a..3bc12532a 100755 --- a/data_structure.py +++ b/data_structure.py @@ -467,6 +467,8 @@ def describe_data_shape(data): """ def helper(data): if not isinstance(data, (list, tuple)): + if isinstance(data,(np.ndarray)): + return 0, type(data).__name__ + " of " + str(data.dtype) + " with shape " + str(data.shape) return 0, type(data).__name__ else: result = type(data).__name__ diff --git a/nodes/list_main/join.py b/nodes/list_main/join.py index 901ef323b..96801bfbf 100644 --- a/nodes/list_main/join.py +++ b/nodes/list_main/join.py @@ -33,13 +33,22 @@ def python_join(slots, level, mix, wrap): list_result = joiner(slots, level) result = list_result.copy() return result - +def correct_arrays(arrays): + tmp_list =[] + for a in arrays: + print(a.shape) + if len(a.shape) > 2: + tmp_list.append([l for l in a]) + else: + tmp_list.append(a) + return tmp_list def numpy_join(slots, level, mix): if level == 1: if mix: - result = [np.array(l) for s in zip(*slots) for l in s] + result = correct_arrays([np.array(l) for s in zip(*slots) for l in s]) else: result = [np.array(l) for s in slots for l in s] + result = correct_arrays(result) elif level == 2: if mix: result = [np.concatenate([l for s in zip(*slots) for l in zip(*s)], axis=0)] @@ -51,14 +60,25 @@ def numpy_join(slots, level, mix): joined = np.concatenate(slots, axis=0) ln = len(slots[0][0][0]) result = [joined.reshape(-1, ln)] - # result = [joined] - # result = [np.concatenate(slots, axis=2)] - print(joined.shape, ln, slots[0][0][0]) + elif level == 3: if mix: - result = [np.concatenate([sl for s in zip(*slots) for l in zip(*s) for sl in zip(*l)], axis=0)] + # result = [np.concatenate([sl for s in zip(*slots) for l in zip(*s) for sl in zip(*l)], axis=0)] + joined = np.concatenate(slots, axis=0) + result = [joined] + if type(slots[0][0][0][0]) in [int, float]: + result = [np.transpose(joined, (1, 2,0)).flatten()] + # else: + # ln = len(slots[0][0][0][0]) + # result = [joined.reshape(-1, ln)] else: - result = [np.concatenate([sl for s in slots for l in s for sl in l], axis=0)] + joined = np.concatenate(slots, axis=0) + if type(slots[0][0][0][0]) in [int, float]: + result = [joined.flatten()] + else: + ln = len(slots[0][0][0][0]) + result = [joined.reshape(-1, ln)] + # result = [np.concatenate([sl for s in slots for l in s for sl in l], axis=0)] else: result = python_join(slots, level, mix, False) return result -- GitLab From 47415a5596c2e1589ed71339dfc446776e52dbdf Mon Sep 17 00:00:00 2001 From: Victor Doval <10011941+vicdoval@users.noreply.github.com> Date: Sat, 8 Feb 2020 14:20:58 +0100 Subject: [PATCH 4/7] exploring situations --- nodes/list_main/join.py | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/nodes/list_main/join.py b/nodes/list_main/join.py index 96801bfbf..2a4673616 100644 --- a/nodes/list_main/join.py +++ b/nodes/list_main/join.py @@ -42,10 +42,10 @@ def correct_arrays(arrays): else: tmp_list.append(a) return tmp_list -def numpy_join(slots, level, mix): +def numpy_join(slots, level, mix, min_axis): if level == 1: if mix: - result = correct_arrays([np.array(l) for s in zip(*slots) for l in s]) + result = correct_arrays([np.array(l) for s in zip(*slots) for l in s]) else: result = [np.array(l) for s in slots for l in s] result = correct_arrays(result) @@ -53,12 +53,20 @@ def numpy_join(slots, level, mix): if mix: result = [np.concatenate([l for s in zip(*slots) for l in zip(*s)], axis=0)] joined = np.concatenate(slots, axis=2) - ln = len(slots[0][0][0]) + # ln = len(slots[0][0][0]) + if min_axis == 2: + ln =3 + else: + ln = 1 result = [joined.reshape(-1, ln)] else: result = [np.concatenate([l for s in slots for l in s], axis=0)] joined = np.concatenate(slots, axis=0) - ln = len(slots[0][0][0]) + # ln = len(slots[0][0][0]) + if min_axis == 2: + ln =3 + else: + ln = 1 result = [joined.reshape(-1, ln)] elif level == 3: @@ -152,7 +160,11 @@ class ListJoinNode(bpy.types.Node, SverchCustomTreeNode): return if self.numpy_mode: - result = numpy_join(slots, self.JoinLevel, self.mix_check) + if self.outputs[0].bl_idname == 'SvVerticesSocket': + min_axis = 2 + else: + min_axis = 1 + result = numpy_join(slots, self.JoinLevel, self.mix_check, min_axis) else: result = python_join(slots, self.JoinLevel, self.mix_check, self.wrap_check) -- GitLab From a70b6297bab7f08d2a4bf6fed72ce63e8d2c2704 Mon Sep 17 00:00:00 2001 From: Victor Doval <10011941+vicdoval@users.noreply.github.com> Date: Wed, 12 Feb 2020 09:15:50 +0100 Subject: [PATCH 5/7] shuold be simpler --- nodes/list_main/join.py | 48 ++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/nodes/list_main/join.py b/nodes/list_main/join.py index 2a4673616..a9af55d83 100644 --- a/nodes/list_main/join.py +++ b/nodes/list_main/join.py @@ -52,22 +52,46 @@ def numpy_join(slots, level, mix, min_axis): elif level == 2: if mix: result = [np.concatenate([l for s in zip(*slots) for l in zip(*s)], axis=0)] - joined = np.concatenate(slots, axis=2) - # ln = len(slots[0][0][0]) if min_axis == 2: - ln =3 + joined = np.concatenate(slots, axis=2) else: - ln = 1 - result = [joined.reshape(-1, ln)] - else: - result = [np.concatenate([l for s in slots for l in s], axis=0)] - joined = np.concatenate(slots, axis=0) + joined = np.concatenate(slots, axis=0).T + result = [joined] # ln = len(slots[0][0][0]) - if min_axis == 2: - ln =3 + if type(slots[0][0][0]) in [int, float]: + result = [joined.flatten()] else: - ln = 1 - result = [joined.reshape(-1, ln)] + if min_axis == 2: + ln =3 + else: + ln = 1 + result = [joined.reshape(-1, ln)] + else: + # result = [np.concatenate([l for s in slots for l in s], axis=0)] + joined = np.concatenate(slots, axis=1) + print("F", type(slots[0][0][0]), joined.shape) + if type(slots[0][0][0]) in [list, tuple, np.ndarray]: + if min_axis == 2: + if len(joined.shape) > 3: + print("e") + result = [joined[0, l] for l in range(joined.shape[1])] + else: + result = [joined.reshape(-1, 3)] + else: + if len(joined.shape) > 2: + print("e") + result = [[joined[0, l] for l in range(joined.shape[1])]] + else: + # result = [joined.reshape(-1, 3)] + result =[joined] + else: + result = [joined.flatten()] + # if min_axis == 2: + # # ln = len(slots[0][0][0]) + # ln =3 + # else: + # ln = 1 + # result = [joined.reshape(-1, ln)] elif level == 3: if mix: -- GitLab From a3b8f7fa611d25cd10c310627e87202b9127a99f Mon Sep 17 00:00:00 2001 From: Victor Doval <10011941+vicdoval@users.noreply.github.com> Date: Thu, 20 Feb 2020 11:03:39 +0100 Subject: [PATCH 6/7] reduced to use cases --- data_structure.py | 4 +- nodes/list_main/join.py | 113 ++++++++++++---------------------------- 2 files changed, 34 insertions(+), 83 deletions(-) diff --git a/data_structure.py b/data_structure.py index 3bc12532a..cc6507248 100755 --- a/data_structure.py +++ b/data_structure.py @@ -467,8 +467,8 @@ def describe_data_shape(data): """ def helper(data): if not isinstance(data, (list, tuple)): - if isinstance(data,(np.ndarray)): - return 0, type(data).__name__ + " of " + str(data.dtype) + " with shape " + str(data.shape) + if isinstance(data, (np.ndarray)): + return len(data.shape), type(data).__name__ + " of " + str(data.dtype) + " with shape " + str(data.shape) return 0, type(data).__name__ else: result = type(data).__name__ diff --git a/nodes/list_main/join.py b/nodes/list_main/join.py index a9af55d83..233a4fa3b 100644 --- a/nodes/list_main/join.py +++ b/nodes/list_main/join.py @@ -9,7 +9,7 @@ import bpy from bpy.props import BoolProperty, IntProperty, StringProperty from sverchok.node_tree import SverchCustomTreeNode -from sverchok.data_structure import (multi_socket, updateNode) +from sverchok.data_structure import (multi_socket, updateNode, levels_of_list_or_np) from sverchok.utils.listutils import joiner, myZip_2, wrapper_2 import numpy as np @@ -33,87 +33,37 @@ def python_join(slots, level, mix, wrap): list_result = joiner(slots, level) result = list_result.copy() return result -def correct_arrays(arrays): - tmp_list =[] - for a in arrays: - print(a.shape) - if len(a.shape) > 2: - tmp_list.append([l for l in a]) - else: - tmp_list.append(a) - return tmp_list -def numpy_join(slots, level, mix, min_axis): - if level == 1: - if mix: - result = correct_arrays([np.array(l) for s in zip(*slots) for l in s]) - else: - result = [np.array(l) for s in slots for l in s] - result = correct_arrays(result) - elif level == 2: + +def np_object_level_2(slots): + return [np.concatenate([l for s in slots for l in s], axis=0)] + +def np_object_level_2_mix(slots): + return [np.concatenate([l for s in zip(*slots) for l in zip(*s)], axis=0)] + +def np_general_wrapper(slots, level, end_level, func): + if level == end_level: + return func(slots) + return [np_general_wrapper(slots, level-1, end_level, func)] + +def np_multi_object_level_3(slots): + return [[np.concatenate([l0 for s in slots for l in s for l0 in l])]] + +def np_multi_object_level_3_mix(slots): + return [[np.concatenate([l0 for s in zip(*slots) for l in zip(*s) for l0 in zip(*l)])]] + +def numpy_join(slots, level, mix, min_axis, depth): + true_depth = depth - min_axis + if true_depth == 1 and level > 1: if mix: - result = [np.concatenate([l for s in zip(*slots) for l in zip(*s)], axis=0)] - if min_axis == 2: - joined = np.concatenate(slots, axis=2) - else: - joined = np.concatenate(slots, axis=0).T - result = [joined] - # ln = len(slots[0][0][0]) - if type(slots[0][0][0]) in [int, float]: - result = [joined.flatten()] - else: - if min_axis == 2: - ln =3 - else: - ln = 1 - result = [joined.reshape(-1, ln)] - else: - # result = [np.concatenate([l for s in slots for l in s], axis=0)] - joined = np.concatenate(slots, axis=1) - print("F", type(slots[0][0][0]), joined.shape) - if type(slots[0][0][0]) in [list, tuple, np.ndarray]: - if min_axis == 2: - if len(joined.shape) > 3: - print("e") - result = [joined[0, l] for l in range(joined.shape[1])] - else: - result = [joined.reshape(-1, 3)] - else: - if len(joined.shape) > 2: - print("e") - result = [[joined[0, l] for l in range(joined.shape[1])]] - else: - # result = [joined.reshape(-1, 3)] - result =[joined] - else: - result = [joined.flatten()] - # if min_axis == 2: - # # ln = len(slots[0][0][0]) - # ln =3 - # else: - # ln = 1 - # result = [joined.reshape(-1, ln)] - - elif level == 3: + return np_general_wrapper(slots, level, 2, np_object_level_2_mix) + return np_general_wrapper(slots, level, 2, np_object_level_2) + + if true_depth == 2 and level > 2: if mix: - # result = [np.concatenate([sl for s in zip(*slots) for l in zip(*s) for sl in zip(*l)], axis=0)] - joined = np.concatenate(slots, axis=0) - result = [joined] - if type(slots[0][0][0][0]) in [int, float]: - result = [np.transpose(joined, (1, 2,0)).flatten()] - # else: - # ln = len(slots[0][0][0][0]) - # result = [joined.reshape(-1, ln)] - else: - joined = np.concatenate(slots, axis=0) - if type(slots[0][0][0][0]) in [int, float]: - result = [joined.flatten()] - else: - ln = len(slots[0][0][0][0]) - result = [joined.reshape(-1, ln)] - # result = [np.concatenate([sl for s in slots for l in s for sl in l], axis=0)] - else: - result = python_join(slots, level, mix, False) - return result + return np_general_wrapper(slots, level, 3, np_multi_object_level_3_mix) + return np_general_wrapper(slots, level, 3, np_multi_object_level_3) + + return python_join(slots, level, mix, False) class ListJoinNode(bpy.types.Node, SverchCustomTreeNode): ''' ListJoin node ''' @@ -188,7 +138,8 @@ class ListJoinNode(bpy.types.Node, SverchCustomTreeNode): min_axis = 2 else: min_axis = 1 - result = numpy_join(slots, self.JoinLevel, self.mix_check, min_axis) + depth = levels_of_list_or_np(slots[0]) + result = numpy_join(slots, self.JoinLevel, self.mix_check, min_axis, depth) else: result = python_join(slots, self.JoinLevel, self.mix_check, self.wrap_check) -- GitLab From 4970172a29a88e46e49970cc953c3f80b31f7b05 Mon Sep 17 00:00:00 2001 From: Victor Doval <10011941+vicdoval@users.noreply.github.com> Date: Thu, 20 Feb 2020 18:14:48 +0100 Subject: [PATCH 7/7] little renaming --- nodes/list_main/join.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/nodes/list_main/join.py b/nodes/list_main/join.py index 233a4fa3b..8ac344b34 100644 --- a/nodes/list_main/join.py +++ b/nodes/list_main/join.py @@ -34,7 +34,7 @@ def python_join(slots, level, mix, wrap): result = list_result.copy() return result -def np_object_level_2(slots): +def np_object_level_2_join(slots): return [np.concatenate([l for s in slots for l in s], axis=0)] def np_object_level_2_mix(slots): @@ -45,23 +45,23 @@ def np_general_wrapper(slots, level, end_level, func): return func(slots) return [np_general_wrapper(slots, level-1, end_level, func)] -def np_multi_object_level_3(slots): +def np_multi_object_level_3_join(slots): return [[np.concatenate([l0 for s in slots for l in s for l0 in l])]] def np_multi_object_level_3_mix(slots): return [[np.concatenate([l0 for s in zip(*slots) for l in zip(*s) for l0 in zip(*l)])]] -def numpy_join(slots, level, mix, min_axis, depth): - true_depth = depth - min_axis +def numpy_join(slots, level, mix, true_depth): + if true_depth == 1 and level > 1: if mix: return np_general_wrapper(slots, level, 2, np_object_level_2_mix) - return np_general_wrapper(slots, level, 2, np_object_level_2) + return np_general_wrapper(slots, level, 2, np_object_level_2_join) if true_depth == 2 and level > 2: if mix: return np_general_wrapper(slots, level, 3, np_multi_object_level_3_mix) - return np_general_wrapper(slots, level, 3, np_multi_object_level_3) + return np_general_wrapper(slots, level, 3, np_multi_object_level_3_join) return python_join(slots, level, mix, False) @@ -139,7 +139,8 @@ class ListJoinNode(bpy.types.Node, SverchCustomTreeNode): else: min_axis = 1 depth = levels_of_list_or_np(slots[0]) - result = numpy_join(slots, self.JoinLevel, self.mix_check, min_axis, depth) + true_depth = depth - min_axis + result = numpy_join(slots, self.JoinLevel, self.mix_check, true_depth) else: result = python_join(slots, self.JoinLevel, self.mix_check, self.wrap_check) -- GitLab