Jump to content
Ultimaker Community of 3D Printing Experts
Kin

Looking for help w/ PostProcessingPlugin JSON formatting - how to include if statements based on first value

Recommended Posts

Hello!

(1) I have been having some fun with the postprocessingplugin. It's really great! My biggest challenge has been that it is *hard* to troubleshoot the scripts, because the actual file is only run by cura, and so when the script completely fails, I only see that it won't load in Cura. And for some reason Cura takes ~25 seconds to open every time I open it, so that testing has quite some cycle time. I may be approaching it in a clunky way, I'm not sure (inexperienced here.)

(2) Specifically, right now I am trying to work out how to include if statements in the JSON header, to try and make it such that B,C,D parameters are input with default values depending on an option selected in enum parameter A. It appears something like this happens within CURA's regular JSON files. For example,

 

"infill_line_distance":                       {                           "label": "Infill Line Distance",                           "description": "Distance between the printed infill lines. This setting is calculated by the infill density and the infill line width.",                           "unit": "mm",                           "type": "float",                           "default_value": 2,                           "minimum_value": "0",                           "minimum_value_warning": "infill_line_width",                           "value": "0 if infill_sparse_density == 0 else (infill_line_width * 100) / infill_sparse_density * (2 if infill_pattern == 'grid' else (3 if infill_pattern == 'triangles' or infill_pattern == 'cubic' else (4 if infill_pattern == 'tetrahedral' else 1)))",                           "settable_per_mesh": true                       }

 

So my code may look something like this:

 

