I'm very new to Nodebox and I've ran into some issues.
I have a .csv with a list of words that I want to display as a paragraph. I'm not sure how to do this. I've tried using a stack but I don't know how to get the line of words to break.
Also, I have another list of frequencies for each word. Would it be possible to multiply the frequency of each word by this value?
- paragraph.PNG 43.2 KB
- list.PNG 6.46 KB
|?||Show this help|
|ESC||Blurs the current field|
|r||Focus the comment reply box|
|^ + ↩||Submit the comment|
You can use
Command ⌘ instead of
Control ^ on Mac
Support Staff 1 Posted by john on 13 Apr, 2018 02:19 AM
Sorry for the delay in responding. Sometimes my pesky day job gets in the way.
You have stumbled onto a NodeBox quirk. What you want to do is straightforward and should be extremely easy - but it's not.
If you could concatenate all your words into a single string (or one string per paragraph) this would be effortless. When you feed that string into a textpath node all you have to do is set the width value (to anything other than the default of 0) and NodeBox will do the word breaks for you.
You can easily turn one string into a list of words (just use the make_string node and use a space as the separator), but strangely there is no way to do the reverse. There is a concatenate node, but it can only concatenate up to seven specific strings at a time. There is no "concatenate this list" node.
It would be fairly easy to write a custom node to do that in Python. So that's one workaround.
A stranger workaround is a to create a subnetwork that does a kind of cell division: combines each string into a pair of strings separated by a space. Each time you apply this "meiosis" the size of the list would be cut in half. String enough of these together (n where 2^n > than number of words in original list) and you would then have a single string which you could feed into the textpath node for an instant paragraph.
The catch with this approach is that you have to wire together the meiosis nodes by hand with enough nodes to match a specific number of words. Oddly, you can't just do this n times in NodeBox because NodeBox is stateless and has no ability to do recursion.
A more complicated method is to work with the words after each one has already been turned into a separate text path. You can find the width of each shape, compute a running total of these word shape widths, calculate a crude estimate of the break points, slice up the word shapes into subsets, and stack each set together to form lines. I say "crude" because you have to do all the lines at once; the second line cannot adjust based on exactly where the first line broke (that would, again, require recursion). The result is a somewhat ragged paragraph, but it may be good enough for your purposes.
I have attached an example network that shows all three methods. I first create a string of the first sentence of the Gettysburg address. If you feed that directly into a text path node and set the width to, say, 280 you will get a nice paragraph in a single bound. I show the result in blue.
To demonstrate the other two methods I break that sentence into a list of individual words; this is your situation. First I feed that list into a set of five meiosis subnetworks to turn them back into a single line of text. The result of that is shown in red.
The third approach, using shape widths as described above, will work for any arbitrarily long list of words. You can just feed in a word lookup from any CSV file. The result, a tad ragged but not too bad, is shown in black. You can fiddle with the "paraWidth" number to adjust the paragraph width.
Sorry for such a long note. As I said, this should be simple, but it's not. But don't let this discourage you from using NodeBox. This is a corner case; for most projects NodeBox works just fine.
Good luck and please keep playing and asking questions.
2 Posted by lobstor on 13 Apr, 2018 01:49 PM
Thank you very much John, this is very helpful.
Support Staff 3 Posted by john on 14 Apr, 2018 12:40 AM
You are most welcome, Lobstor.
But I was so focused on your first question, I forgot about your second:
"I have another list of frequencies for each word. Would it be possible to multiply the frequency of each word by this value?"
Yes, this is easy, but just a tad tricky.
For the multiplying part you just use the repeat node. This take a list of one or more items and repeats them a given amount of times. If you put 3 as the amount, it will either repeat the entire list three times or repeat each item in the list 3 times.
If you do a lookup on your Word column and feed that into the list port, and feed your Frequency column lookup into amount port, and set the checkbox to "Per Item", you might expect to get the result you want. Almost but not quite.
If your first three frequencies are 15, 7, and 1 it will repeat ALL of your words 15 times (15 alphas, 15 betas, 15 gammas, etc.), then all the words 7 times, then all the words once, and so forth. Quite a long list and not what you want. How do you get the repeat node to repeat the first word 15 times, the second word 7 times, the third word once, etc.?
To do this you have to wrap the repeat node inside its own subnetwork. Most NodeBox newbies assume subnetworks are for grouping clumps of nodes the way you group files into folders. But actually the main purpose of subnetworks is to coordinate the way input streams relate to each other.
In this case we want the repeat node to take the words one at a time and the frequencies one at a time. But that's not the way the repeat node works; it takes the entire word list in a single gulp then applies the frequencies one at a time.
So to fix this, just control-click your repeat node and select "Group into Network". Name it anything you want. You will then have a network node with two input ports: list and amount. With your network node still selected, click the Metadata button just above the parameter pane. You will see a dialog with ports listed on the left. Select "list". On the right half of the dialog, under Range, change "list" to "value" and click OK.
That's it. Subnetworks are confusing at first but they are very powerful. In case you have any trouble I am attaching a simple example. I used the make_strings node and the make_numbers node to recreate the first ten items of your CSV shown in your screenshot. All you have to do is replace those two nodes with lookup nodes attached to your CSV node.
4 Posted by lobstor on 15 Apr, 2018 10:36 AM
Thanks again John, I really appreciate the help :)