Fluid.jit.plotter, for a better performance than fluid.plotter

I have been working with an increasingly large dataset that I want to “knearest-scrub” around with fluid.plotter. Initially I thought that north of 10k samples in a dataset the fluid.kdtree~ performance degrades so much that, especially beyond 35-40k samples, it drags to a near halt.

I was reading this thread (though still haven’t finished reading all of it) and was thinking how I could speed up kdtree, and came up with an idea (that I’ll share in more detail in another coming post): scanning the dataset space with a kernel size and a stride and fitting a kdtree to each such kernel. As fun as it was to implement this in Max :upside_down_face:, at the end I realized that the culprit was not actually fluid.kdtree~ but rather fluid.plotter. I guess this is because jsui always uses the cpu-bound mgraphics backend, and therefore does not scale well.

So I made a similar thing in jit.gl.land and named it fluid.jit.plotter (but still open for suggestions). It does not do nearly as much as fluid.plotter as of now, it makes the scatterplot (with fixed point size and color atm), and highlights in red. This is all I needed for now, but I can see implementing a total fluid.plotter replacement if the community is interested.

I made an example patch to show that the responsiveness of fluid.jit.plotter does not really depend on the number of points in the dataset. In the test patch there are 100k points, but I have tested with 1M too, but it’s harder to capture that since the fluid.plotter starts to break the whole patch down. :stuck_out_tongue_winking_eye:

I wanted to avoid using other dependencies from my home-cooked things, so now you have to make it into a bpatcher and manually resize it to 300x300 (which is for now the hardcoded size of the thing). But if this would become part of a package then one can always use the clippings folder with a saved bpatcher instance (BEAP-style), or I can also recommend bl.autobp that can do the same.

Let me know what you think, or if you have suggestions for it, and happy patching! :slight_smile:

fluid.jit.plotter.maxpat (19.9 KB)
fluid_plotter_vs_jit_plotter.maxpat (12.1 KB)

fluidjitplotter_vs_fluidplotter

3 Likes

That’s definitely loooads faster!

Having some parity would be nice as I think I use the color/size things in places in my patches (sp.plotter mainly). I do miss that crazy 5d one we were building a couple years ago, but thankfully there’s a native way to do all that now, even if a bit slow for large datasets.

2 Likes

I don’t see why we shouldn’t include this in the next release at some point, even as a release on its own. I could help facilitate that @balintlaczko if you were open to it? I think as @rodrigo.constanzo pointed out some additional finessing to make it more in line with the existing non-GPU one would be all it needs.

2 Likes

when it is road ready, make a PR - ideally it would probably replace fluid.plotter if it has parity of feature and is faster, no?

I think that js and jitter differ enough in behaviour and learning materials, perhaps even just slightly cosmetically that having both is worth it.

As two separate abstractions?

I imagine that would make maintenance more cumbersome.

I don’t really use either (js / jitter) in the core of my practice so I have no horse in this race, but I’d think jitter is more “native” overall.

Assuming the drawing is exactly the same and has all of the same features (highlighting, zooming features) there is still the ergonomics of the resize and whether or not people want to have jitter in their patch. I think that the js version is longstanding enough at this point that a replacement poses risk in modifiying the behaviour of what is there, without serious testing, which as we know sucks in Max.

2 Likes

we could aspire to a deprecated status - slow replacement… let’s see how @balintlaczko and his team go forward with it, I’m excited!

I have a resizable version now:

2 Likes

FWIW @balintlaczko I am working on integrating this here if you wanted to contribute and collaborate:

2 Likes

Hey all, I am getting close to ready with this, it mostly mirrors the interface of fluid.plotter but there are a few differences.
First, individual setpoint, pointcolor and pointsize are not implemented:

I can look into this if there is a huge public backlash for not having them, but since the aim of this abstraction is to have a high-performant variant of fluid.plotter (that can take 1M points without much “scrubbing” lag), I decided not to have them.

