#pyqtgraph

1 messages ยท Page 6 of 1

rough furnace
#

"this very channel" I'm not sure what that means in this context (should have caught that earlier my bad)

hexed tundra
#

Gah that's my bad--I try to keep the bulk of the messaging between the announcements as similar as possible and missed that--give me a moment

rough furnace
#

no problem!

hexed tundra
#

(thankfully it's a simple edit)

#

and review pull requests in the #pyqtgraph-sprint-chat channel under the OPEN SOURCE PROJECTS category which can be found in the left sidebar of the discord

#

That should be more clear

rough furnace
#

๐Ÿ‘

#

not sure if you can sticky comments, I'm drafting a post to put on there with some more details that I felt might be overwhelming in the annoucement.

hexed tundra
#

I can sticky mod comments, and yours will be distinguished since you were named in the post. If we need to I can make a stickied comment linking to yours

rough furnace
#

that should be fine

rapid kestrel
#

Also, question for all you pyqtgraph maintainers: How interested are you in keeping this channel around for y'all to use year round for organizing things for pyqtgraph in general?

#black-formatter has migrated to this server after the freenode irc debacle and you can see how they use it. You could use this channel for something similar (we could open this channel or a similar one for year-round interaction with folks on this server).

rough furnace
rapid kestrel
#

That's entirely reasonable! Happy to leave the option on the table for y'all for the future

rough furnace
#

that's largely a question for admins here if they would be willing to have the channel here, ...they may not want to add to the noise if there isn't buy in from all the maintainers. If they do allow the channel to maintain, I would gladly monitor it tho (and low-key hope we migrate away from slack)

rapid kestrel
#

We can just keep this channel private to y'all and hidden from the general server members. We already have... quite a few channels that one more in this category won't hurt anything.

#

I can also always make a pretty snazzy proposal showcasing some of the nicer features we can offer in this discord, but it will always come with some downsides especially being part of a large server like ours

wide prism
#

Are we going to move regular development discussion to the public channel here for the duration of the sprint? It doesn't really look like we'll be overwhelmed there...
Seems like pyqtgraph is the anti-hype, non-dashboard, "what's this 'data science'?" plotting library ๐Ÿ˜

rough furnace
hexed tundra
#

@rough furnace Would you like a second post on reddit tomorrow, at the start of the sprint announcing it's kickoff?

rough furnace
hexed tundra
#

Nah it's no problem at all! I'd be happy to!

#

I'll make a draft later today, what time would you like it posted? And is there any different content you'd like to highlight from the original announcement?

rough furnace
#

no need to change content; in terms of time to post, maybe 11 AM PDT?

hexed tundra
rough furnace
#

Thank you!!!!

rough furnace
#

@obsidian sapphire :chef-kiss:

obsidian sapphire
#

heh; that's not exactly an improvement.

rough furnace
#

heh, before you ran pycln the error count incremented upward by over 100

#

this PR was never going to address the static code checker stuff anyway

obsidian sapphire
#

mm. it looks like we're -106 from earlier this evening, though, so nice work on #2002!

rough furnace
#

yup, waiting for lgtm.com to rescan our repo and see if we get bumped up from "A" code quality to "A+"

#

(which I'm not sure if that says more about our repo or their service)

#

dumb question, does pycharm have type-completion now when using pyqtgraph.Qt ?

#

(also I'm giggling on the inside every time I see the diff in a commented out code chunk)

obsidian sapphire
#

I have a Qt.pyi file that usually does it for me, but I haven't looked at it closely to know if I'm doing it correctly in all environments.

#

Nils gave it to me, I think? it's just a series of nested try/except-import-error blocks that go through all the possible versions of qt

wide prism
#

No, that's not a thing I'd be good at ๐Ÿ˜†

rough furnace
#

Pretty sure that was @mortal grotto

obsidian sapphire
#

I would equally believe that!

rough furnace
#

@obsidian sapphire this PR LGTM; do you want to merge or should I?

obsidian sapphire
#

do eet!

obsidian sapphire
#

no? it has some very large automated things and some small, hand-made things, which might be useful to keep separate someday.

rough furnace
#

good point

obsidian sapphire
#

๐Ÿ‘ฏ

rough furnace
#

alright, i'm going to call it a night, ...and i'll briefly say hello tomorrow morning but I have some kid related errands I gotta run so I won't be particularly active on here until mid-day my time.

obsidian sapphire
#

cheers! see you then.

rough furnace
#

and back to 25 PRs ๐ŸŽŠ

rough furnace
#

@fervent vale I'll take another look at the jupyter example, last time I used it it was in pretty good shape

mortal grotto
fervent vale
#

Don't think many of us have an idea of that

rough furnace
#

@wide prism has been an advocate for pyqtgraph in the notebook, so he may be a good first person to ask; I'll take a look at the issue tracker as this has come up on a few occasions

wide prism
#

I like the idea because I think that is how many science people use Python now. As a cheap/capable Matlab/Mathematica alternative.

rough furnace
#

the use-case I'm imagining comes w/ future integration w/ pandas, often with scatter plots zooming in/out to evaluate stuff in more detail.

fervent vale
#

I think I would have liked an easy way to plot an image and then to play inter actively with the levels

#

For line plots pyqtgraph allows the user to zoom

#

For images the speed of pyqtgraph allows the user to play with intensity levels

wide prism
#

But my own use case is to run in %matplotlib qt mode:
I like to keep the plots out of the notebook itself, because that notebook sits in a git repository for versioning/backup/distribution.

If I understand the current effort correctly, the framebuffer is what allows plots inside the notebook, right?

fervent vale
#

But there's no image view widget now

rough furnace
#

going to be afk for the next hour+

fervent vale
#

Yes, the plots are in-line within the notebook but are not static

hexed tundra
wide prism
#

How does it handle saving the notebook? Keep a frozen image around?

rough furnace
hexed tundra
#

Thank you! I'll drop a draft of the post here when it's ready then post it in an hour and a half, unless you'd like it up when it's written

wide prism
fervent vale
#

I suppose you could plot lots of points, pan and zoom it to the view that you want, then click save

wide prism
#

random plot

#

Having linked axes on the time series data would be really cool. And I need to jump around in the data and look for glitches, so pyqtgraph pan/zoom would be awesome.

#

I have the opposite problem with saving:

#

I keep fiddling with the view, and it ends up saving a new version of the large file every time. And that clutters up my repo. Which distributes to a bunch of computers.

#

So currently, I store the images separately (they don't need versioning, really).
(edit) I am just saying that I probably won't be able to switch my "production" environment to use your framebuffer pyqtgraph.

fervent vale
#

That's why none of the included example notebooks has images saved in them...

#

I was trying to setup mybinder.org but it gives me a ubuntu 18.04 container and the kernel crashes the moment I create a QApplication

wide prism
hexed tundra
#

For the pull request above (2055)--is it fair to say this pull request aims to "improve plot interactivity in the Jupyter Notebook environment"? Or is there a better way to quickly explain it?

wide prism
#

If @fervent vale isn't around right now:
I think that is a good description.

hexed tundra
#

Fantastic, thank you!

rough furnace
#

Hey Keith I would say enable interactivity, presently we can't do interactivity at all

wide prism
#

Oh, but it improves interactivity over the MatPlotLib version ๐Ÿ˜›

hexed tundra
#
Title: Join the PyQtGraph Code Sprint!

Body:

Join the PyQtGraph maintainers today, November 13th and 14th for a Code Sprint hosted by our sister community the Python Discord!

PyQtGraph frequently finds use in scientific computing/research applications especially when you need to view data in realtime. The Python Discord be hosting a coding sprint on the server to tackle open issues and to submit and review pull requests in the #pyqtgraph-sprint-chat channel under the OPEN SOURCE PROJECTS category which can be found in the left sidebar of the discord.

During the sprint we hope to:
- Submit PRs that address existing open issues
- Test, review and merge existing PRs
- Identify documentation that can be improved, and submit PRs to do so

If this is interesting to you, an example pull request we hope to tackle can be found here: Jupyter PlotWidget Example which aims to enable interactivity in the Jupyter Notebook environment.

Office hours will be at November 13, 2021 3:00 PM (2100-2300 UTC on Saturday, November 13) where @j9ac9k (u/ogi010), @ntjess, @outofculture will be available to answer any questions you might have while contributing!

If you're interested in helping contribute to this library then check out the following:
- Read and abide by the code of conduct https://github.com/pyqtgraph/pyqtgraph/blob/master/CODE_OF_CONDUCT.md
- Setup your contributing environment https://github.com/pyqtgraph/pyqtgraph/blob/master/CONTRIBUTING.md
- Get ready to have fun and support an awesome library!

Basic Plotting Example Using PyQtGraph
Exploring a Scatter Plot
Highlighting Regions of Interest
A pColorMesh which generates pseudocolor plot with convex polygons

Ok it dropped the links, but roughly, how's that?

#

It's almost identical to the previous one, but this adds a reference to the pull request you're focusing as an example of what to expect

wide prism
#

"especially when you need to view data in realtime" --> "especially when there is a need to view data in realtime"

#

"The Python Discord be hosting" --> "The Python Discord is hosting"

#

๐Ÿดโ€โ˜ ๏ธ Arr!

hexed tundra
#

Ok I'll grab a bit more coffee and fix that ๐Ÿ˜…

#

clearly it's needed lol

wide prism
#

"Office hours will be at November 13, 2021 3:00 PM (" needs a timezone?

hexed tundra
#

Additionally, if you'd like to make the submission, I can and pin it

wide prism
#

"then check out the following:" --> "then"

hexed tundra
wide prism
#

@rough furnace , can we pick one of the images to actually have in the post, instead of links to four of them?

hexed tundra
#

I think it's fine, but I am time and time again not the person to ask about data science visuals. I go far too noisy all the time

rough furnace
#

I don't think Reddit supports embedding images, extensions like Reddit enhancement suite can automatically put them inline

wide prism
#

Four images is certainly overload. The color mesh looks kinda-clean, though ๐Ÿ™‚

hexed tundra
#

Really? Interesting. Why that one specifically? I liked the basic plotting example personally

wide prism
#

Keith, thank you for helping us out with that. The post is great as it is, I can always find something to nitpick on ๐Ÿ‘

#

Well the basic example would also work

#

It's a better example of functionality, but the other one seemed like a better eye catcher ๐Ÿ™‚

rough furnace
#

not really AFK any more but not really not-AFK

wide prism
#

What's your timezone?

hexed tundra
#

No problem at all! I'm excited and hope the reddit post can encourage some contributors to take a look

hexed tundra
hexed tundra
rough furnace
#

ugh, we just had daylight savings time lol, "office hours" starts ~2 hours from now ๐Ÿ˜†

hexed tundra
#

haha yeah daylight savings is what's messing my timing up. I think UTC is still correct: 2100-2300 UTC

wide prism
#

6:00-8:00 JST ๐Ÿ˜œ

#

(Yeah, UTC seems right)

rough furnace
#

yeah maybe just put UTC and be done with it ๐Ÿ˜†

hexed tundra
#

Ok listen here! I just had a full tom scott timezones moment: https://www.youtube.com/watch?v=-5wpm-gesOY ๐Ÿ˜›

A web app that works out how many seconds ago something happened. How hard can coding that be? Tom Scott explains how time twists and turns like a twisty-turny thing. It's not to be trifled with!

A Universe of Triangles: http://www.youtube.com/watch?v=KdyvizaygyY
LZ Compression in Text: http://www.youtube.com/watch?v=goOa3DGezUA
Characters, Sym...

โ–ถ Play video
#

Wait JST is a time zone?

wide prism
#

JST = Japan Standard Time

rough furnace
hexed tundra
#

I got, "Joint Services Transcript." when I looked so I assumed you were messing with me. Full tom scott timezones now.

wide prism
hexed tundra
#

Oh that 'Difference from Local Standard Time' is a nice feature

#

So that section now reads,

Office hours will be at 2100-2300 UTC on Saturday November 13, where @j9ac9k (u/ogi010), @ntjess, @outofculture will be available to answer any questions you might have while contributing!

rough furnace
#

perfect

mortal grotto
#

How do you monitor your feeds? It's unwieldy for me to have reddit, discord, slack, GH discussions, and issues open... I suppose I should get better at configuring notifications, haha.

#

Just bringing it up in case we wanted to recommend a contact method in the post

hexed tundra
#

Ok I think I've got all the changes, dropping the links it looks like this:

PyQtGraph frequently finds use in scientific computing/research applications especially when there is a need to view data in realtime. 

The Python Discord is hosting a coding sprint on the server to tackle open issues and to submit and review pull requests in the #pyqtgraph-sprint-chat channel under the OPEN SOURCE PROJECTS category which can be found in the left sidebar of the discord.

During the sprint we hope to:
- Submit PRs that address existing open issues
- Test, review and merge existing PRs
- Identify documentation that can be improved, and submit PRs to do so

If this is interesting to you, an example pull request we hope to tackle can be found here: Jupyter PlotWidget Example which aims to enable interactivity in the Jupyter Notebook environment.

Office hours will be at 2100-2300 UTC on Saturday November 13, where @j9ac9k (u/ogi010), @ntjess, @outofculture will be available to answer any questions you might have while contributing!

If you're interested in helping contribute to this library then:
- Read and abide by the code of conduct https://github.com/pyqtgraph/pyqtgraph/blob/master/CODE_OF_CONDUCT.md
- Setup your contributing environment https://github.com/pyqtgraph/pyqtgraph/blob/master/CONTRIBUTING.md
- Get ready to have fun and support an awesome library!

Basic Plotting Example Using PyQtGraph
A pColorMesh which generates pseudocolor plot with convex polygons```
rough furnace
# mortal grotto How do you monitor your feeds? It's unwieldy for me to have reddit, discord, sla...
Know Your Meme

Pepe Silvia is a reference to one of the most famous scenes of Itโ€™s Always Sunny In Philadelphia in which the character Charlie goes on a conspiratorial rant about how he believes a person named โ€œPepe Silviaโ€ does not exist. The scene has gone on to be a favorite in the Always Sunny fandom and has found use as a reaction image on Twitter.

hexed tundra
rough furnace
#

only other suggestion I have is potentially linking the comment I made in the previous post about some more of the speciifcs

#

let me dig up the link

hexed tundra
#

Office hours will be at 2100-2300 UTC on Saturday November 13, where @j9ac9k (u/ogi010), @ntjess, @outofculture will be available to answer any questions you might have while contributing! u/ogi010's introduction to the event and project can be found [here](https://www.reddit.com/r/Python/comments/qm0bmz/pyqtgraph_code_sprint_on_november_13th_and_14th/hj6jl6n/?context=3)
how's that addition?

rough furnace
#

:chef-kiss:

hexed tundra
#

Ok, the post is ready then. Want me to post it or would you like to? I can pin it regardless

rough furnace
#

why don't you do it, no doubt I'll still screw it up ๐Ÿ˜†

hexed tundra
#

Haha I screwed it up last time so that's not a big deal at all

#

(Lets see if the image embeds work)

rough furnace
#

embedded links I think require reddit enhancement suite; on a plain browser they just show up as hyper-links

wide prism
#

The factorio reddit has images; That's about the full extent of my reddit usage.

hexed tundra
#

I *think* that's how reddit behaves if it's not specifically a gallery post

wide prism
#

Ah, alright then ๐Ÿ‘

hexed tundra
#

Did the old post show the links more correctly?

wide prism
#

No. Just links; That's why I brought it up. I thought it did that because there were too many images.

rough furnace
#

left is safari, no extensions, right is chrome with reddit enhancement suite

hexed tundra
#

I honestly don't know. Their whole embedded content is weird. *grumbles in moderating on reddit*

rough furnace
#

hahaha naw leave this as is, it's fine. ... probably should look into it at some point, not worried about it now tho

wide prism
#

Agreed, no need to worry! ( @rough furnace , is it just me, or is it a little hard to tell how exactly that is "enhanced"?)

rough furnace
#

reddit enhancement suite has a ton of functionality and I only use a micro-fraction of it.

#

truth be told I don't often like to stray from defaults, when I installed it to begin with, it was much more essential than it likely is at this point... I honestly haven't done a good comparison of what functionality it provides that I find very useful

hexed tundra
#

Reddit is a cobweb of weirdly well supported things, poorly supported things, and community supported things. I have res default to old reddit because I'm adverse to change (Where as Joe drives us to try the new features and actually keeps the sub feeling up to date). Regardless, looks like the post is up and works, I'll be watching it throughout the day to make sure anyone who's got a question refers to the discord

rough furnace
#

Thank you so much @hexed tundra !

#

@wide prism I don't even want to do the math on what your current local time is ๐Ÿ˜†

hexed tundra
#

No problem! Glad to help and hope the reddit side joins! We really wanted to work more with the greater python community this year and events like these are a fantastic opportunity to do so!

wide prism
#

(j9ac9k) Well, you could click on the JST link above. But the answer is simple: Sleepy time! I won't solve any more ViewBox issues today ๐Ÿ™‚

hexed tundra
rough furnace
#

between you and the admins here we've the thankful ones!

hexed tundra
#

@rapid kestrel Thank you as well for helping get all of this running!

rough furnace
#

<@&267628507062992896> any chance we can white-list some folks to voice-verification that haven't been here for 3 days that just joined the server for the purposes of the sprint?

polar onyx
#

I can disable voice verification for this VC if you'd like

rough furnace
#

I'm good w/ that, provided you can re-enable it if it's a problem?

polar onyx
#

Yeah, np

rough furnace
#

thank you so much!

polar onyx
#

Everyone should be able to speak now

#

If someone still can't speak they will need to re-join the VC for the permission to update

rough furnace
#

way more people here than scipy sprints ๐Ÿ˜ฌ

fervent vale
rough furnace
#

at least in safari there is something funky happening w/ linear region items, let me check w/ chrome

#

ok, the linear region item is a safari specific issue

#

on the ROI examples, looks like the plot is cut-off?

#

same with the plotting example, although the cut-off isn't as extreme

#

baby is waking up, afk for a little while

fervent vale
#

If you close the left sidebar, you get more screen estate. Then you can resize the plot frame to show more

#

I am not sure if GraphicsLayoutWidget has some minimum size per plot

#

One thing is that a few of the examples in pyqtgraph set up really large screen geometries

rapid kestrel
#

If you'd like me to end the office hours event let me know

rough furnace
#

@fervent vale I'll do another run through on your jupyter PR in a bit (few hours), I'm a bit bummed about the safari mouse behavior but I suspect there isn't anything we can do about that one, maybe the jupyter_rfb folks.

rough furnace
#

@fervent vale hmm... I collapsed the side, panel, unfortunately that didn't seem to buy me any space on google chrome:

#

same w/ plotting example

#

i'll try and take a closer look once I get the kids to bed in a few hours

fervent vale
#

after collapsing the side panel, you can drag the bottom right corner of the plot to resize it

rough furnace
#

right, in my case it seemed to stretch the image (at least on the plotting example, should check the ROI example)

rough furnace
#

the ROI example rescaled once i made it wider ๐Ÿ‘

rough furnace
#

I have previously had gotten ~5 pycharm pro licenses for working on pyqtgraph (license could not be used for commercial work) if there is interest in getting those again let me know and I'll re-apply

rough furnace
#

@rapid kestrel we've had more newcomer activity than I thought we might. Thanks again for hosting/promoting us!

not sure when we should discuss if we want to keep and/or open this channel to the public, and what factors would go into that.

#

oh, and on queue, baby woke up from nap!

rapid kestrel
#

So! We're happy to keep this channel around for y'all closed if you want to use it for the future.

If you'd like a permanently open channel, that'd be closer to our partnership with #black-formatter, where this channel is more of a base for your operations and open to the community to participate in as well

rough furnace
#

I want to continue this convo later, with the baby being up, my attention is sort of taken there ...i'll be monitoring the sprint channel here for the rest of the weekend but probably won't be too active there (maybe after the kids are in bed)

fervent vale
#

NilsNemitz, I was trying to add an interactive ColorBarItem to the jupyter simple.ipynb image example. How are the handle bars meant to work? They keep on snapping to some other position?

wide prism
#

The ColorBarItem example has a number of different settings.

#

The handles make the limits ("values") shift while pulled; the handles snap back when you let go.

fervent vale
#

So let's say in the ColorBarItem example I pull the lower handle to 5000, is the lower image level set to 5000?

#

The handle snaps back and it's not obvious what level got set

wide prism
#

It's designed to work interactively by looking at what the axis says and how the image looks.
There's a quadratic dependence on selected position that gives you both close-in accuracy and the option to make large changes quickly.
The logic starts here:

#
        """ internal: recalculate levels based on new position of adjusters """
        if not self.region_changed_enable: return
        bot, top = self.region.getRegion()
        bot = ( (bot -  63) / 64 ) # -1 to +1 over half-bar range
        top = ( (top - 191) / 64 ) # -1 to +1 over half-bar range
        bot = math.copysign( bot**2, bot ) # quadratic behaviour for sensitivity to small changes
        top = math.copysign( top**2, top )```
#

Qt also lets you drag the mouse outside the plot window, and it will still follow. Not sure if the notebook lets you do that?

#

Grabbing the top handle and moving it to the top of the bar should double the range.
Grabbing the top handle and moving it to the center of the bar collapses the range to the allowed minimum.
(same in reverse for the bottom handle)
Between the end points the response is quadratic: When the handle is moved up by half the distance to the end of the bar, the range will change to 1.25 x the previous range.

fervent vale
#

Okay, so I misunderstood the meaning of the handles. They don't indicate the levels

rough furnace
rapid kestrel
#

whoo! ๐ŸŽ‰
We'll delete the voice channel and archive the pyqtgraph-sprint-chat

rapid kestrel
rough furnace
rough furnace
#

@rapid kestrel debating how to handle people DMing me for support w/ random stuff (not pyqtgraph related, just ... "hey can you help me w/ <insert weird pyinstaller issue>" )

quartz tiger
#

We have this pin in our staff channel, might work for you with a small amount of altering ```
Hey!

We do not offer programming help via DMs, so please ask your question in one of the available help channels (See #โ“๏ฝœhow-to-get-help). The main reason is that by asking your question in public, everyone can contribute to the answer or benefit from it. Also, as we're a fairly large server (275k+ members), it prevents our staff from getting flooded with DM requests for help.

Thanks!

rough furnace
#

was about to ask ๐Ÿ˜†

half jewel
#

I'm pretty sure python community members have access to the !poll command FYI

runic umbraBOT
#
Should

๐Ÿ‡ฆ - we
๐Ÿ‡ง - migrate
๐Ÿ‡จ - from
๐Ÿ‡ฉ - our
๐Ÿ‡ช - slack
๐Ÿ‡ซ - workspace
๐Ÿ‡ฌ - to
๐Ÿ‡ญ - this
๐Ÿ‡ฎ - discord
๐Ÿ‡ฏ - channel?

half jewel
#

ah sorry I should've provided an example

rapid kestrel
#

It's not just me!

half jewel
#

!poll "your question" "option-1" "option-2"

runic umbraBOT
#
your question

๐Ÿ‡ฆ - option-1
๐Ÿ‡ง - option-2

rough furnace
#

than kyou!

hexed tundra
#

I don't know how to use the polls either, so I'd have done the same

rough furnace
#

!poll "Should we attempt to migrate from Slack Workspace to this discord channel/server?" "Yes" "No"

runic umbraBOT
#
Should we attempt to migrate from Slack Workspace to this discord channel/server?

๐Ÿ‡ฆ - Yes
๐Ÿ‡ง - No

rough furnace
#

Tagging some pyqtgraph members to answer above, check the thread for more explanations.

@wide prism @fervent vale @torn coyote @obsidian sapphire @mortal grotto @plush fulcrum @violet basin

mortal grotto
rapid kestrel
#

yup! all message history is retained.
If you don't mind me asking, what sort of tools/niceties does slack provide y'all that you'd need here (if you were to theoretically switch)

rough furnace
# rapid kestrel yup! all message history is retained. If you don't mind me asking, what sort of ...

there is really nothing slack provides us that is particularly useful other than it's an online place that everyone is already at. Discords screen/voice/video share capabilities are far better, the history/search capability is far better...

I do have a slack github bot that alerts us of new/closed PRs/issues but that's something that's just handy, hardly a requirement or something tempting....

The big hurtle here is asking people to migrate over, ...not sure if everyone (most people?) even had discord installed before the sprints (we did a sprint via discord at the scipy conference)

wide prism
#

Hmm. The view from very much my perspective is

  • I find it somewhat easier to scroll back and read up on Slack. Somehow discord's interface feels more focused on what's on now.
  • The noise (of things happening in other channels, random messages, the "online users" bar on the right) is dangerously distracting for me.
  • We would need to maintain some separate communications for "random" vs. "development". (And I don't want to chat with 100,000 python users.)
  • I haven't found a way to follow individual channels on discord, and even on this weekend missed discussions in the one other channel
#

That said, I feel like this is much more accessible here to the users we would like to help out; and maybe get to contribute at some point. So it seems like the right move to migrate?

rough furnace
wide prism
#

I could imagine that one option might be to set up a cozy little pyqtgraph discord server that I could usually hang out on? Jumping servers seems to be as convenient (or more so) on discord as on slack.

rough furnace
#

Scrolling back on the black-formatter channel, looks like most of the activity is the github bot (which I would probably not want); other than that, looks relatively quiet.

wide prism
#

Anyway, work! (distractions, distractions)

tight cliff
#

fyi, that github bot is a webhook service provided by GitHub itself, so you can filter events (commits, pr comments, issue creation, etc.) as you please, plus this server has some custom filtering through cloudflare workers as well

obsidian sapphire
#

I don't mind being on all the chats and servers, myself, and discord works as well as anything.

rapid kestrel
# wide prism Hmm. The view from very much *my perspective* is - I find it somewhat easier to ...

So, if you don't mind me commenting (I use slack on the daily for a non-profit I'm very involved in). I promise this will be neutral!

  • Discord is definitely more IRC-like than Slack. Both a blessing and a curse. I will say that discord supports threads and they're a bit better than Slack (i.e. you can view it in full preview mode, see all threads in a channel at a high overview, opt into threads you care about)
  • This server has been known to be very... alluring to those who like distractions. I find myself frequently sidetracked being helpful but not necessarily productive. It does help if I'm ruthless with muting channels + categories and then collapsing them so I only focus on what's necessary.
  • As for communications, dawn mentioned a thing that worked for black, which is a private DM for the closed stuff, otherwise things go in this channel. I will say the these open source channels are relatively left alone. Not entirely because of this server's size, but we do have a team of moderators.
  • Following individual channels gets difficult. You can change your settings to get notified for every message in this channel but that gets very noisy very quickly. The only other thing I've found is just ruthlessly muting and collapsing all the other categories.

Slack also has keyword notification ability which I very much miss for this discord.

I also would recommend y'all to see if setting up your own little server is maybe a better move. It'll be quieter, you'll have total control, and we can still whitelist the channel here if you want to post an invite.

Also, as dawn said, we have the ability to filter which github events you want. So if you want we could do something like: new PRs, new issues, and things like that.

wide prism
#

Just to clarify: My thought was that it might work to have the private, low traffic, random channels on a separate server. Then stick to the one development channel on here.

But it also seems that once I figure out discord's muting/notify system I might feel a little healthier here (thanks @rapid kestrel , for pointing that out.)

rough furnace
#

we now also get the squid icon next to our names fwiw

mortal grotto
#

Also, is there a way to hide the top-level threads I don't want? It would make navigation so much easier

quartz tiger
#

if you right click on the category, you should get a mute option

#

you can then click it to collapse all channels in the category

rough furnace
#

After muting a number of groups, I must say the left channel is much more manageable (even though I had become accustomed to just using Ctrl/Cmd + K to navigate)

mortal grotto
#

Thanks for the tip! Using those keywords I was able to find a helpful post online.

For others in the same boat, you can right-click the python discord and go to notification settings to mute multiple at once without having to right-click every individual channel

rough furnace
#

@rapid kestrel is there a way we can get the archived channel logs? we suspect there may have been a hint in there about something we now can't remember ๐Ÿ˜† (and to think I thought archiving instead of deletion was silly)

rapid kestrel
rough furnace
#

@mortal grotto while I don't see the channel in my left window, using Ctrl+K, it will show up as available, want to search there for what you were looking for?

#

@rapid kestrel thank you!

mortal grotto
#

That worked, thanks!

mortal grotto
#

@rough furnace why on earth wouldn't you want type hints?? ๐Ÿ˜›

plush fulcrum
#

I particularly like all the unions with Any in there, rendering the rest of the union useless

mortal grotto
#

Interestingly, PyCharm doesn't treat them as useless. i.e. Union[Any, str] can still give string completion suggestions

wide prism
#

@fervent vale, I finally got the jupyter notebooks to run on my machine, and just wanted to say that it is indeed awesome to have pyqtgraph interactions there!

Is there some way to lock the notebook files in the git repository? If I go play with them, they seem to keep autosaving, and then I have to avoid accidentally committing a changed version. I guess it might also be a good idea to gitignore the .ipynb_checkpoints subfolder?

fervent vale
#

I suppose one could copy the example notebooks to a local directory. I don't have a good idea how to deal with the auto-saved notebooks, except to run git restore .

mortal grotto
#

Regarding discord vs. slack, I think I'd be fine with either as long as we are consistent (leaning toward discord just because of message history...)

It's becoming hard for me to search for things since now they could be under either service. It doesn't matter much, but it's enough of an inconvenience to take me off the fence ๐Ÿ˜›

Can someone remind me of the fix for the "model not found" error in pyqtgraph.jupyter? Where does offscreen need to be set?

fervent vale
#

Windows or Linux?

mortal grotto
#

Windows ๐Ÿคฆโ€โ™‚๏ธ๐Ÿคฆโ€โ™‚๏ธ Don't know why I said that

fervent vale
#

For Windows, offscreen plugin doesn't work, so you can't use it. (There will be no fonts)

#

So just run jupyter-notebook.exe

#

On Linux, and especially so for WSL2, you can use offscreen plugin.

#

QT_QPA_PLATFORM=offscreen jupyter-notebook

#

I didn't manage to get QtWidgets.QApplication(['-platform', 'offscreen']) to work, even though web search says it should

#

But that said, I haven't come across this "model not found" error before

mortal grotto
#

I found the issue. I thought if I restarted the kernel after installing jupyter_rfb I could interact with the widgets, but the server itself had to be restarted, not just the kernel. Not sure if there should be a blurb in the docs about this if users run into the same issue? I imagine many people will install jupyer_rfb for the first time in this setting and might open issues. Or, they will be smarter than me ๐Ÿ˜›

fervent vale
#

For me, installing jupyter_rfb was the thing that pulled in all the notebook dependencies for me. If you look at binder/requirements.txt, it is really short

mortal grotto
#

Right, but I had a jupyter server running and installed jupyter_rfb while in a kernel. I got the "model not found" error until after I restarted the server, then everything was fine

All the requirements install properly, it just shows a static screenshot until you restart the entire server (instead of just the kernel, as many users might be accustomed to doing). Again, it could also be a non-issue

wide prism
#

Same here on the static images on jupyter rfb. I installed the pacakges (conda on windows) and the notebook would only show static images. Today I tried again, and everything ran interactively. So I guess a restart of something is required at some point.

rough furnace
#

The way to do then would be to add them to .gitignore which I don't think is a bad idea really I may have been way off base

wide prism
#

How does that work in this case? If they are in .gitignore, it won't add them as new files to the repo. But won't it keep updating them if they are already known?

It might be a good idea to add

.ipynb_checkpoints
*/.ipynb_checkpoints/*
``` ?
rough furnace
#

i would git ignore the directory; you can still commit stuff to git ignored files, there is just an extra check to do so on second thought not sure git ignore would ignore changes to already added files...

rough furnace
cedar trail
#

that's so sweet

rough furnace
#

we've been really lucky in that regard, we periodically get some impatient people with "new issue -> when are you doing the next release?" ...we had one individual that went a mini rant when we introduced a CoC but overwhelmingly our users have been super supportive

#

I'm not sure if this is because our library generally is tailored towards other scientists/engineers that may not be software devs, and there just isn't a good replacement.... anyway not sure the reasoning even matters

rough furnace
# runic umbra

tag 7 people, get 1 vote ๐Ÿ˜† clearly we are an opinionated lot

mortal grotto
#

The last thing keeping me from wanting to migrate is being able to follow a thread. If you're late to the conversation, is there a way to see all replies to a post (if no thread was created)? Or do you really have to click through the linked list of replies?

cedar trail
#

you can make a new thread for each "post"

#

since can make unlimited threads

#

oh my bad
the answer is no

#

you will have to click through the linked list of replies since there is no way to filter out messages that are not related to the post

#

is that a thing in Slack?

cedar trail
mortal grotto
wide prism
#

I have a direct message from our github contributor Wubbzi / Inigo Montoya.
I would assume that we want to invite any active contributor to this channel?

vital night
#

feel free to ask the admins for anyone you may wish to add here

wide prism
#

I think we'll wait for @rough furnace to wake up, but if anyone else has ideas on policies for the pyqtgraph discord club house, maybe speak up.
Since we don't usually have an excessively large number of people involved in discussions (on github and slack), I think we don't need to be particularly selective here either.

rough furnace
#

Oh yeah please invite them here

wide prism
#

How's it work? Do I need to ask a server-level admin to set access to #pyqtgraph ? I don't want to waste anybody's time ๐Ÿ™‚
There's an "invite" button on the channel sidebar, but that seems to want to invite to the Python discord in general.

rough furnace
#

Yeah, this channel is limited to those with the pyqtgraph role, and only admins can assign roles

wide prism
#

I guess I should ask then ๐Ÿ™‚

rapid kestrel
#

I can also assign roles, feel free to drop the ID here and we can handle it~

wide prism
#

Dear <@&267628507062992896> , can we give access to #pyqtgraph to Chris_ ? He's one of our github contributors.

rough furnace
#

I Think it's @harsh ravine

zealous magnet
#

Done

rough furnace
#

@wide prism need to add the #xxxx ...on "normal" sized servers, that's not an issue ๐Ÿ˜†

#

๐Ÿ‘‹ @harsh ravine

wide prism
#

Awesome, thanks lots!

rough furnace
#

Thank you @zealous magnet logo_pyqtgraph

wide prism
#

Couldn't find it...

rough furnace
#

time to take the kids to school ๐Ÿ‘‹

wide prism
#

Ah, doh... I was looking in the private messages window. The number does show up with the "@" search. Learning, learning.

wide prism
#

Sorry @rapid kestrel , just noticed that I totally ignored you there. Apologies. Long day, time zones, scatterbrained. ๐Ÿ‘‹

cedar trail
#

like, you can give an individual user permission to participate in the channel

#

I feel the latter should be done if they are not part of the org

wide prism
#

Interesting. I guess we need to figure that out. The pyqtgraph "org" is basically @rough furnace over there.

#

Rest of us are just random squids.

cedar trail
#

oh lol

wide prism
#

I'd wager a guess that some other communities are a tad larger.

#

But it's probably a good idea to invite some people in without the role first, and then assign a squid if they decide to keep hanging around. Thanks for the info, I didn't know that!

polar onyx
#

To give a bit of a more technical explanation, permissions are assigned to either roles or specific users. We can create more roles with the permission, or give existing ones the permission, or give the permission to specific users

rough furnace
#

I think I can safely say for everyone w/ the pyqtgraph role is that we don't want to wear out our welcome and we want to take every step to minimize workload on admins.

cedar trail
#

I'm not an admin, but pinging admins (or even mods) will not wear us out because we receive so many pings a day that we are not phased by it anymore

rough furnace
#

Now I don't foresee a flood of requests for giving people roles/permission to access this channel; but if there is something in this process we can do to minimize pings to you all, we'd love to do it.

wide prism
#

And DO let us know if we are doing something the annoying way ๐Ÿ˜

cedar trail
#

lol pings shouldnt be a concern Jack
I get so many pings a day by @runic umbra that it feels nice to have a human ping me once in a while

cedar trail
polar onyx
#

If adding more people is something you foresee becoming routine, we can think of some sort of arrangement

rough furnace
#

I can see a case of adding a few people a week, but I can see that tapering off, there aren't that many pyqtgraph maintainers, and not that many regular contributors....

quartz tiger
#

we can give you access to control the permissions of the channel yourself

rough furnace
#

If you're good w/ that, I'm good w/ that.

quartz tiger
#

Nice, of course we can still assist if anything goes wrong or you need help ๐Ÿ˜„

rough furnace
#

thank you so much, you all have been great

quartz tiger
#

let me just run it by the admins to make sure we're alright with that, should be fine ๐Ÿ˜„

rough furnace
#

I won't be offended if they say no ๐Ÿ˜›

quartz tiger
#

ok that's funny

#

Zig already asked in our admin chat about it ๐Ÿ˜„

#

seems like we're ok with it ๐Ÿ˜„

rough furnace
#

"great minds think alike"

#

๐Ÿ‘ so ugh, how do I manage permissions to this channel?

quartz tiger
#

I've jsut given you access

#

you should be able to right click the channel and click edit

rough furnace
#

๐Ÿ‘

quartz tiger
#

it's essentially add a role/member and then give them perms

#

My only suggestion is not to edit the everyone role on the channel

#

since that may make it public

polar onyx
#

Since everyone can send messages in the channel already, you only need to give new members read permissions

#

if you'd like to then remove them, you should have a big red button at the bottom of the permissions list for each role/user

rough furnace
#

going to read the discord FAQ ...took a quick look and I didn't notice how I actually grant a read permission to an individual ... but I'll sort that out ๐Ÿ‘

quartz tiger
#

You click the + icon next tole roles/members as a way to say, I want this role/member to have special permissions in this channel

#

find the person/role you want, add them, then tick the read messages permission

rough furnace
#

oh you mean the "add roles or members" button

#

๐Ÿคฆโ€โ™‚๏ธ

quartz tiger
#

Yea ๐Ÿ˜„

#

that doesn't add them to this channel BTW

#

that just adds them to the list of people with bespoke perms

#

you then give them read messages perm

rough furnace
#

right...got that part ,...but thanks for the clarification

quartz tiger
#

Cool cool

rough furnace
#

loosely related note, is this the largest discord server?

quartz tiger
#

not by a long shot ๐Ÿ˜„

#

There are quite a few Discord servers at the member "cap" of 800k

rough furnace
#

!

quartz tiger
#

If you click the compass icon on the left side of Discord you can see an ordered list of servers

#

you can see the largest server per category there too

#

We're the second largest Science&tech server

#

behind a gaming browser

cedar trail
#

we are the largest online Python community I believe

quartz tiger
#

Yea, we are afaik

wide prism
#

Hats off to lofi girl for 127,000 online users.

quartz tiger
#

and PySlackers has ~40k members

quartz tiger
#

iirc they did a lot of talent shows when stage channels were big

rocky furnace
#

pyslackers have probably reached their terminal velocity for growth. they had 25k members when we had 20k members.

#

we're growing at a very different pace

quartz tiger
#

A scary pace D:

#

You're gonna have to pay us more soon lemon

rocky furnace
#

yes. but it's been scary for a while and we keep managing.

rocky furnace
#

it's a Christmas miracle!

half jewel
#

... of zero lemons .. lemon_pensive

wide prism
#

Hehe... I'd certainly be scared. Lemons or no.

quartz tiger
#

almost at 300k, dang

wide prism
#

scary big numbers make brain hurt

#

Seriously though, congrats and good job!

quartz tiger
#

I'm glad we're attracting lovely people like all of you at pyqtgraph to hang out with us and get closer to the community though ๐Ÿ˜„

rocky furnace
#

i heard the president of Discord flies to your house with his private jet and gives you a second hoodie when you hit 300k

#

except this time it's not a physical hoodie it's an NFT

wide prism
#

Wait, who gives you the first hoodie then?

rocky furnace
#

they just mail that

rough furnace
rocky furnace
#

I'm still grumpy I never got one.

#

Discord doesn't acknowledge non-dictatorial discord server hierarchies

#

our triumvirate is not sanctioned

wide prism
#

๐Ÿ˜ Thanks guys, keep up the great work!
(I am off to bed for today.)

cedar trail
#

good night ๐Ÿ‘‹

rough furnace
#

๐Ÿ’ค

wide prism
#

((For some reason, I have now totally identified the "president of Discord" as Snowcrash's Uncle Enzo.))

rough furnace
#

๐Ÿ˜†

rapid kestrel
harsh ravine
#

oooh a new channel

rough furnace
#

๐Ÿ‘‹

#

most of us are on a slack workspace; we're testing the waters here after the sprint for a bit

harsh ravine
#

How does it compare so far?

rough furnace
#

personally I prefer discord myself; but would want there to be something resembling a consensus for us to permanently migrate; that said I've been on this discord server for some time, and I don't plan on going anywhere.

harsh ravine
#

Work has slowly made me start to really dislike slack

#

Integration with Perforce, Targetprocess, Zendesk, etc that constantly flood the channels with automated messages.. its just too much

rough furnace
#

yeah slacks "best" feature is also its worst feature ...

harsh ravine
#

Has there been any discussion about creating or symlinking .pyi files for widgets, gui and core?

rough furnace
#

@mortal grotto @obsidian sapphire are the two people that have that config, I've indicated I'm open to a PR to add that kind of stub file

#

right before the sprint, we pushed through a big PR that migrated our imports to follow Qt6 API standards (import widgets from QtWidgets not QtGui for example)

harsh ravine
#

Oh cool, I made a small script to stay sane that copies the files over to the pg/Qt directory. I was just wondering if there was going to be something permanent in the future.

rough furnace
#

if memory serves, that stub file was recognized by PyCharm well enough, but not VSCode, ...not sure if there is a more robust way of handling that (or hope that VSCode reads/respects stub files within a project)

harsh ravine
#

VSCode is weird. I do remember seeing an issue with the Qt.py bindings not being able to autocomplete using Jedi in VSCode

rough furnace
#

@mortal grotto @obsidian sapphire if either of you have a .pyi file you like using it and wouldn't mind sharing it, I'll try it against various editors and see how it works

#

(since I have an unhealthy obsession w/ switching editors every few weeks)

mortal grotto
#

Yeah, I'd be happy to share what I have tomorrow. I refrained from submitting a PR since I didn't know if the pyi file opened up other scopes...

rough furnace
#

it might ๐Ÿคทโ€โ™‚๏ธ I think a pyi file to get auto-complete, even if for dev quality of life is worthwhile

harsh ravine
#

The way I set mine up is pretty awful. It gives me auto complete but if I cmd+click on anything it opens the .pyi file instead of a .py

#

Still, its better than no auto complete

rough furnace
#

@wide prism

wide prism
#

3/5, would read.

rough furnace
#

๐Ÿคฃ

#

I'm scared of checking the time-stamps on slack to know how long I've been going at this

#

omg....

#

omg, it's worse than that, it's been almost an hour:

harsh ravine
#

If it's any consolation, the bullet points do look much better.

wide prism
#

How hard would it be to set the table text to normal size in the style sheet?
The failure mode here is that the text tries to be both "table formatted" and "bullet list fomatted" and sphinx fails to merge that correctly.

obsidian sapphire
#

@mortal grotto ^ that's stuff I added to the pyi file you gave me.

obsidian sapphire
#

you could probably add App: QtWidgets.QApplication, as well.

mortal grotto
#

Oh, that's in my pyi file already.

technically you would want a getattr defined in QtGui until the widgets accessors are deprecated

rough furnace
#

they already are ๐Ÿ˜‰

#

actually wait, no ...they're not, we just emit warnings

mortal grotto
mortal grotto
obsidian sapphire
rough furnace
#

downloading it and seeing if sublime text works.... just put that inside the ./pyqtgraph/Qt/ directory?

#

๐Ÿ‘

#

sublime text w/ lsp doesn't seem to recognize what's up ๐Ÿ˜ฆ

mortal grotto
rough furnace
#

wait.... in pycharm I'm not getting auto-complete either

mortal grotto
#

Oh, my bad! Put it in ./pyqtgraph, not under Qt

rough furnace
#

๐Ÿ‘

mortal grotto
#

It has to have the same module resolution as pyqtgraph.Qt. By nesting it you're effectively typing pyqtgraph.Qt.Qt

rough furnace
#

haha, was just thinking about that; anyway PyCharm auto-complete is good now ๐Ÿ‘

mortal grotto
rough furnace
#

๐Ÿ˜†

#

using the "nord" theme

#

(I frequently switch themes)

#

whops, actually using Vuesion

mortal grotto
rough furnace
#

๐Ÿ˜›

mortal grotto
#

Zorin OS does it, it's great

rough furnace
#

vscode doesn't appear to be reading the .pyi file either ๐Ÿ˜ฆ

mortal grotto
#

Mine didn't work with Pylance, but did with Jedi

Try changing your language server

rough furnace
#

was seeing something in the issue tracker about adding extraPaths bit where the pyi file(s) is/are,...but that didn't seem to work for me :/

#

seeing some libraries using __init__.pyi should we be doing that with our Qt.pyi file? (that didn't help vscode pylance auto-complete fwiw)

mortal grotto
#

Did Jedi work for you? Yeah, I wasn't sure about the easiest way to use extraPaths, but then again I am not yet heavily invested in vscode

rough furnace
#

you know, forgot to try jedi ๐Ÿ˜† will do that right now

#

it does!

#

jedi still works when I move ./pyqtgraph/Qt.pyi to ./pyqtgraph/Qt/__init__.pyi which I have a slight preference for __init__.pyi... need to test pycharm still

#

looks like pycharm works with __init__.pyitoo

#

still feel like there is some magic setting for Pylance but I'll have to do a lot more tinkering

fervent vale
#

seems like connect='pairs' would be trivial to add for enableExperimental if anyone actually cared for it. it's already done in GLLinePlotItem

rough furnace
#

I think connect='pairs' would be a really worthwhile thing to add, as I suspect future downsampling methods might make use of connect='pairs'

mortal grotto
fervent vale
harsh ravine
#

@mortal grotto Let me know if you're available sometime this weekend to talk about adding the slider to the ParameterTree. I've added it, and I think I've got the code working for all of the bindings but the slider isn't interpreting the min/max values correctly.

#

I have a few other related questions as well

mortal grotto
harsh ravine
#

No, I haven't created a pull request yet. I was hoping to at least have it working in a minimal form before doing that if possible.

#

I'm happy to open a draft so you can take a look if you'd like

mortal grotto
#

A draft would be good, but if you didn't feel like doing that yet you could also just let me know your fork. Is it already publicly available on github?

harsh ravine
#

No, its not on github. I'll create a branch for the slider and send you a link when my kid gets to sleep.

harsh ravine
#

@mortal grotto There is a slider example in the examples app, so you can see how it should actually work

rough furnace
#

A draft PR is good, I think it meets the criteria, open a PR when you're ready to have enough code to have a discussion about it

wide prism
rough furnace
#

the 1-million points use-case still made me do the blinking meme; .... if someone is trying to plot 1m points, probably would be better served by implementing a fast downsampling method

fervent vale
#

There are users who enable useOpenGL just because there's some stackoverflow code that does it

rough furnace
#

I would love to know more use-cases of useOpenGL but not use enableExperimental

fervent vale
#

I remember from before that useOpenGL ends up disabling subpixel font rendering

#

or rather, doesn't have

wide prism
#

I suspect a lot of useOpenGL is premature optimization. You are coming off Matplotlib, and are googling "how do I make my plots fast?" Then you find

#
  • pyqtgraph
  • weird optimization options that may not actually be needed in your case
#

The main downside of this is that I don't know if anybody will read the documentation on the goals and trade-offs of useOpenGL...

fervent vale
#

There was also issue #1918 with the user enabling useNumba for boolean types

rough furnace
#

oh, I should close out that issue

fervent vale
#

the actual error was not fixed

rough furnace
#

I mean, is that really an error?

fervent vale
#

but it seemed strange to me to have to fix it

#

to plot boolean dtypes, the user could change the view of the data to np.uint8

rough furnace
#

I mean, I guess it's an exception; and we should try to avoid those...

fervent vale
#

the question to me is: to what extent does the user expect the library to handle arbitrary data types?

#

and arbitrary data ranges

rough furnace
#

dtypes are tough; would definitely think we can't (shouldn't?) try and handle arbitrary ones, lots of optimization work has been put in to optimize what we can...

#

for ranges, i'm generally of the mind-set we should try and make stuff work as best possible, a value range is tough to predict; ... and we've taken steps to try and avoid weird cases (like avoiding qFuzzyIsNull)

fervent vale
#

issue #1964 is also strange to me too... the user doesn't want to change their data prior to sending it to ImageItem

#

nevermind that ImageItem itself might make many memory copies of their data...

rough furnace
#

it's tough to plan for people's workflows like that; ...no doubt plenty of people mid-understand the constraints they're under; or attempt to do pre-mature optimization... vs. a real world effect. I'm good knowing we won't be able to cover all use-cases, and especially in the case of #1964, users may need to do a little pre-processing

#

I suspect @wide prism is right, people are using useOpenGL as a form of pre-mature optimization; I can see myself doing that.

This is partly why I'd like to document the benefits/downsides of each of those options

wide prism
#

#1964 seems like a valid misunderstanding of the implementation. The colormaps do promise that there is a "repeats" mode... It isn't the most unreasonable expectation that this is there for using the color map for false color images.

#

If that's what you are doing, then it would indeed be nicer to have the internal colormap lookup use adjusted_index % color_map_length rather than reconditioning the bitmap every time...

fervent vale
#

my understanding of the lookup functionality of ImageItem is to use it to map some range of values A to some other range of colors B.

#

It is not to use A as an integer index into B.

wide prism
#

Yeah, sorry, that was oversimplfied. Although I think Nathan is also trying to abuse it in that way ๐Ÿ™‚

What I meant was that if the value range 0 to 1 maps to the color range, then 1.5 could map to the same value as 0.5 does. This is - I think - what the color map itself does when you ask it to repeat.

This doesn't translate to ImageItem, because this does not use the ColorMap lookup functions, it uses the LUT directly.

#

A perfectly "do-what-I-want" version of ImageItem would replicate that behavior. But I wouldn't exactly rate that as a "must have". Or even as a "would be nice".

But in case you see a neat way to implement a flag to add this behavior to the internal lookup, then we could have a plasma demo in the examples, though ๐Ÿ˜ตโ€๐Ÿ’ซ

fervent vale
#

but the notion of setLevels itself is to clip the data to get a good contrast

wide prism
#

Well, that's why ColorMap calls that CLIP mode. But there is also

#
Parameters
----------
mapping: int or str
  Sets mapping mode to
  - `ColorMap.CLIP` or 'clip': Values are clipped to the range 0 to 1. ColorMap defaults to this.
  - `ColorMap.REPEAT` or 'repeat': Colors repeat cyclically, i.e. range 1 to 2 repeats the colors for 0 to 1.
  - `ColorMap.MIRROR` or 'mirror': The range 0 to -1 uses same colors (in reverse order) as 0 to 1.
  - `ColorMap.DIVERGING` or 'diverging': Colors are mapped to -1 to 1 such that the central value appears at 0.
#

I'll say that I haven't yet found the need to apply these to an ImageItem. But the operations themselves would seem to be well-defined even in that case.

fervent vale
#

It would then be repeating the range of values set by setLevels to be well-defined

wide prism
#

(Except for diverging, which I find to be uncomfortable because it changes the basic mapping over the 0 to 1 range)

Yes. If REPEAT mode is active, and the range is 1000 to 1562, then the value 1564 is the same as 1002. Next loop is 3126: same again.

#

I am not good at coming up with pseudo-code for this, but if the normal lookup is with clip( val,0.0, 1.0), then repeat would look up with val - floor(val) ?

fervent vale
#

Incidentally, the last example that I gave for issue #1886 has plotting artifacts if I change the span to span=(49.999,50.001)

#

instead of just 2 colors divided at 50, it becomes a repeating band of red and green

wide prism
#

Interesting...

fervent vale
#

that's what you get for abusing the system!

wide prism
#

ouch

#

I think it makes a gradient bar over 49.999 to 50.001, so length of 0.002. The internal coordinates of that run 0 to 1 to map colors.

#

It seems to break around 15 or so... that is... ~7500 in internal coordinates? No idea why it would overflow at that point ๐Ÿ˜ฆ

#

I was expecting it to be 65,536 or something.

#

... See? It's all repeating anyway ๐Ÿ˜†

#

I really liked your example there; I have been wondering if there is a way to conveniently set a colormap with a hard break like that.

#

I was expecting the next complaint to be that if you zoom in far enough, you can actually see the red-green interpolation gradient.

harsh ravine
#

At this point I feel like I'm not sure what the goal is for this PR anymore

wide prism
#

Sorry about that.
I am always pushing towards a better color implementation, but I won't claim that I know how the pieces fit together.

#

I have been meaning to test-run your PR, but I keep getting interrupted by work and stuff.

#

I think we don't want to hard-code color values in the GroupParameterItem if we can avoid it.

#

But we certainly don't want to hard-code a palette that is different from what we have now, and I am pretty sure the comment did not mean to say that.

fervent vale
harsh ravine
#

It's not your fault.. There have been so many comments on the PR its hard to keep track of what the current goal is. I took the comment I linked above, and the back and forth you and I had to mean I should detect dark mode and set the palette on the app if darkMode is active

#

There's 0 difference when applying the palette with a QDarkStylesheet

#

I looked into their code and they are actually changing the palette slightly

wide prism
harsh ravine
#

Their stylesheet is so thorough that any palette is completely overridden.

wide prism
#

Yes. That was what I found before. If I then go and try to use the palette for an item NOT covered in the qdarkstyle sheet, then it is totally wrong.
Maybe they improved that recently.

#

Pulling the colors from the stylesheet seems to be hard. So I wouldn't recommend that for your PR.

#

Pulling colors from the palette is easy, and could be used in a lot of other places, too.

#

So, without TRYING to derail your PR, this would be a good opportunity to move the GroupParameterItem to use a sane, palette based color lookup.

#

The rest of the discussion results from that. Some touch-up to the palette is required on some system configurations, otherwise we are in the same place as where we started: GroupParameterItem looks like some insane combination of light and dark mode.

#

You are on Mac?

harsh ravine
#

I am

wide prism
#

Does your QApplication automatically have a different (and reasonable) QPalette in light and dark mode?

#

((I already know that alternateBase is weird))

harsh ravine
#

Yeah, the only real difference is that the group items have the color of whichever alternating color row they are on instead of the outermost being a slightly different color than the groups it encloses

wide prism
#

So what is the original bug, then? There it seemed like some cells rendered white background in a dark scheme.

#

I am on Windows, nothing changes color without pushing it.

harsh ravine
#

The original bug was caused by hardcoding the colors, when mac goes in to dark mode, it does weird things, dark roles become lighter.

#

The easiest thing to do to solve only the groupParameter problem would be to pick some colors for both light and dark themes and hard code them exactly like they were before.

wide prism
#

what exactly changes on Mac? Is that reflected in the application QPalette or not?

harsh ravine
#

If we want to stick them in a palette to grab them, I'm fine with that

wide prism
#

How does the rest of the stuff know to change color? Qt has hard-coded colors, stylesheets and the palette.

#

Does any of that change, or does every pyqtgraph widget detect the darkmode flag and set manual colors based on that?

#

Do your QLabels and QLineEdits change color in darkmode?

#

What I am hoping for is that the application's palette does what the documentation seems to promise: Automatically hold a palette of colors that works with your system. And ideally works with dark mode / light mode...

#

It doesn't really do that on Windows, but I mean, that's Windows...

harsh ravine
#

So this is with no palette in dark mode

#

This is when a set the background role on app.palette to #111

wide prism
#

What are the baseColor and textColor roles in dark mode? What are they in light mode?

#

What you are showing is that the applications DOES rely on the palette to have a dark background role in dark mode.

#

That means that this basically seems to be working: The palette goes dark, and some elements automatically change to be dark.

#

Other elements are (annoyingly) hard-coded to ignore the palette and set "seemed-like-a-good-idea" fixed color values.

harsh ravine
#

dark
#1e1e1e base
#ffffff text
light
#ffffff base
#000000 text

wide prism
#

โค๏ธ

#

I think that makes the goal of your PR the following:
Derive some colors from the palette that make the GroupItem look good <on MAC> in both light and dark modes.

#

I think you want to grab the baseColor and push it a little towards gray to make the alternate color. That should work with both light and dark schemes, and with any actual base color that the user might set.

#

alternateBase would have been nicer, conceptually, but it seems that Qt and or Mac OS disagree with us on what that color would be good for.
What you showed there on github (thanks!) is not usable.

#

There is a separate PR here (which leaked into yours):
Now that things on Mac use the palette correctly, we need to make this work on Windows again. On Windows, you get "dark mode" typically by applying qdarkstyle.
Which stupidly leaves a light mode palette in place. So if we catch that, and fix up the palette ONLY in that case, things should work nicely.

Once we get bug reports from other platforms, we add palette fixes there, too ๐Ÿ˜†

#

Err... Does any of that make sense?

harsh ravine
#

Yeah... Sorry, I was just thinking how I could change the items in both light and dark mode without changing anything but a modifier. I think using HSV might be the best way, like you suggested.

wide prism
#

I think that is reasonably simple because Qt already has all the functions in QColor. The first thing I would try are to move L in HSL or V in HSV toward 0.5

harsh ravine
#

I still don't understand why this behaves the way it does

#

alternate base is #989898, which is clearly not that color

#

but if I set the background on the groupItems

#

It turns to #989898

#

the background using alternate base

wide prism
#

Normal widgets don't have a background, they are often transparent.

#

You might be seeing some other background

#

How do you set the background?

harsh ravine
#

If I specify the base and alternate base after creating the app the colors are consistent.

#

Its a treeWIdgetItem that is getting the background, I don't think thats a QWidget but I'm not 100% sure

#

I just don't understand why when there is no palette set, qt doesn't use the base and alternate base for the items

wide prism
#

Is that possibly related to manual darkmode overrides?

#

mkQApp sets that flag on startup, looking at the palette base color, I think.

harsh ravine
wide prism
#

And then it turns the color that you set? Or it turns a DIFFERENT color?

harsh ravine
#

I don't think so, I've tested with QtWidgets.QApplication([]) also

#

It turns the color I set, which is alternate base, the light gray color.

#

when there is no specific palette set on the app, the alternateBase is no where to be found in the tree

wide prism
#

Makes sense, because it is ugly.

harsh ravine
#

thats with no palette

wide prism
#

Ok...

#

By the way, the double labels on the buttons are a different bug, right?

#

...and if you re-apply the same palette, colors change???

harsh ravine
#

Yeah, the buttons in dark mode are transparent and the itemWidget that the button is within has the same text

wide prism
#

but we shall ignore that for now, right?

harsh ravine
#

we know what the problem is and a couple of different ways to get around it

#

If I ever finish this I'll do that ๐Ÿ˜…

wide prism
#

My interpretation of the behavior I have seen so far is that out of all the pyqtgraph-provided items, nothing uses alternateBase. So if you change alternateBase in the palette, nothing should change color. If it does, I need to update my working theory.

harsh ravine
#

Yeah, I guess they actually don't, and thats whats confusing.. The docs say that the alternateBase is what is supposed to be used for tables/trees/lists with alternating row colors

wide prism
#

The docs also say "QPalette::Dark 4 Darker than Button." which wasn't true last time I tried.

#

QPalette is not used very much by the Qt devs, it seems to me.

#

Here's the theory:
pyqtgraph should be using the palette, but instead colors are hard-coded all over the place.
Goal: Fix it.
Today's goal: Fix the tiny litle bit of the large problem that is in GroupParameterItem ๐Ÿ˜

harsh ravine
#

Its just inconsistent between color modes

wide prism
#

modes = light / dark?

harsh ravine
#

dark is the example parameters there

#

and also here

harsh ravine
wide prism
#

"dark" is the "dark"color role?

harsh ravine
#

I assume because button is transparent here

#

yes, palette.button and palette.dark

#

This is what I meant when I said in dark mode some color roles change the behavior

wide prism
#

"dark" is not a background color, I think. QPalette.dark() returns a brush, not a color. So whatever the devs have in mind for that, we are probably using it wrong.

harsh ravine
#

Its supposed to be used for button bevels/shadows iirc

wide prism
#

Highlighted text is supposed to be "HighlightedText" on "HighLight" background.
This seems to be drawing "textColor" on "Dark", which isn't a combination anybody promised would look decent.

#

I would promise that this was coded before anything actually did dark mode. And it -randomly- happens to look decent in light mode. And then it didn't look terrible enough in dark mode for anybody to change it.

harsh ravine
#

Oh, absolutely.. I'm pretty sure it hasn't changed since before Qt4

wide prism
#

You might still be assuming there is some grand plan. But it's squids all the way down. logo_pyqtgraph

harsh ravine
#

yeah I'm slowly learning that ๐Ÿ™ƒ

wide prism
#

You can either ignore the "dark" color. Or you can change it to something more reasonable and robust, as long as it does not look MORE TERRIBLE than the current version.

#

I'll back you up, although usually @rough furnace makes the merge decisions.

harsh ravine
#

Yeah, I'm going to get it done here with in the next 30 minutes.

#

What do you think about using html color names?

#

seems like it would be less messy than converting and modifying the lightness

wide prism
#

But wouldn't you still be hardcoding colors in that case?

#

Assume that in the future I want to set a palette on my application and see it actually work ๐Ÿ™‚

#

...and my palette might be monochrome green or retrowave teal and purple.

harsh ravine
#

well you and your PR make a good point

wide prism
#

Hmm. Did I never screenshot the later version? Anyway, like so:

#

The text bits are still boring, they should be able to work with a weird palette, too.

harsh ravine
#

that's going to be an awesome feature

wide prism
#

It breaks so many things that I don't know if it will ever work... Dreams, man, gotta have dreams! ๐Ÿ˜Ž

harsh ravine
#

Suggestions for either one?

fervent vale
#

If I understand correctly, the setStyleSheet override would only be visible to Python, not to the C++

harsh ravine
#

All of the changes to mkQApp have been reverted.

wide prism
#

That's part II now ๐Ÿ™‚

@fervent vale , the goal would be to react to the user specifically setting a stylesheet, would it catch that?

#

We do not need to react to anything Qt does internally, we want to read the user's mind if they apply a dark mode style.

fervent vale
wide prism
#

Thank you for the clarification. I am dumb and have no idea what I am talking about. ๐Ÿ˜

#

Do you have other concerns where this kind of override might cause us trouble?

wide prism
fervent vale
#

There seems to be a few issues listed on PYSIDE issue tracker concerning QApplication

#

I think it was something about there being a single C++ QApplication instance, but the Python side might have more than 1 wrapper to it

#

So if you assigned a Python attribute to the Python instance of QApplication, is it really going to be visible to everyone

#

That's all hearsay on my part, I haven't encountered it since I steer clear of such things ๐Ÿ˜†

#

So in pyqtgraph, we assign the QApplication instance to QAPP. If the user always accesses QApplication via a call to mkQApp, then that should be clear of any such issues

wide prism
#

Do you happen to have a good alternative suggestion how to catch the user applying a stylesheet?

I think we can ask the user to keep the main qApp object around if they want later stylesheet updates to work.
I mean, they can already totally break that part by not using mkQApp...

harsh ravine
#

There is an event we can watch but you have to patch an eventFilter onto the QApp

fervent vale
#

I recently found that PyQt would crash if one instantiates a QApplication using QtWidgets.QApplication() and then not hold a Python reference to it

wide prism
#

I have to admit that I didn't even know that mkQApp did stuff outside of conveniently accessing Qt. None of my own programs use it so far...

#

Breakage with garbage collected Qt objects seems fairly normal. I had some fun time with QTimers before.

#

I think we can steer users towards mkQApp.

#

@harsh ravine , did you update the PR? I'd like to check later how badly it breaks on Windows.

harsh ravine
#

Oh, no I haven't. Check back in a couple of minutes.

harsh ravine
#

sorry I realized I ran a code cleanup in qt/__init__.py so I had to put all the trailing whitespace and empty lines back before committing

#

it should be there now

#

@wide prism could you test with qdarkstyle if you have it installed. I'm not 100% sure if what I did there is going to work on every platform.

wide prism
#

I will, but I have some non-programming things to do first.

harsh ravine
#

no rush!

wide prism
#

hehe, maybe we have some more work to do.

#

Another interesting thing: The QDarkStyleSheet has a length of 50355 characters.
I think we might not want to run a full text search against that three times per update ๐Ÿ˜

#

How does the collaps button work on Mac?

#
self.collapseBtn = PathButton(path=self.openPath, size=(12, 12), margin=0)
self.collapseBtn.setStyleSheet("""
border: none;
""")
self.collapseBtn.setPen('k')
self.collapseBtn.setBrush('w')
rough furnace
#

Good morning everyone; looks like I have some reading to do

wide prism
#

๐Ÿ‘‹

rough furnace
#

ok, .... i'm soooo glad there seems to be some kind of confusion on the "correct" implementation for this fix among everyone else, not just me

#

more important than the length of the qdarkstylesheet is that I don't believe the style-sheet string "language" conforms to a "regular language" which will make regular expressions not a particularly great tool

wide prism
#

Well, we are only trying to detect the name of the stylesheet.

#

i.e. if '/* QDarkStyleSheet' in stylesheet:

#

Windows, with QDarkStyle and patched up application palette:

#

Without palette and stylesheet:

rough furnace
#

that looks good! is this the PR in its current form?

wide prism
#

No, current form is the four-panel image above ๐Ÿ™‚

rough furnace
#

o; yeah...

wide prism
#

Hmm... How do I live dangerously and patch the setStyleSheet call in mkQApp?

def patched_setStyleSheet(self, styleSheet):
    print('hi! I have been patched!')
    if '/* QDarkStyleSheet' in styleSheet[:512]:
        print('this is QDarkStyle!')
        self._setStyleSheet(styleSheet)
        # QAPP.setStyleSheet(styleSheet)
           
original_setStyleSheet = QAPP.setStyleSheet
QAPP._setStyleSheet = QAPP.setStyleSheet
QAPP.setStyleSheet = patched_setStyleSheet.__get__(QAPP.setStyleSheet, QtWidgets.QApplication)
QAPP._setStyleSheet = original_setStyleSheet
#

works, as far as getting called, but I cannot call the original setStyleSheet from there: AttributeError: 'builtin_function_or_method' object has no attribute '_setStyleSheet'

#

The commented out QAPP.setStyleSheet(styleSheet) line seems to work, but that seems a little beyond the level of crazy I wanted to sink to today.

rough furnace
#

dumb question; why do we need _setStyleSheet to be a method of QApp? can we not pass the QApplication instance into a general function (basically we don't want to modify class attributes of QApplication instances if I remember right

#

oh, ...we have to do that or else we don't intercept the setStyleSheet calls ... yeah that's a problem

#

and we can't catch/intercept the events because we're not subclassing QApplication either...

wide prism
#

There's even a comment that says stuff blows up if we do.

rough furnace
#

generally messing w/ QApplication outside of the Qt API has been risky if memory serves (might be better now that we've deprecated Qt4 and Qt < 5.12 support)

#

We might want to open an issue on the qdarkstylesheet repo and ask them for input

wide prism
#

This works for me

#

pijyoi's interpretation is that the patch will probably not be valid if another instance of app is retrieved through app = QtWidgets.QApplication.instance()
But it might work as long as the user holds onto the original app returned by mkQApp, at least until the stylesheet is applied.

Note that we don't need to patch the internal calls Qt might make. The only thing we want to know is if the USER has called the python wrapper to setStyleSheet().

#

@harsh ravine , if you want to have a look, the only change needed in the ParameterTree example is to add

import qdarkstyle
app = pg.mkQApp("Parameter Tree Example")
app.setStyleSheet(qdarkstyle.load_stylesheet())
rough furnace
#

let me see what this looks like on macOS with light/dark mode

wide prism
#

Let me know if I need to do anything to the code on my fork. I don't want to steal Chris's credit by posting my own PR.

rough furnace
#

ok ok, that's an easy fix...

#

what happened is those fields didn't update when the palette changed...

#

but when I loaded the example when I was already in light mode, it looks good

#

when launched w/ system already being in light mode

wide prism
#

No Mac, won't fix. ๐Ÿ˜

#

Are you switching that on the fly?

rough furnace
#

the first two involved switching on the fly while starting in dark mode

#

you can detect the change by tying into the qapp.paletteChanged signal

#

we do this w/ the Example App

wide prism
#

Wait, did that ever work before?

#

I mean, on GroupParameterItem?

rough furnace
#

hmm... good point, probably not, let me check

#

(starting in dark, changing to light)

wide prism
#

Weeeeelllll......

rough furnace
#

@wide prism w/ QDarkStyleSheet does the example app look ok?

wide prism
#

The example app? Never tried that. probably not. I'd have to manually add that to the python file, too.

#

forgot to set darkMode property ๐Ÿ™‚ updated my fork

rough furnace
#

if we have custom widgets with manually encoded colors, we should try and update the colors with changes of the QApplication palette, lucky with the paletteChanged(QPalette) signal this is not too difficult to do.

#

but handling the stylesheet change stuff is another beast :/

#

(and that's certainly something I can help with if @harsh ravine would like my help with)

wide prism
#

Then let's not support complicated stylesheet stuff.
Require the user to supply a decent palette (works on Mac), use one of a limited number of recognized stylesheets (works for QDarkStyle), or manually select our dark palette (goes on the todo list).

rough furnace
#

yeah; I'm good w/ breaking this up into 2 parts, handle light/dark palettes, and changes, then reaching out to QDarkStyleSheet maintainer(s?) for help w/ integrating from there

wide prism
#

The palette update is really easy now, since there is no light/dark mode specific code in the GroupSomethingItem anymore. You just need to rerun the color setting.
Can you rig something up for that, maybe?

  • I am terrible at writing code I can't test
  • I need to get up for work in five hours
rough furnace
#

haha you go to bed ๐Ÿ˜›

wide prism
#

I think we don't need anything from QDarkStyle. Maybe they could put the name of the stylesheet somewhere into the first characters...

#

If we want to rip the palette from the stylesheet, we need a CSS parser; which probably exists. It would only need to run on a setStyleSheet call, so it can be slow.
Then we pull colors into the application palette and use that.

Medium term development goal is to turn off the stylesheet and make things work with just the palette on Windows.

#

Right now, the buttons break in that case:

#

But the buttons are also broken on Mac, so that needs looking at anyway.

fervent vale
#

I think setting methods on the class should work. Setting methods on the instance is unknown

wide prism
#

I have this now

def mkQApp():
    QAPP = QtWidgets.QApplication.instance()
    # code of mkQApp, illustration only up here
    def patched_setStyleSheet(self, styleSheet):
        QAPP._setStyleSheet(styleSheet) # I would rather call this as self._setStyleSheet, but that fails
        if '/* QDarkStyleSheet' in styleSheet[:512]:
            # print('this is QDarkStyle!')
            app = QtWidgets.QApplication.instance()
            palette = app.palette()
            if palette.base().color().lightnessF() > 0.5:
                # need to fix light palette background in dark style sheet
                app.setPalette( dark_QPalette() )
                app.setProperty('darkMode', True )
    QAPP._setStyleSheet = QAPP.setStyleSheet
    QAPP.setStyleSheet = patched_setStyleSheet.__get__(QAPP.setStyleSheet, QtWidgets.QApplication)

If you have some pointers how to make this a little more robust, they would be very welcome!

#

Good night! ๐ŸŒ™

#

(sorry, hope the indents make more sense now)

#

It seems that we are already propagating the 'darkMode' property through the QtWidgets.QApplication.instance() ,but since that really only works on Mac, it probably isn't a good global test.

#

(in __init__.py, somewhere around L450)

fervent vale
#

Could the monkey patching not follow the style of QGraphicsItem.scale done earlier up in the same file?

#

I.e. modify the class not the instance

#

That seems to have worked

#

Although QApplication is special

rough furnace
fervent vale
#

Is the scope to cover such a case or only to cover cases where the application was instantiated via mkQApp?

rough furnace
#

I think everything in the library right now works with existing instantiations

fervent vale
#

Does QAPP.setStyleSheet = types.MethodType(patched_setStyleSheet, QAPP) work in lieu of using __get__?

harsh ravine
# wide prism hehe, maybe we have some more work to do.

In the upper right hand image, QDarkStyle is loaded, so maybe windows handles the transparent background different than macOS does. That doesn't really explain why the text is black though. The foreground text is set to almost pure white when the dark stylesheet is loaded.

harsh ravine
wide prism
harsh ravine
#

touchรฉ

#

If we're concerned about user created stylesheets then shouldn't we be doing a basic check to see if there is a non-qdarkstyle stylesheet and opt not to change the bg/fg colors if there is?

wide prism
#

I think the latest code specifically looks for QDarkStyle, and only makes changes if that is found. Ideally we would parse the style sheet to extract colors, but that may be hard.

harsh ravine
#

What would we be looking for specifically?

wide prism
#

In parsing the style?
I think that is a few steps in the future. A recurring pattern of background-color and color, I guess.

But I think it is probably more productive to let our own widgets be styled by stylesheet. I hope Qt would mostly do the parsing for us in that case.

harsh ravine
#

hmm, alright.

#

I'm kind of confused by the picture in the bottom left corner. The text color was set to #F0F0F0 when a dark stylesheet is detected. I'm curious why that wasn't applied for windows but is for mac.

wide prism
#

I think your logic was upside down.

harsh ravine
#

The only thing I could think of is the background is set to a color with 0 alpha, but I wouldn't think that would change the appearance of the FG brush

wide prism
#

It applied black text when it detected QDarkstyle. On Mac, there is no stylesheet, and it left the colors alone.

#

Sorry, have to run to work now

harsh ravine
#

hmm, I'll look at the PR

rough furnace
#

@fervent vale I may have been mistaken on the instantiation bit. I believe the hidpi settings won't work if QApplication was instantiated before PyQtGraph got imported

harsh ravine
# wide prism I think your logic was upside down.

I commented the important parts of the PR explaining what should be happening when a qdarkstyle stylesheet is detected. Which part is upside down?

# set textColor to None so we can `or` with it later
textColor = None 
if '/* Light Style' in stylesheet or '/* Dark Style' in stylesheet:
    # either a dark or light QDarkStyle stylesheet was found
    # regardless of which one was found - set full transparency on the background brush
    background = QtGui.QColor(255,255,255,0)
    altBackground = background
    # Assume the stylesheet is the LightPalette stylesheet and set a dark text color
    textColor = QtGui.QColor('#000000')
    if '/* Light Style' in stylesheet:
        # If the stylesheet is the DarkPalette, apply a light text color 
        textColor = QtGui.QColor('#F0F0F0')
    ...
   if depth == 0:
        background = altBackground  
    ...
   # set the background brush to transparent 
   self.setBackground(c, background)
   # since we assigned a text color for both versions of the style sheet
   # the palette.text().color() is only applied if the elif/else run
   self.setForeground(c, textColor or palette.text().color())
harsh ravine
#

This is how everything looks on macos with the code from the PR

fervent vale
#
from PyQt6 import QtWidgets
import types

_setStyleSheet = None

def monkey_patch(text):
    global _setStyleSheet
    def setStyleSheet(self, sheet):
        print(text)
        _setStyleSheet(sheet)               # already bound
    qapp = QtWidgets.QApplication.instance()
    _setStyleSheet = qapp.setStyleSheet     # already bound
    qapp.setStyleSheet = types.MethodType(setStyleSheet, qapp)

app1 = QtWidgets.QApplication([])
monkey_patch('HEY')
app2 = QtWidgets.QApplication.instance()
app2.setStyleSheet('')
#

this is essentially the same as what Nils showed, except that the old bound method is stored within the module

fervent vale
#

(In some other C++ development, it was really annoying that merely linking to some library caused side effects)

harsh ravine
#

I had a similar function in the previous PR but it was using the application instance. What is this going to be used for?

fervent vale
harsh ravine
#

ohh, gotcha. I didn't run into any issues when testing either.

#

It would sure be nice if we were able to subclass the app

fervent vale
#

Oh, the comment about the crashing if we subclass was added by me

harsh ravine
#

Ah, you saw it happen?

fervent vale
#

The thing was that, not all the examples crashed

#

It took a long time before it was pinpointed to the subclassing

harsh ravine
#

oh, so some worked? Do you remember any specific ones that worked or crashed?

harsh ravine
fervent vale
#

As I recall, it started crashing regularly on program close with Python 3.9 series and the later versions of 3.8

#

So one of the first times I encountered it was on ArchLinux on the Raspberry Pi, which is more bleeding edge.

#

So at first I just thought it was because it was running on the RPI

harsh ravine
#

hmm, by chance did you try a signal handler before removing the subclass?

fervent vale
fervent vale
#

Maybe it's an implementation issue/detail with PySide2

#

In any case, PR 1605 now ensures that each example ends normally, so the CI will detect the crashes

rough furnace
#

@wide prism is unable to login here to contribute to the discussion due to technical issues, he'll be back in 12-13 hours

harsh ravine
#

I spun up a windows VM to test my PR and it looks just like it should ๐Ÿ˜

harsh ravine
#

The way I see it, the signal would have to come from the treeWidget. setting one up is no problem, but I'm not sure about how to call updateDepth from with the signal from the tree, as it needs a depth.

rough furnace
harsh ravine
#

Oh, yeah... that part is no problem. I set it up in groupItem without thinking about it and it kept toggling dark mode on and off ๐Ÿ˜…

#

I suppose I just need to think of a better system to track when and how the darkMode property has been set

rough furnace
#

Oh nice, thought that's what you were referring to

harsh ravine
#

Anyway, you can go back to your evening, I'll figure something out!

rough furnace
#

I will be active here in a bit, have kids climbing me and otherwise bouncing off the walls

harsh ravine
#

I know it all too well

rough furnace
harsh ravine
#

I had to run to the store, so not much has changed.

rough furnace
#

second kid is in bed; i think those windows screenshots look fine; if it handles macos light/dark mode, and the switch between them, is that effectively "everything" or is something else missing?

harsh ravine
#

So, I think I need to set a flag on each item in the method that the paletteChanged signal connect to so I can check for that flag in the updateDepth method to let me know that we need to update the colors

#

... or something..

rough furnace
#

most things handle changes in the system palette; just the stuff we hard-code colors for

#

so like, if the alternateBase color worked as we thought it should, we could assign that and call it a day

#

(that still surprises me so much that that didn't work...)

harsh ravine
#

Yeah, I should probably start looking at the source code for Qt as soon as something seems weird. It would probably save me a lot of time in the long run

#

Did you have a chance to test the most recent PR on Windows?

#

I'm not sure what was going on with Nils but when I tested on windows everything looked just like it did on the mac

#

the copy of windows wasn't activated so I wasn't able to change the themes or colors, so it could have something to do with that if he's customized the colors

#

So, I have the palette change working now.. but when the theme changes colors the items text are shifted down

harsh ravine
#

Okay, well I guess that's working now.

rough furnace
#

@wide prism when you get back, can you check @harsh ravine 's PR on windows? sorry I got a bit tired, if you don't hear back tomorrow morning I'll fire up my windows machine and check things out, but yeah, things look great from the screen shots!

mortal grotto
#

Sorry @harsh ravine I was hoping to check out your branch this weekend but real life interfered... Is it OK if I keep this on hold for a few more days? I promise I haven't forgotten!

harsh ravine
#

No worries. Just let me know what you think after you've had a chance to play around with it.

harsh ravine
#
from PySide2.QtWidgets import QApplication, QPushButton


class App(QApplication):
    def __init__(self,l):
        # QApplication.__init__(self,l)
        # super(App, self).__init__()
        super().__init__(l)
def fn():
    # global app
    app = App([])
    button = QPushButton("Push")
    button.show()
    button.clicked.connect(app.quit)
    app.exit(app.exec_())

if __name__ == '__main__':
    fn()

@fervent vale if you run this, python will segfault, if you uncomment the first line in the function, it exits with code 0

fervent vale
#

I tested a slightly modified version of your script against all bindings and only PySide2 crashes. The thing is that previously pyqtgraph already held a global module reference QAPP to the instance. And the order of destruction of module level variables is undefined, if I understand correctly

#

So the end result was that which examples crashed or not on exit was dependent on the python interpreter version and also on what things that example had done. For a fixed python interpreter version, it was reproducible as to which example would crash

#

So yes, it seems like a PySide2 issue, and even if it has been fixed, users will be stuck with the version on PyPi

harsh ravine
#

It would make sense why the error only happened on certain versions and on pyside

wide prism
#

Hi, back from work ๐Ÿ™‚

wide prism
# harsh ravine I commented the important parts of the PR explaining what should be happening wh...
if '/* Light Style' in stylesheet:
# If the stylesheet is the DarkPalette, apply a light text color 
textColor = QtGui.QColor('#F0F0F0')

Sorry, on my system, I didn't find the terms "Light Style" or "Dark Style" in the style sheet. Maybe my version is outdated?
So I adjusted the test, but I assumed that the term "light style" would show up in a light mode palette, where the text color should be dark.

wide prism
wide prism
# fervent vale I think it would be preferable not to monkey patch if the QApplication has alrea...

I would agree with only applying the patch as part of QAPP creating in mkQApp. Setting up everything by yourself should be a supported option.

If we are unsure that the monkey patch is safe, then there is also the option to simply provide a function or parameter such as mkQApp(style='dark') to let the user conveniently set a usable palette.

Then we just need to figure out how to document that so that it's easy to find when the app ends up in mixed colors.

rough furnace
#

I should point out that QDarkStyleSheet does have docs in their README with how to use their sheet with pyqtgraph specifically, we could certainly make a PR with them to update those instructions

wide prism
#

I am not giving up on the monkey-patch just yet.
But agreed. Patching up the qapp to intercept style sheet changes is an optional bonus feature.

The main point would be to give the user a simple, one-line way to set a usable palette on systems where that is not automatic.

harsh ravine
harsh ravine
#

The line it checks for should be on line 10 of the stylesheet.

#

@rough furnace Do you want the palette changed fix to be part of the current stylesheet shenanigans PR or separate?

rough furnace
#

I feel bad that this happened on your first (or second?) PR

harsh ravine
#

ahh it's ok stuff like this happens sometimes

#

I'll keep it in the current branch since it relies on updateDepth where the colors are applied.

wide prism
rough furnace
harsh ravine
wide prism
#

Interesting!

#

By the way, the stylesheet that I read back from the qapp starts like like:

#
/* ---------------------------------------------------------------------------
    Created by the qtsass compiler v0.1.1

    The definitions are in the "qdarkstyle.qss._styles.scss" module

    WARNING! All changes made in this file will be lost!

--------------------------------------------------------------------------- *//* QDarkStyleSheet -----------------------------------------------------------
This is the main style sheet, the palette has nine colors.

It is based on three selecting colors, three greyish (background) colors      
plus three whitish (foreground) colors. Each set of widgets of the same       
type have a header like this:

    ------------------
    GroupName --------
    ------------------

And each widget is separated with a header like this:
#

Is that what you are also seeing? I tried running an update, but I am on the conda version, so that might be behind, too.

harsh ravine
#

hmm, thats a different qtsass compiler version than mine. I'm not sure if thats from Qt or QDarkStyle

#
/* ---------------------------------------------------------------------------

    WARNING! File created programmatically. All changes made in this file will be lost!

    Created by the qtsass compiler v0.3.0

    The definitions are in the "qdarkstyle.qss._styles.scss" module

--------------------------------------------------------------------------- */
/* Dark Style - QDarkStyleSheet ------------------------------------------ */
/*
wide prism
#

So... the conda version is behind, and is on a version that does not know about the Light Style verson yet.

harsh ravine
#

this is so much fun! ๐Ÿ™ƒ

wide prism
#

This is the worst part of the library to pick for working on. I don't think anything else is different across OSs / versions AND bindings.

#

How often does the styling code run in the widget? Looping over a 50k stylesheet once during setup is no problem, but I'd feel a little guilty about doing that every redraw.

harsh ravine
#

It's better for me to work on than someone else thats more familiar with pyqtgraph who could spend their time adding useful functionality

#

I fixed that part of the code

wide prism
#

Hehe... Instead you've got everybody bound up looking at this, mentally coming up with their own solutions ๐Ÿ˜†

harsh ravine
#
textColor = None
if self.styleSheet:
  background = QtGui.QColor(255, 255, 255, 0)
  altBackground = background
  if self.styleSheet == 'Light':
      textColor = QtGui.QColor('#000000')
  else:
      textColor = QtGui.QColor('#F0F0F0')
.....
.....
    @cached_property
    def styleSheet(self):
        stylesheet = mkQApp().styleSheet()[:500]
        if not stylesheet:
            return None
        palette = None
        if "/* Light Style -" in stylesheet:
            palette = 'Dark'
        elif "/* Dark Style -" in stylesheet:
            palette = 'Light'
        return palette
wide prism
#

What do you think about just getting the user to tell us what style we are on?

#

The more the detection escalates, the less I like having it in each graphical item that needs it.

harsh ravine
#

I also changed it so the if/else in updateDepth so it makes sense

#

hmm, i'd like to not have to run the check, but it only needs to one the one time

#

with the way the code in updateDepth is right now we'd still have to check what colors to use based on what the user inputs

wide prism
#

Can I see the latest updateDepth code on github?

harsh ravine
#

and I don't know how we could deal with what happens if they don't

#

sure, just a second

wide prism
#

I am now tending towards

#
  • fail fast and ugly
  • have a very google-able one-line fix in the docs.
#

We need a summary of what breaks down where. I think

harsh ravine
#

the code is up

wide prism
#
  • Everything works on Windows / PyQt5, but is always light mode.
  • Everything works on MacOSX / KDE / Windows+Pyside if we pull from the palette.
#

What breaks is using QDarkStyle by itself, but we can make that work by setting a palette, and we can document that - both in our docs and the QDarkStyle docs, which already has a specific section on pyqtgraph.

harsh ravine
#

I can test more with PyQt5, but everything on mac works. OS Dark/Light themes and Dark/Light with QDarkStyle(at least with pyside2) and everything on windows works on PySide2/QDarkStyle.

#

Although I'm not sure if you saw the message I sent last night, my windows version isn't activated, so I can't change the system color theme, so I don't know what, if anything that breaks

rough furnace
#

@wide prism and I can test on windows (w/ this kind of cross-platform-ness, you have to rely on others to verify this stuff ๐Ÿ˜† )

harsh ravine
#

Sounds good to me. I'll make sure i get the PyQt5/Mac stuff tested

wide prism
#

is the self.styleSheet property basically the same as the darkMode Flag that we already have?
I think you've managed to simplify the code to the point where it really only needs to check that, right?

harsh ravine
#

No, stylesheet only checks if there is a stylesheet, and if its a qdarks tyle stylesheet

wide prism
#

And otherwise you just leave the colors alone?

harsh ravine
#

No, we then check if the dark mode property is set and applies dark colors, if not we apply the light mode colors

#

those parts are all still in updateDepth

wide prism
#

So, if we make sure darkMode is properly set, then we don't need to check the stylesheet?

harsh ravine
#

If we have a stylesheet we don't want to change the background colors, just let it be responsible for the style

#

at least I think thats what we want

#

stylesheet has the highest priority

#

if we have one we dont care what mode the OS is in

#

qdarkstyle breaks the small combo boxes in a great way

wide prism
#

I'd read the darkMode flag to specifiy what mode the app is in... Either from OS or stylesheet. But that's not really defined.

#

Can you remind me why we need to adjust the background if we don't have a stylesheet?

harsh ravine
#

I believe the original intention was to distinguish between the outermost groups and the groups they contain

rough furnace
#

which is why alternateBase not working really hurts as that's exactly what we want.

wide prism
#

Makes sense. But we'd still want to do that if there is a stylesheet, right?

harsh ravine
#

I don't see why. The person who chose that stylesheet knew exactly what they were going to get when they applied it

wide prism
#

Can that even be styled by stylesheet now?

harsh ravine
#

that said, i thought what we had earlier when a stylesheet was applied looked pretty good

#

I believe you can access properties from objects that inherit from qwidgets in a stylesheet

wide prism
#

But do we do that?

harsh ravine
#

Well, that would have to be done in the stylesheet and we don't write the code for that

#

I honestly haven't looked past the top of the stylesheet except to grab a couple of colors

#

I'll check to see what the pyqtgraph specific stuff is though

#

we could make sure that the people who want to modify the stylesheet to do that could

#

we just need to set a property on the groupItem that returns its depth, then they could add their own colors/css

wide prism
#

My working assumption is that the specific aspects of ParameterTree are not customizable by styelsheet. But I may be wrong. My main hint towards this is that there are hard-coded colors....

I thought grabbing colors from the palette was the simple solution here, otherwise I wouldn't have made so much trouble ๐Ÿ™‚

harsh ravine
#

This is the only pyqtgraph stuff in the stylesheet

PlotWidget {
  /* Fix cut labels in plots #134 */
  padding: 0px;
}

        QDockWidget::title
        {
            background-color: #C9CDD0;
            text-align: center;
            height: 12px;
        }
        QTabBar::close-button {
            padding: 2px;
        }
        
        QMenu::item {
            padding: 4px 24px 4px 6px;
        }
harsh ravine
#

I also could be wrong about this

wide prism
#

Does that have the depth levels? If it does, why do we need to make our own colors? (In non-stylesheet mode, I mean)

harsh ravine
#

The parameterTree? No, we would have to set a property on each groupItem(QTreeWidgetItem) with a property that returns the depth, or something that indicates whether or not its an inner widget or not

#

Or... we actually might be able to do it from the tree... something like TreeWidget::item['depth=1']{//css here}

#

rather, they might be able to style their group items this way if we were to set a depth property

wide prism
#

WARNING DETOUR:
You can set an objectName on the QtWidgets, and the stylesheet can be applied based on these. That would be a neat way to get the depth levels into QDarkStyle. Maybe we should set these by default. setObjectName('groupitem_depth_1') etc.

#

To come back to the main track:
I feel like the depth level coloring is a hack. If we need it in palette mode, we also need it in stylesheet mode.

#

If we can get rid of it in stylesheeet mode, we should try to get rid of it in palette mode ๐Ÿ˜

#

So I would still vote to ditch the new stylesheet / no stylesheet distinction and stick with just the one global light/dark info flag.

#

And since that seems to work automatically on a growing number of systems, I would say let's force the user to handle it for the exceptions.

#

Like forcing dark mode on PyQt5 / windows.

harsh ravine
#

The problem with a global color for dark mode and dark stylesheet is that, atleast on macos, dark mode is grey and the stylesheet is dark blue. That means the tree would look weird in at least one of those situations

wide prism
#

Solved by getting the user to supply a palette that matches the stylesheet they want.

harsh ravine
#

Yeah

#

That would also solve another issue that would happen if we did that. A light stylesheet in dark mode would cause the bg colors in the tree to be super dark

#

How would we handle the case where the user has a light stylesheet applied, but switches to dark mode in the OS?

#

should we change their stylesheet also?

wide prism
#

Tell them not to do it.

#

Document how to intercept the mode change?

harsh ravine
#

Well, I didn't think anyone did that until @rough furnace said we needed to fix it ๐Ÿ˜…

wide prism
#

We should be able to provide the following:

  • the default colors change as expected
  • it is possible to use custom colors without total breakage when the light/dark mode toggles
#

But the second part is a problem with any stylesheet application in Qt, so there should be a solution already. We just have to make sure we don't break it.

harsh ravine
wide prism
#

But they still need to actively swap! So it's user responsibility already.

harsh ravine
#

or they just have one stylesheet

harsh ravine
#

I'm mostly talking about closed source, paid applications that use Qt

wide prism
#

That's a level of sophistication where I'd think they'd also be able to catch a system applied palette change and undo it.

harsh ravine
#

we're doing that now in the most recent PR

wide prism
#

In ParameterTree or at the app level?

harsh ravine
#

Those changes are in ParameterTree and ParameterItem because it was the easiest place to detect and respond to the change

#

The only thing that it does is run updateDepth again after the palette has changed so the colors match when some psycho changes their theme while the app is running

wide prism
#

That's precisely what it should be doing. ๐Ÿ‘

#

What I think I am trying to get to:
If you use a stylesheet, you have to be aware that the system might change your palette.
Either update your stylesheet to match, or make sure that the palette change does not affect your app at all.

#

If we can provide example code (ready to copy-and-paste)

  • that gets called when the palette changes
  • that can either block the change, or just immediately reset back to a stored palette
    Then @rough furnace 's example can be managed.
#

I don't think we can do that 100% automatic, since we will never know what is a system call, and what is a psycho with bad taste in colors.

#

But it only affects the "manually applied stylesheet" case, which requires custom user code already, so adding a little to that is not a big deal.

#

My (non-authoritative) wishlist for the PR is now this:

  • ditch the hard-coded colors for palette colors as much as possible
  • make sure it works in the default mode on each system (that is only light mode on [my] broken Windows/PyQt)
  • ideally handle light/dark switching on mac
  • stylesheets can work, but put responsibility on the user to set a matching palette (which also updates the darkMode flag)
#

So, basically don't worry about the stylesheet anymore.

harsh ravine
#

Okay, I need to think about how we can do that for a few minutes.

wide prism
#

Awesome. I hope we can come up with something that ports over to other parts of the library that now rely on hard-coded colors... ๐Ÿ™‚

harsh ravine
wide prism
#

User's problem.

harsh ravine
#

Ignore the fact that the message i replied to is on a completely different topic

harsh ravine
#

even if it gets merged like that, how will they know whats going on without digging into the code

#

I can always use the text palette color and bump the brightness on it, but thats pretty much whats happening now with less messy code

wide prism
#

We write a doc that says "if you are seeing a white text on white background after applying a stylesheet, you need to make sure the palette matches the the stylesheet. This code applies a general dark palette to a QApplication that fixes this problem:

#

pg.configureApplication(qapp, style='dark')

#

The user should be able to find that the problem results from the stylesheet, so they have a good basis to search from.

harsh ravine
#

There is already a default foreground option. Could we just use that?

wide prism
#

No, but we can add the palette explanation to the docs in that part of the code, too.

#

There is a separation of text and graphics palettes. I don't think the scheme should leak over.

#

If we wanted to allow that, the default foreground should pull from the palette, not the other way around.

#

(Note that we now default to black text on white for UI, but light text on black for plots)

harsh ravine
#

Oh, in the comments it said labels, I assumed that meant QLabels

wide prism
#

I mean, we have so many crazy flags, maybe you found one I am not aware of ๐Ÿ™‚

harsh ravine
#
CONFIG_OPTIONS = {
    'useOpenGL': useOpenGL, ## by default, this is platform-dependent (see widgets/GraphicsView). Set to True or False to explicitly enable/disable opengl.
    'leftButtonPan': True,  ## if false, left button drags a rubber band for zooming in viewbox
    # foreground/background take any arguments to the 'mkColor' in /pyqtgraph/functions.py
    'foreground': 'd',  ## default foreground color for axes, labels, etc.
    'background': 'k',        ## default background for GraphicsWidget
    'antialias': False,
    'editorCommand': None,  ## command used to invoke code editor from ConsoleWidgets
    'exitCleanup': True,    ## Attempt to work around some exit crash bugs in PyQt and PySide
    'enableExperimental': False, ## Enable experimental features (the curious can search for this key in the code)
    'crashWarning': False,  # If True, print warnings about situations that may result in a crash
    'mouseRateLimit': 100,  # For ignoring frequent mouse events, max number of mouse move events per second, if <= 0, then it is switched off
    'imageAxisOrder': 'col-major',  # For 'row-major', image data is expected in the standard (row, col) order.
                                 # For 'col-major', image data is expected in reversed (col, row) order.
                                 # The default is 'col-major' for backward compatibility, but this may
                                 # change in the future.
    'useCupy': False,  # When True, attempt to use cupy ( currently only with ImageItem and related functions )
    'useNumba': False, # When True, use numba
} 

from pyqtgraph/__init__

wide prism
#

background is the default blac"K" background of the plots, and the axes are a "D"ark gray foreground color.

harsh ravine
#

Gotcha, so changing that would fix one thing and break the other if we used that color for text on a light theme

wide prism
#

It would certainly change everybody's pyqtgraph apps dramatically โ˜€๏ธ

rough furnace
#

๐ŸŒš

wide prism
#

That looks vaguely unhealthy.

rough furnace
#

I think it's supposed to be a moon, representing dark mode ๐Ÿ˜†

harsh ravine
#

Do you have any thought/preferences about any of this @rough furnace ?

rough furnace
#

been a bit afk, if I can summarize, and please correct me if I'm wrong....

#

what works: macos (maybe kde linux) toggling light/dark mode, starting applications in light/dark mode, windows...which is effectively always light mode (w/o style sheets)

#

what doesn't work: when style-sheets enter the picture, and if light/dark mode are toggled while a style-sheet is applied

wide prism
#

style-sheets need a little help from the user side.

rough furnace
#

can we not make a PR w/ qdarkstylesheet?

harsh ravine
rough furnace
#

and completely ignore style-sheet related issues on our end?

#

(sorry, should let you all finish typing before I post non-sense ๐Ÿ˜› )

wide prism
#

Problems:

  • I believe that we need to do some work to make the tree fully style-able. If we have that, then we can indeed work with QDarkStyle to style it.
#

Unless I am wrong, though, that would be yet another dramatic change in direction for this PR.

#

Problem 2:

  • the current workarounds rely a lot on hard-coding colors for various cases, which --> I <-- am allergic to.
rough furnace
#

so first question, does this PR make the parameter-tree any less styleable than it is now (or IOW, do we make things worse with respect to QDarkStyleSheet (or any style-sheet that may be applied globally?)

wide prism
#

-> No, but it could make it infinitely more style-able with very little work.

rough furnace
#

fwiw, hard-coding colors is what got us in this mess a bit so I'm pretty allergic to that too

#

hmm...if we don't break the styling any more, I think we should give @harsh ravine the option to take the exit ramp and merge the improvement as-is, and then do whatever other work is needed to make style-sheets work more robustly

wide prism
#

Acceptable; and all the talk has already given us a lot more ideas for how to handle this in the future. โค๏ธ

harsh ravine
#

If any other stylesheet is applied... I think we change the colors with the system theme... I need to look again

rough furnace
#

I legit thought this issue was replacing the hard-coded color w/ qapp.palette.alternateBase().color().base()

harsh ravine
#

We're pulling colors from palette.window.color and changing the brightness level based on the color theme for the background and foreground. For the text colors they are hard coded either black or white to match theme

#

(Thats when a stylesheet is applied)

#

when no stylesheet is applied the color is just the palette.text.color

rough furnace
harsh ravine
#

Oh... yeah Alternate base is a thing.. I just didn't know it had a base attribute i could use