zanoni-mbdyn / blendyn

MBDyn (https://www.mbdyn.org/) graphical post-processor for blender (https://www.blender.org/)
GNU General Public License v2.0
40 stars 8 forks source link

allowing more liberal labels #39

Closed louisgag closed 3 years ago

louisgag commented 4 years ago

https://github.com/zanoni-mbdyn/blendyn/blob/231cce63742113e6cb19c092a4a2b17ae6ac0976/baselib.py#L493

The ability to load labels from MBDyn is, in my opinion, extremely useful, as it allows to stop worrying about which number goes with which node and in a case where someone is using a preprocessor, to actually not even see these numbers anymore.

That said, I find it somewhat restrictive. For example, I use my own (integer) variable naming convention which is incompatible with what is allowed by Blendyn. I also often use the same numerical value for different objects (ie: a node, a joint, and a reference frame) and this is currently disallowed by the code. I am conscious that there is a bit of risk in doing what I am proposing here, but it could perhaps be associated with a "extreme" checkbox next to the load labels button? So the code below does load any integer from the log file and will assign it to any beam, node, ref frame, or joint that has the matching number. Note that if both a beam and a node have the same label as a result of this method, it is guaranteed to be wanted by the user. PS: I've also changed type and dict to some more generic terms, to avoid confusion...

def assign_labels_extreme(context):
    """ Function that parses the (optional) labels file and assigns \
        the string labels it can find to the respective MBDyn objects """

    mbs = context.scene.mbdyn
    nd = mbs.nodes
    ed = mbs.elems
    rd = mbs.references
    objList = [nd,ed,rd]

    labels_changed = False

    log_file = os.path.join(os.path.dirname(mbs.file_path), \
            mbs.file_basename + '.log')

    set_strings_any = ["  const integer", \
                        "  integer"]

    def assign_label(line, set_string, theObj):
        line_str = line.rstrip()
        eq_idx = line_str.find('=') + 1
        label_int = int(line_str[eq_idx:].strip())
        label_str = line_str[len(set_string):(eq_idx -1)].strip()
        print ("set_string:" + set_string)
        print ("line_str:" + line_str)
        print ("label_str:" + label_str)
        for item in theObj:
            if item.int_label == label_int:
                if item.string_label != label_str:
                    item.string_label = label_str
                    return True
                break
        return False

    try:
        with open(log_file) as lf:
            for line in lf:
                found = False
                for set_string in set_strings_any:
                    if set_string in line:
                        for theObj in objList:
                            labels_changed += (assign_label(line, set_string, theObj))
                        found = True
                        break
    except IOError:
        print("Blendyn::assign_labels_extreme(): can't read from file {}, \
                sticking with default labeling...".format(log_file))
        return {'FILE_NOT_FOUND'}

    if labels_changed:
        return {'LABELS_UPDATED'}
    else:
        return {'NOTHING_DONE'}
# -----------------------------------------------------------
# end of assign_labels_extreme() function
zanoni-mbdyn commented 4 years ago

Louis, I think allowing more freedom in assigning labels is definitely a good idea.

I assume that you mean that you use the same literal value for multiple objects having different integer labels, correct me if I'm wrong. The opposite is actually allowed in Blendyn, currently.

One thing that we could do to ease the risk that you pointed out is to keep track of the integer labels of the objects we already assign a literal label to, and skip them when we are assigning a new label. That could prevent the clashes you mention.

Do you agree?

louisgag commented 4 years ago

Andrea, yes, I got my train of thought mixed up. What I mean is that the current implementation skips the other types of items once a match is found for a label. Your solution sounds good, the user should in that case only be advised to define all labels before any other integer with the same value.

zanoni-mbdyn commented 4 years ago

We could also maintain the current setup, in which we ask users to put all the labels into a single .lab file. I don't think it is a great limitation, and this way it is not necessary to declare them all before anything else, just to keep them in a separate file.

louisgag commented 4 years ago

I would still prefer to use "extreme" function I pasted above because MBDyn's Python preprocessor does not actually create such a .lab file, it would not work for any input file which was not specifically made for Blendyn (and this is the beauty of Blendyn), and it would render impractical for the user to define the label right next to the object it refers to in the input file. Perhaps the .lab file could also be an option, so the user could choose between "extreme" (there is surely a better term for this), "traditional", and ".lab file"?

zanoni-mbdyn commented 4 years ago

That can be a way, yes... But I still think it is a bit too extreme :)