More importantly, to populate the plot you need the refer message with a dataset name. This avoids some unnecessary copying that can be a big time-saver with large datasets. The right-side labelset inlet also listens to refer, although it understands dictionary too since (sadly) it’s anyway using dictionary dumping under the hood (unlike the dataset). I’m thinking of how to improve this in a future update, but it might be good to already get used to using refer.

Both in the case of the dataset (left inlet) and the labelset (right inlet) a refer without arguments clears the reference and the plot/colors.

The rest aims to have parity with fluid.plotter, so we have:

  • highlight that works with lists (and non-numeric IDs)
  • xrange, yrange, and range
  • shape (“circle” or “square”)
  • pointsize and highlightedpointsize (both are ints – this is actually not in parity, they are there instead of having one pointsizescale and a fixed size-ratio)
  • bgcolor
  • click’n’drag zooming and reporting zoomxrange and zoomyrange via the 2nd outlet
  • …and of course now it can be resized and it enforces (somewhat jankily) a square aspect ratio on the bpatcher

Here is a w-i-p test patch while there is no help patch yet:

<pre><code>
----------begin_max5_patcher----------
3762.3oc0cs0aiaiE94L+JDLFfcWfzr7No5Scwtu2W125VDHaSaqYjkbknyj
zh1e6qDIksbhjLiMEimYvXOhR1jmOdtQxy43+3S2MadwyxpYQ+XzuDc2c+wm
t6NcSMMbm856lsM44EYIU5Ga1VYUUxZ4r6M2SIeVoaGAp+Saq6JkUxbUhJsH
+wrzb4hh845mC09DIpEaRyW+Xobgxz+HD+Av8QHpn4MBReQ8qQ+p8yjueaZd
lTU08Kptwh8p1Vg1VSWpGTEy+xOHXsiJyyodYmzzgylE8qM24O+zmZd4dOf.
yFl7fB7CzCjGl5KxiDHxC7.KFvi.OvADwHzoPfd.USnbdbCIBQD8k9fTQgiT
E.LinIVF4X+1C4xISE4x4dlbykeq968MTaY8WuL52KJ19bYR9Zy+8E8+cL5l
hZXm4Pflr4mgeF2KUi6gpACS02a+mWmr2UlVqZZDBkwZHTHWz7F1Wpk3gRts
TtRVNB8whMpcI52vXOQeLQHounk62t8kGWjsuRIqmPWOBASo5ITKACwDOQw3
3ajYTJL1LU52YTD0yz278JUQ9XlLADyjC271gW6mRfNaHoi8qxjsxZVlGk4I
yyzzCXHpbdsJwIhRiAFmC3B+Rn7.SnCwxVIU6JFWOq0DByZPgv7kCRz.IVVk
96iYvDS0hiTjVdDC7kcjPo0AB.i6fKhq8H.IzjFI1WDHNLtA8aYoaiPiQfDn
lmjaHMi4CePfnPNCN67K.yNA5MOcfdl9TEqWmMlnFjPgcVJo2TmxhuH0oM58
tHBcQw1sxiJMOLQ9u2n8SeS55MY0+SIWFo0tF0nBJ5uuTtJYel5GiHf+Q6m0
0EgW6NjA5.5o+lEs1nsh89vNPmQ7hhrhRyWN3AJ.Fy.bAACw7l0I4VSvNce2
4iCp1WUjqz5eaFR0C4KQsv9syG0sJHRXrIA0FpnmQCd+HCpGpfcQbUMqDx+F
p6vSoYozbTeF5BrXrXCs7O3qeEDit9WONw2u8fcQ0SGpWbQMSr1vGQLNg6rZ
FJ6BH7tCSYokbsza8SmlIeRVVkV6E5wN8tYI610o4657QZ.ouXDbE2enozbS
SzCMUJeJs8yer0jxZvRUiT6K0ivYOyZWuayWSwRYY99T8PwzX8zkcHomXxqk
Cp1krv7gal+ZucmMZhXV+lUUuVnDy6.+0S7qyJV7U4xNBR0f5NYdZd2sn7ja
a0d93I.L5gdu+J6Hr2a1PC5g++pLMI6.ArtLcYQdyf3jYhlla6tZVKM0z75Q
hQ+D4I654CWy0TCKCbypZhbe07jxlIJqVET6MUEEYmdqCetL4Jk816RyyeEJ
pJ1M7MKazfL7smWTeysi8cquS0i6yM28wZdB0iUIOcJZqRxxrRum90+bRd51
DkTkZlBPfC2znYcS0hxhrrSnWycdpm6rrlGeg7aoKUazcTWlg5GOcWKSzrCy
xKSWKqTm1lJYc0osTodw.5cZZ+bqL7iJ41cY0TwoOPszQZkpZSw2prOXKiVW
.33l52UltqpvSZ+UpD0JsNHuNvRV09BebsLMudfY8MJ+.mdi2p.7MJA618C3
RUmmn0UotPk9aLeo74N5YrVGrpbtP34TimmZ13yvH3Q2rGzzgYwfPFyrlvW6
JwflMcG.g3QQPqaCdBQNwF5o.Rimm0hLNBHwZ.w5Cwn.BdP.AM.fPFGPN0ep
aFVEiG3SJmB76INEKdLkLJnuKYThmZ9D1sAaRYR9xhsMHhi5TLmYCGOAPBwA
qT2XnhU9YBAE72efR7TiInaFLwMsrwStR1O.crifJOIedWYzmWAi9mMrKNAO
Hl1w2XGfG36leQbanr8KEo4QXmPCjYMqL90vsLDbvuMfCUz7l+5BdHDNCGCy
cfG.NFWEqVx49W8dnfneaqTUV3rCKlcMiylB+Z4mGk7JpX5BmDVLJMbYkyCy
b.Fv76INkbQKL93lN0XsXfsRPSaM2uejopXe4hVr159Xzoz4RYkJM+vVv8KG
rLz7bNMu7dGCTWGC7IbPPbcPfmvAA10AwTNczXkyoQAlLkiBtiih1g6zLJZl
QPNLJHS8f.5xDxTOHbZ9XJGDNNFXS3X.5Li4TNc.cUekVNBMUiBmUXMkxGPz
6AKfS0n.5JVLkRHv2CTz+fv1X6g+Mq4DdV9n4zrdLQoJSmuWY7+n6oY9tN0k
0YEySxd0Qkz2gx7oiCN+bBxpMk6G63igB8ZCH.yRDhuj3InuiO12wM9YBCkd
C8DzkD5IPQaHz27lIZqtQC8jiaojOBAgyfvpMxnpMI6jQEqzWXBMinjplqd4
uUJiVVl7s7Gd2PNJN1tcwMjpY+LtQQ73XOB3CFCmZTdQZ4hwCvLDTu9MgdKO
3BOEwKTQXh3kwo9peaeR4nTOzr5UCWiQIlOn93.EuOmOPuLwMHzD.89KPu.2
PA5kyQ2kEKXBuxpyferA2UobmLeYz70FMVmOHuH.SZ.YhKRODkWLTXPfpu0P
TNPgXDWSgl8wkCdeoxUe763KleeUVQxwH7n1uP09xigp0CBpPfvTTLAB4Lp2
ix8whRZrAerQIM0W4wIkFtn.eTlg3NAwOxbgGnNXXBh+UY6SW9PVxbYVkT8W
umzBylmeHfNO+fw7KQNuGo.Ab7DZL.Z6LY34pTUsZukoKTNjbbFTH9hhk29.
AP3.ggX7qcoKo79Nvfg6XYhJ4BRePHRXxXKrmrHxEenVDMRNecqLIu5uh9o5
gqEMphHNfFLiTivWRMbV3XXFZ0W+2e9+7y+3+K+GhlKS18C5X0LpMlLiRyi1
800u2EbIh0tOPMwtLwrRWL9xVvU23PANyyFAcnRFXrQ3sJY.NTV.UxpQiqeq
EdhIHr8V9Ai3gN+Ys4MKl42zfBQBbVkdFm3OjyJmO28hAljTA.80lsgCUReq
2IHPD77JisI9M0WYfI02In3Wp1mNVxPaObbspRFo80woh4EkKM48BvUaLzKe
83cr+jlIOrqxFin6xJT0eWy7HmdxWiVEsZzTkGpW8FABzuQ7jWID7G6VRUuV
uQoZSNGiQvGhAHAFFa9iH9vhW7.FP9nw.lCy7SLFPCCFTuv+5whKS4Lsi2z2
xnupnbah9oYWkKnjqNuLCJrX4BrvBX5fEwsCrLtwxOCi9L5bXViid0nEFPYL
B.CQDiji21oSR7G6NcdVSGB9jX4fdiS1sEtKeS2werFKXitzsX7v1Kw9JwsQ
evGiEAbdt8IFAXerHv4pzGBSHGzKHPndBDfevf.vAg+9YCP9BAhuQbZpUrex
8YBg9NxmoVUAStKSn3aeWldwMelZvrgbYR3KSnXvGqlimcCKN3AwzBFvaDkH
sFMrhKuckk9RbAK9NRIxAKIGzsxmJbg.9NXkWGqFmMGr142QV6lUF6qMqDGp
po1pTkSzosRFZqZbBecZBPdfnyulKSJkUpw0EZmMEPT+oy0kNaRBZbCjVoPy
2uxgZ.noZOy4d5XDHCOaVOdZJ2q9uhO2Nw5vrpgNiunJBXOJxfnyc3td+bsW
pJkx+5n.6iMWqOl6bY55MyK1WVM5YqzBEsUjVlmBJPHcBvhgNQaCX7kT0gyn
Xj5BsQwLK1DNXF8yfq9jp4y7N8bdZABLGFlwGeaJ4d8zBalW2keJ.W+mlPhd
TMs1pT.zV9y7kgSW1zlk0NNTJ2kYK6YvK4PqaqPc1uxmRkeSW8wRyRUuzcrU
rZUkT0FL4flXE+HMZpqaKKSVerdc0NCsHKcwWUap0xsdS21eSo+5za7zaugo
WZcUps04qaJfcmzxaN7wQb3I1V.fAGd6RTm9pybriL8C03cc2Oqm0gNApZtz
xpOFpW.Qa4P1WEaVTfpVvswdf6E1ZKkFK7jKCHXfb.bT+9P1hgLinWNnuhWT
D3FyuuV5zXTji7zjHTDR+9zEyieRUltds7Lt6XYZIFe9h80ug.vf5OeiidGC
C3ysNMqXJi5T8m2cG7vgyY2Fq.U6RyxFM6cLaiiI.mIPeQlvvRl4EoUxHXjN
SAXjHjCjrIN3ffXOQyCyLWOBebaRsj1yWNwe9edLfcqW6dK79v2FQ229eOMx
jMFQ.GlaMjO+hJJ+87yPzvbyut35bwU28QiS8wLEIfc+gjvagequ+cRqI+sG
MN+HlkVJrqj4xxyt1Va5s1z663R56wIX7k8ahxDgAhZEvGyl.OhAsQueOH.k
3ADPO9Ns7.Y.jWWFArvxaKGPmT6WFoBe.G.4csinbG6Hv01QX26H6yrM0Vl8
sRDHpNsaLVk4X3auBKPlTGfd3pqcXiBD9zDITAoivwAh0BGJnCCCUGABTGgn
gpibneDcq5QyNtYNSdGyO8gNzyvqtmgmqmAd.aELGnQnO5HRf5HMrbNrS3Cc
GbWjz3bOzStnMD6kYIWLoSnSAKuacMo+t95jyEN4eg3iqqYSBf6B6aqg3qSP
wE92t0JwKumbgIhy7QO4hhSgOTQycQyovKpNwgRGsKVVIbezSv.QRLW3wo9f
yi4hJCpO.OlK73LuzStv4w7gyjLTvPOXv5IWzjy7AWNMNTzDUDrdxItbeXch
RCjxHJITlAogR+pKPG1GlaIN4GJdrMABBL+NrhEbaEm53kW6nyEk+cq0xWdO
wbEGfCiCls5BGaq7VziWdsiNW3GHBefCtHKQ7grDwEifDe3PNwECFwiwhyoP
cXRaYwO4xqcv4hFEenRAKbDEFjAW.MkqAC+MmyLffG3uwtHmCo9.EXgZwY3P
Y9CSdGf2n6iufTOkJhgHhopxAfz6G4dW63NP3CxIu3FCdDhtF35d00Nzb5Lk
7xtJ6jDlOrjhbQBC4C85HmrU4iNBGJkFHji7pCpjNlz0IjXn27AAACFH.bkW
8Z2oYnKpFH9vOanSR5domBlsTnKR5Xe3UJzIao9POIzEcJHeXVB5hREA0Gb4
NoTwGRtPmzQ3ENh.o5G5vwqgQSwYk3RO+JYcOcTIvt+v93tqBlHrIY2tmjkU
1mV2Gy1l7ESU1Wbu9xzbykT8kkxl7ov77lVRJWrIUIWn1WZxYfmYlP.ZVShL
TluO0Rj5eHNloCeol7KnZmMQOzQ4zm9yO8+wtCHfj
-----------end_max5_patcher-----------
</code></pre>