"settings":           {               "machine_type":               {                   "label": "Machine Type",                   "description": "Select which machine type you are using. CRITICAL!",                   "type": "enum",                   "options": {                       "A":"A Type",                       "B":"B Type",                       "C":"C Type",                       "D":"D Type",                       "E":"E Type"                   },                   "default_value": "B"               },               "input_paramA":               {                   "label": "Second JSON",                   "description": "Beep bop boop",                   "unit": "mm",                   "type": "float",                   "default_value": 3,                   "value": "9999"                 },                   "default_value": 5 if machine_type == \"A\" else 3 if machine_type == \"B\" else 9               }

 

This specific version of the input_paramA is not working, but I have tried quite a few others (including comparing the machine_type without the \"\" modification.) Sometimes I can get the parameter to show up as a gcode modifying script, but never have I gotten the if statements to work. It seems at best the if statement doesn't know what machine_type means, or maybe I also have the application of if statements in the header incorrect.

I am trying to setup my input parameters based on a different method than the tweakAtZ script, because my reading of the tweakAtZ script is that a different input box is put up depending on which of a first selection box is chosen. In this you use the "enabled" modification. This works OK when you have 2 settings that depend on one of 2 choices (like at mm vs at layer.) But it doesn't scale well when you have 10 machine_types and 5 input parameters. It seems like there might be a better method for my application.

But, I am totally at a loss at this point. Any tips, help, or direction is appreciated! I'm still quite a python beginner.

Share this post


Link to post
Share on other sites

A few things that i notice with your json;

 

  • default_value can never have a python function, use value instead.
  • Things that need to be evaluated by python (such as; 5 if machine_type == \"A\" else 3 if machine_type == \"B\" else 9) need to be enclosed by ""
  • default_value must be a part of a setting.

 

So if you take that into account, the json would be someting like

"input_paramA":

{

"label": "Second JSON",

"description": "Beep bop boop",

"unit": "mm",

"type": "float",

"default_value": 5,

"value": "5 if machine_type == \"A\" else 3 if machine_type == \"B\" else 9"

}

Share this post


Link to post
Share on other sites

Hi Nallath! I really appreciate the answer and help. I think you've got me further, and I see now the mistakes you pointed out. One thing I was not totally certain was what you meant by "default_value must be a part of a setting." I am not sure if you are saying "default_value must be used, even if you have a "value"" or something else.

I paired down my normal script into just the JSON header, for debugging purposes. I have added your line

"value": "6 if machine_type == \"A\" else 3 if machine_type == \"B\" else 9"

to a previously working JSON header (for e.g, with just

9

instead) Unfortunately when I add the python statement line, the script no longer will load.

Is there something obvious that I am doing wrong? I have really been butting my head on this quite a bit.

I've copied the code below, and also attached to a public dropbox file here:

https://dl.dropboxusercontent.com/u/3619097/Robust_Wipe.py

 

from ..Script import Scriptimport reclass Robust_Wipe(Script):   version = "2.1"   def __init__(self):       super().__init__()   def getSettingDataString(self):       return """{           "name":"Robust Wipe """ + self.version + """",           "key":"Robust_Wipe",           "metadata": {},           "version": 2,           "settings":           {               "machine_type":               {                   "label": "Machine Type",                   "description": "Select which machine type you are using. CRITICAL!",                   "type": "enum",                   "options": {                       "A":"A Type",                       "B":"B Type",                       "C":"C Type",                       "D":"D Type",                       "E":"E Type"                   },                   "default_value": "A"               },               "input_paramA":               {                   "label": "Input",                   "description": "First Input Parameter",                   "unit": "mm",                   "type": "float",                   "default_value": 5,                   "value": "6 if machine_type == \"A\" else 3 if machine_type == \"B\" else 9"               }           }       }"""   def execute(self, data):       if 1==1:           pass           #I want the most basic version of the script for figuring out JSON       return data

 

Share this post


Link to post
Share on other sites

 One thing I was not totally certain was what you meant by "default_value must be a part of a setting.

 

It means that this;

"bla": {"default_value":10} is allowed.

"bla": {}, "default_value": 10 is not allowed.

 

Unfortunately when I add the python statement line, the script no longer will load.

 

I don't see anything obviously wrong, but why don't you try to keep it as simple as possible first? Try something like "6 if machine_type == 'A'" and see what happens. If that works, increase the complexity.

Share this post


Link to post
Share on other sites

Hi Nallath! Thanks!

Wow, I did not realize that in the first code I wrote I had "default_value" outside of the setting. :O. That was a huge mistake. I hope it wasn't in all of the versions I had tried, or else I wasn't ever going to get anywhere.

I think you are right of course about trying to keep it simple. I went back to testing just

 

default_value:6

 

and then

value:"6 if machine_type == \"A\"" but not luck

I do wish I had a better sense of the error, since it feels extremely hard to debug otherwise. Difficult for an amateur, I guess, maybe feasible for someone more versed with this kind of scripting & JSONs.  (Also, given that Cura takes 30 seconds to load on my SSD laptop [not on all the computers I've used though] it takes extra long to test all the changes.)

Edited by Guest

Share this post


Link to post
Share on other sites

Interestingly, I got somewhere with

 

                   "value": "6 if machine_type == A"

 

But it is kind of faulty.  That is, at least the script loads, but the box is red and unhappy. It does let you enter numbers though, but it doesn't preload 6.

Edited by Guest

Share this post


Link to post
Share on other sites

Never made it further with this. Unfortunately I think I'm stuck hard coding things into the script and then adding override settings.     I wish I understood JSON a little better or had a better sense of how to debug the scripts given the issue of no error reporting. It's been a bit of a frustrating struggle. Overall still cool to have the postprocessing plugin so not to air my frustrations as an overall negative review. It's great :D.

Edited by Guest

Share this post


Link to post
Share on other sites

Interestingly, I got somewhere with

 

                   "value": "6 if machine_type == A"

 

But it is kind of faulty.  That is, at least the script loads, but the box is red and unhappy. It does let you enter numbers though, but it doesn't preload 6.

 

Hi. I've been lurking and following this thread. From what I'm understanding, shouldn't this be:

 

"value": "6 if machine_type == \"A\""

 

I also sent you a PM (just saw yours - sorry). Maybe I can help...

Share this post


Link to post
Share on other sites

Hi. I've been lurking and following this thread. From what I'm understanding, shouldn't this be:

 

"value": "6 if machine_type == \"A\""

 

 

Hi DaHai!

I agree, I think per my fledgling understanding so far, the double quotes would be necessary. However, when I add them, the script that partially works doesn't load, even if that is the only change. I have the script attached and I just reran the tests. I'm sending the double quote version, which you will see can't load, and then if you take out the \"\" then it loads, but doesn't process the if statement looking for the "A". https://dl.dropboxusercontent.com/u/3619097/Robust_Wipe.py

I don't really know what fails when I add the quotes, just that it fails.

Right now although I would love to understand what I'm doing wrong, I admit I think I'm moving towards adding a third type "custom" and just looking at a set of always-on values only if custom is selected. Unfortunately this means the built-in values aren't displayed per type, which was really my ideal and a more robust script. At least, I'm glad to now have a slightly better sense of how the JSON is formatted and works, but I have been really stuck getting it right.

Share this post


Link to post
Share on other sites

Alrighty, here we go:

 

"value": "6 if machine_type == 'A' else (3 if machine_type == 'B' else 9)"

 

Now, following this pattern, I believe additional logic would be nested like so:

 

"value": "6 if machine_type == 'A' else (3 if machine_type == 'B' else (4 if machine_type == 'C' else 9))"

 

And that does work in testing with Cura 2.3.0...

So, with each additional 'if' logic, you'd need another level of nested parens

P.S. Forgot to mention: It appears every IF must have an ELSE. The Default value does not take effect if the IF fails.

Edited by Guest
  • Like 1

Share this post


Link to post
Share on other sites

Update: So this totally went wayside during the holiday madness :O. I am glad to have finally sat down on it. Dahai8 you uncovered the secret. I've include below the example code you gave extended to a more complicated number of parameters.

I still have had a bear with opening cura to test edits to the script, but mostly it's just me not being a cautious practiced programmer and missing punctuation. I probably rely too much on (for example) the compiler in arduino to point out such issues. I don't get so lucky with the gcode modifier script because I never see how it fails in cura (just that it doesnt load, which no longer is an issue.)

Thanks again for all the help! Very happy to have done this as neatly as extensively as I hoped would be possible. Only due to the json hacking help of others.

 

from ..Script import Scriptimport reclass Robust_Wipe(Script):   version = "2.1"   def __init__(self):       super().__init__()   def getSettingDataString(self):       return """{           "name":"Robust Wipe """ + self.version + """",           "key":"Robust_Wipe",           "metadata": {},           "version": 2,           "settings":           {               "machine_type":               {                   "label": "Machine Type",                   "description": "Select which machine type you are using. CRITICAL!",                   "type": "enum",                   "options": {                       "A":"A Type",                       "B":"B Type",                       "C":"C Type",                       "D":"D Type",                       "E":"E Type"                   },                   "default_value": "A"               },               "wipe_layer":               {                   "label": "Wipe Frequency",                   "description": "Wipe every N layers",                   "unit": "Layers",                   "type": "int",                   "default_value": 1               },               "wipe_volume":               {                   "label": "Wipe Volume",                   "description": "Wipe every N layers and volume - not implemented",                   "unit": "mm",                   "type": "float",                   "default_value": 0               },               "input_paramA":               {                   "label": "Input A",                   "description": "First Input Parameter",                   "unit": "mm",                   "type": "float",                   "default_value": 99,                   "value": "1 if machine_type == 'A' else (2 if machine_type == 'B' else (3 if machine_type == 'C' else (4 if machine_type == 'D' else (5 if machine_type=='E' else 9))))"               },               "input_paramB":               {                   "label": "Input B",                   "description": "Second Input Parameter",                   "unit": "mm",                   "type": "float",                   "default_value": 99,                   "value": "1 if machine_type == 'A' else (2 if machine_type == 'B' else (3 if machine_type == 'C' else (4 if machine_type == 'D' else (5 if machine_type=='E' else 9))))"               },               "input_paramC":               {                   "label": "Input C",                   "description": "Third Input Parameter",                   "unit": "mm",                   "type": "float",                   "default_value": 99,                   "value": "1 if machine_type == 'A' else (2 if machine_type == 'B' else (3 if machine_type == 'C' else (4 if machine_type == 'D' else (5 if machine_type=='E' else 9))))"               },               "input_paramD":               {                   "label": "Input D",                   "description": "Fourth Input Parameter",                   "unit": "mm",                   "type": "float",                   "default_value": 99,                   "value": "1 if machine_type == 'A' else (2 if machine_type == 'B' else (3 if machine_type == 'C' else (4 if machine_type == 'D' else (5 if machine_type=='E' else 9))))"               },               "input_paramE":               {                   "label": "Input E",                   "description": "Fifth Input Parameter",                   "unit": "mm",                   "type": "float",                   "default_value": 99,                   "value": "1 if machine_type == 'A' else (2 if machine_type == 'B' else (3 if machine_type == 'C' else (4 if machine_type == 'D' else (5 if machine_type=='E' else 9))))"               },               "input_paramF":               {                   "label": "Input F",                   "description": "Sixth Input Parameter",                   "unit": "mm",                   "type": "float",                   "default_value": 99,                   "value": "1 if machine_type == 'A' else (2 if machine_type == 'B' else (3 if machine_type == 'C' else (4 if machine_type == 'D' else (5 if machine_type=='E' else 9))))"               },               "input_paramG":               {                   "label": "Input G",                   "description": "Seventh Input Parameter",                   "unit": "mm",                   "type": "float",                   "default_value": 99,                   "value": "1 if machine_type == 'A' else (2 if machine_type == 'B' else (3 if machine_type == 'C' else (4 if machine_type == 'D' else (5 if machine_type=='E' else 9))))"               },                "input_paramH":               {                   "label": "Input H",                   "description": "First Input Parameter",                   "unit": "mm",                   "type": "float",                   "default_value": 99,                   "value": "1 if machine_type == 'A' else (2 if machine_type == 'B' else (3 if machine_type == 'C' else (4 if machine_type == 'D' else (5 if machine_type=='E' else 9))))"               }           }       }"""   def execute(self, data):       if 1==1:           pass           #I want the most basic version of the script for figuring out JSON       return data

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Our picks

    • Taking Advantage of DfAM
      This is a statement that’s often made about AM/3DP. I'll focus on the way DfAM can take advantage of some of the unique capabilities that AM and 3DP have to offer. I personally think that the use of AM/3DP for light-weighting is one of it’s most exciting possibilities and one that could play a key part in the sustainability of design and manufacturing in the future.
        • Like
      • 3 replies
×

Important Information

Welcome to the Ultimaker Community of 3D printing experts. Visit the following links to read more about our Terms of Use or our Privacy Policy. Thank you!