Think about the classic rotor model: one of the first const int you're going to define is the number of blades... And that already screws the labeling system you propose!

Maybe it would be just easier to add an option to the Python Preprocessor to write all the labels to a separate file?

louisgag commented 4 years ago

It does work for me because I have no labels below 100, but yes, it is somewhat extreme...

Maybe it would be just easier to add an option to the Python Preprocessor to write all the labels to a separate file?

that would be a good compromise indeed ;-)

zanoni-mbdyn commented 4 years ago

@louisgag do you think we can close this issue, at least for now?

louisgag commented 4 years ago

Yes, but can we make the code I proposed at least as an optional behavior?

zanoni-mbdyn commented 4 years ago

Yeah, I think so. I'll do it ASAP.

zanoni-mbdyn commented 4 years ago

@louisgag, please take a look at the free_labels branch. If you can test and report, I'll be glad to document and merge it if everything looks ok ;)

louisgag commented 4 years ago

thanks for the update. I wanted to test but somehow both free_labels and master branches bring up an error with my current Blender (2.82) when I try to load them:

Read prefs: /home/louis/.config/blender/2.82/config/userpref.blend
Warning: property 'release_confirm' not found in keymap item 'OperatorProperties'
addon_utils.disable: blendyn-master not disabled
Modules Installed (blendyn-master) from '/home/louis/Desktop/blendyn-master.zip' into '/home/louis/.config/blender/2.82/scripts/addons'
WARN (rna.define): /build/blender-RL3axj/blender-2.82.a+dfsg/source/blender/makesrna/intern/rna_define.c:1647 RNA_def_property_ui_text: 'Collector of rotational offsets of element attach R.Fs.' description from 'rotoffsets' '' ends with a '.' !
WARN (rna.define): /build/blender-RL3axj/blender-2.82.a+dfsg/source/blender/makesrna/intern/rna_define.c:1239 RNA_def_struct_ui_text: 'Download and installs the required dependencies to enable additional Blendyn features. Internet connection is required.' description from 'BLENDYN_OT_install_dependencies' '' ends with a '.' !
WARN (rna.define): /build/blender-RL3axj/blender-2.82.a+dfsg/source/blender/makesrna/intern/rna_define.c:1239 RNA_def_struct_ui_text: ' Plots the selected variable in the image editor
        and optionally save it as .svg in the 'plots' directory.
        The user can choose among all the variables of all the
        MBDyn entitites found in the output NetCDF fila.' description from 'BLENDYN_OT_plot_var_scene' '' ends with a '.' !