And here is the fork with the source.

Feedback would be much appreciated, PR is coming soon. :slight_smile:

3 Likes

I think pressure testing this could be of good help. Also, I’m not certain where we can sensibly package it for maximum impact. I’m thinking of a tab in the fluid.plotter helpfile…

1 Like

Unless it doesn’t have (all the) main feature parity, I would opt for a complete replacement. There’s already so much “lore” that’s missing for new users as things are buried in forum posts, example folders, 3rd/4th tabs of help files, it would be a shame to add new stuff but put it out of sight.

edit: I do like having the individually addressable point size/color like the 5d one from a while back, but I’m presently not using anything like that.

Is this due to the per-point set approach to this (instead of older approach that had color/size as separate pre-packaged matrixes?). I personally liked/preferred having/building a separate matrix per D anyways, rather than having to uzi/iterate through a long list to manually set each individual point (as is the current paradigm/implementation).

edit edit:
Being able to do this with a native plotter would be amazing.
datasetplot-raycast

2 Likes

it doesn’t and won’t, so let’s not dwell. Also, since it makes a diff only at 100k point+ then it is quite a niche use… or at least probably not a beginner

feel free to do a PR once you’ve coded it :smiley:

Even with a modest (few hundred) amount of points I get lag when it first using it. It “catches up” after a bit.

That whole thread was essentially that, but it was never folded in (hence the comment about things lost in the forum, of shoved in a folder). Things not baked into the actual files don’t really get used or explored. But that’s a tangent not relevant to the thread!

1 Like

I can look at the 3D version in a bit, I do think it would be cool, too! Maybe as a fluid.jit.3dplotter…?

As for the individual point sizes/colors, it is of course, possible, but since fluid.jit.plotter was aimed for speed with large datasets, I sacrificed these features in the name of speed. If we want the individual settings we have to change paradigm (instancing via jit.gl.multiple instead of using jit.gl.mesh), and that adds quite the overhead when we talk about 100k+ objects.

…and those features are already covered anyway in fluid.plotter, at the moment I see novelty in making a solution for a lot larger datasets (like fluid.jit.plotter) or making the 3D one.

3 Likes

I feel quite strongly that having this as a separate object with its own documentation and help file is the best path forward. It is a tool that is called for in different circumstances, and is there to overcome the limitations of Max and the wider problem of high dimensional visualisation. It also shows a significant benefit at high numbers of points but it does feel quite a lot faster even at low dimensions. In many ways its a superior option for simple uses cases, especially if the plotter is being used instrumentally.

2 Likes

Yeah that’s fair.

I just didn’t want it to end up in an abandoned /Examples folder never to be seen again. Having it as a “native” abstraction, folded into the actual documentation would be fantastic.

it won’t replace the canonical one in the helpfiles for many reasons, but a tab pointing at it in the canonical help to showcase the main raison d’être, and its own help, seems a better place than Examples indeed

2 Likes

although @MattS6464 has improved the paths to Examples