blender(BLI_system_backtrace+0x37) [0x564ca1ae7897]
blender(BLI_ghash_insert+0xe2) [0x564ca1a867e2]
blender(+0x18ef87b) [0x564c9f8f687b]
blender(+0x1913a0f) [0x564c9f91aa0f]
/usr/lib/x86_64-linux-gnu/libpython3.8.so.1.0(+0x258be2) [0x7f98ab074be2]
/usr/lib/x86_64-linux-gnu/libpython3.8.so.1.0(+0x72ffd) [0x7f98aae8effd]
/usr/lib/x86_64-linux-gnu/libpython3.8.so.1.0(_PyEval_EvalFrameDefault+0x3c6b) [0x7f98aae9306b]
/usr/lib/x86_64-linux-gnu/libpython3.8.so.1.0(_PyEval_EvalCodeWithName+0x8fb) [0x7f98aafe188b]
/usr/lib/x86_64-linux-gnu/libpython3.8.so.1.0(_PyFunction_Vectorcall+0x90) [0x7f98ab0bccd0]
/usr/lib/x86_64-linux-gnu/libpython3.8.so.1.0(+0x72ffd) [0x7f98aae8effd]
/usr/lib/x86_64-linux-gnu/libpython3.8.so.1.0(_PyEval_EvalFrameDefault+0x8067) [0x7f98aae97467]
/usr/lib/x86_64-linux-gnu/libpython3.8.so.1.0(_PyEval_EvalCodeWithName+0x8fb) [0x7f98aafe188b]
/usr/lib/x86_64-linux-gnu/libpython3.8.so.1.0(_PyFunction_Vectorcall+0x90) [0x7f98ab0bccd0]
/usr/lib/x86_64-linux-gnu/libpython3.8.so.1.0(+0x72ffd) [0x7f98aae8effd]
/usr/lib/x86_64-linux-gnu/libpython3.8.so.1.0(_PyEval_EvalFrameDefault+0x4ea2) [0x7f98aae942a2]
/usr/lib/x86_64-linux-gnu/libpython3.8.so.1.0(_PyEval_EvalCodeWithName+0x8fb) [0x7f98aafe188b]
/usr/lib/x86_64-linux-gnu/libpython3.8.so.1.0(_PyFunction_Vectorcall+0x90) [0x7f98ab0bccd0]
/usr/lib/x86_64-linux-gnu/libpython3.8.so.1.0(PyVectorcall_Call+0x5c) [0x7f98ab0bd3cc]
blender(+0x19116bf) [0x564c9f9186bf]
blender(+0x18ed199) [0x564c9f8f4199]
blender(+0x15d1a78) [0x564c9f5d8a78]
blender(+0x15d20fb) [0x564c9f5d90fb]
blender(WM_operator_name_call_ptr+0x4a) [0x564c9f5d95ca]
blender(+0x1b954b6) [0x564c9fb9c4b6]
blender(+0x1ba672d) [0x564c9fbad72d]
blender(+0x15d549f) [0x564c9f5dc49f]
blender(+0x15d73ec) [0x564c9f5de3ec]
blender(wm_event_do_handlers+0x50d) [0x564c9f5dec6d]
blender(WM_main+0x20) [0x564c9f5d4160]
blender(main+0x2b6) [0x564c9f3a73d6]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf3) [0x7f98a8be80b3]
blender(_start+0x2e) [0x564c9f3f58ae]
BLI_assert failed: /build/blender-RL3axj/blender-2.82.a+dfsg/source/blender/blenlib/intern/BLI_ghash.c:464, ghash_insert_ex(), at '(gh->flag & GHASH_FLAG_ALLOW_DUPES) || (BLI_ghash_haskey(gh, key) == 0)'
Aborted (core dumped)
zanoni-mbdyn commented 4 years ago

Sorry Louis, I missed your last post completely!

That's weird. I don't really have a clue, it seems like something that is specific to the Blender version that you are running. Can you try with another one? It should be easy to use also the bundled pre-compiled ones now, since there I've added a panel to manage and automatically install the additional Python modules, in the addon configuration window.

louisgag commented 4 years ago

Hi Andrea,

No problem about the delay, I forgot about it as well as I've been recently doing more FreeCAD than Blender. Somehow it seems that Ubuntu 20.04's Blender does not like Blendyn :disappointed:

I tried with 2.83. The panel to install the python packages is quite nice! There is only one issue with it: psutils requires the python development headers, which are not shipped with Blender's bundled Python. I had to follow this procedure to get them before installing psutil from the addons menu. I'm not sure if you can do this directly from Blender :confused:

Concerning the main point, free_labels, I've tested it (again 2.83) and it's exactly what I was hoping for. Thank you Andrea.

zanoni-mbdyn commented 4 years ago

Thank you for pointing out to me about psutil needing the Python headers, I did not know that! I will put a disclaimer on the panel, for the time being, and then evaluate the situation. Installing the Python headers automatically, especially in a cross-distro and cross-platform way, can be tricky I fear...

Good that free_labels is okay, I'm merging it! Thanks for testing it