Tyrrrz / LightBulb

Reduces eye strain by adjusting screen gamma based on the current time
MIT License
2.27k stars 141 forks source link

Adding parameter to shift sunset/sunrise #131

Closed slanglade closed 4 years ago

slanglade commented 4 years ago

Hi,

A nice feature to have would be to add a parameter to shift the sunset/sunrise timing (grabbed from internet) by a given amount of minutes.

For instance : the transition duration is 45 minutes, the shift is 20 minutes. Then :

Or it could be better (??) if :

This way, transition start when sky light already changes / artificial light is already active, but sun is not officially 'rised' or 'set'. With the current version, transitions are always lagging behind true sky changes and are happening a tad too late.

Tyrrrz commented 4 years ago

Hi,

I was thinking about it as well, mainly the last thing you mentioned. I think the problem is that the transition duration currently works by pushing the sunset finale further, instead of starting the sunset earlier.

slanglade commented 4 years ago

Yes, you're right!

By having transition start earlier on sunset, it would far more logical, symmetrical and straightforward.

Tyrrrz commented 4 years ago

Changed how the flow works. If you have time, please check out the CI build with this change implemented (look for artifacts in the top right): https://github.com/Tyrrrz/LightBulb/runs/372768259

Tyrrrz commented 4 years ago

@slanglade please tell me if/when you try it out as I'm curious to hear your thoughts.

slanglade commented 4 years ago

Hi,

thanks for your build, but I'm in big trouble with stupid Symantec corporate antivirus, that is blocking me from testing. That's strange, given that I didn't have to do anything for the previous "regular" build up to and including v2.0.0

I will try again today and keep you informed.

slanglade commented 4 years ago

Wow-ho ! I love Symantec...

So I did install, battling thru endless antivirus popup windows, and given the "preview" effect it seems really good to me ! I will check and keep you informed this afternoon. Thanks again !

slanglade commented 4 years ago

Works like a charm :-)

Tyrrrz commented 4 years ago

I've been trying it lately and it seems like it now starts too early for me hmm. I think the transition should indeed start at sunset but be a bit shorter. We can calculate it as the time between sunset and complete night time.

I think adding configurable offset kinda makes sense, but it would offset the sunrise/sunset times as a whole.

slanglade commented 4 years ago

If I understand correctly : before, you were doing transition starting at sunset or sunrise time, for a given period of time (set by user).

It was working ok in the morning : dawn did start a bit earlier but in working environment, we still have artificial lights on.

But it was not working in the evening, as at sunset time, we often are already using artifical light.

So having the timing of transition being (from sunrise to sunrise + transition) and (from sunset - transition to sunset) sounds good to me : it works the same (but reversed) as in the morning, and is way better. It's up to the user to have a correct transition duration, according to his likings.

Maybe can you do some hard math to have transitions starting with theorical dawn or dusk period, and not sunrise and sunset timings. But it deeply depends on meteorogical conditions, and may be useless at the end.

What if you have two duration parameters : one for sunrise and one for sunset? This way, and keeping this new 'reverse' period mecanism for sunset, it will be a bit more flexible for user.

But I really think the way of doing things in this build is a good trade-off.

Tyrrrz commented 4 years ago

If I understand correctly : before, you were doing transition starting at sunset or sunrise time, for a given period of time (set by user).

Yes, that's correct.

It was working ok in the morning : dawn did start a bit earlier but in working environment, we still have artificial lights on. But it was not working in the evening, as at sunset time, we often are already using artifical light. So having the timing of transition being (from sunrise to sunrise + transition) and (from sunset - transition to sunset) sounds good to me : it works the same (but reversed) as in the morning, and is way better. It's up to the user to have a correct transition duration, according to his likings.

It's interesting, can you tell me the city where you live and what time, approximately, are the artificial lights turned on?

But I really think the way of doing things in this build is a good trade-off.

For sure. I'm also trying to avoid adding additional configuration as it's exponentially harder to test, so if there was a single way to satisfy all user needs, I would be happy 🙂

slanglade commented 4 years ago

I'm in Clermont-Ferrand, France : Longitude 3.087025 Latitude : 45.777222

And according to me (the best opinion on earth, once again according to me) : in the morning, we have a tendency to leave lights on late, having natural + artificial lights adding up. And a tendency to switch lights on late in the evening, with less light. So in the evening, there is more need to have transition starting before sunset.

Is there some public API (or not-to-crazy algorithm) that would provide theorical dawn and dusk period? That may be ideal :

slanglade commented 4 years ago

You surely already know this service : https://sunrise-sunset.org/api

They provide twilight timings, that may be useful to automate things and have a good approximation of what our eyes are seeing.

Tyrrrz commented 4 years ago

Thanks!

Is there some public API (or not-to-crazy algorithm) that would provide theorical dawn and dusk period?

Yes, it's quite easy. Currently the sunrise and sunset are calculated as points in time when the sun reaches a certain elevation: https://github.com/Tyrrrz/LightBulb/blob/89d70e9f4532e76f60ca5c72955af86c498c9bfb/LightBulb/Logic/AstronomyLogic.cs#L50-L64

I can just calculate it for certain elevations, something that corresponds to phases here: https://www.timeanddate.com/sun/ukraine/kyiv

Tyrrrz commented 4 years ago

You surely already know this service : https://sunrise-sunset.org/api

I used it in LightBulb versions prior to 2.0 but then replaced with the above algorithm. This way LightBulb doesn't use internet for anything critical.

slanglade commented 4 years ago

That's great and interesting stuff. In fact, if you have an angular parameter instead of a duration parameter, you can have the user choose whatever twilight angle he prefers (6° for civil, 12° for nautical , 18° for astronomical, or any free angle, see https://www.timeanddate.com/astronomy/different-types-twilight.html).

And adapt you calculation to have a precise timing of the corresponding twilight amplitude. But I don't know if it's as easy as offsetting your 90.83 constant with the chosen parameter, as I quite don't understand how this works precisely 😃

And maybe combine that with a duration parameter to tell "how much time before given twilight for dusk" and "how much time after given twilight for dawn".

Or a percentage, with 100% being the time period between morning twilight and sunrise (and between sunset and evening twilight). With percentage, it adapts automatically to seasons, in fact.

slanglade commented 4 years ago

A quick pseudo-diagram,with totally fake numbers :

---|-------------------|-------------------------------------|-------------|--------
Twilight              Sunrise                                Sunset       Twilight
   -6°                  0°                                    0°          6°
6h44                    7h00                               18h00        18h16
    <---- 16 min    --->

So with a 200% parameter, it gives :

Or it can be 6h44->7h32 and 17h28->18h16, I don't know which is more natural.

Tyrrrz commented 4 years ago

But an important thing to note is that if the transition is calculated automatically, it will still start at sunset (as it did before this change).

slanglade commented 4 years ago

But what if you modify your formula, so you get twilight timing (using the angular offset parameter) in addition to the regular sunset /sunrise? This way you'll have a time interval that depends on season and sun declination. Using it as-is for transition period will be a good approximation of real light conditions, plus and additional parameter to grown / shrink the transition.

Tyrrrz commented 4 years ago

But twilight happens after sunset. So according to your diagram, for this particular day, it would be an equivalent of setting transition duration to 16 minutes in the previous version of LightBulb.

Your suggestion works (actually we were both suggesting the same thing) but with that setup the transition to night will start at 18:00, which is too late for you as you've described earlier.

slanglade commented 4 years ago

Well in fact, I f**'d-up my explanations... In fact, if you calculate the transition (in the mornig) from twilight to sunrise+(sunrise-twilight), then you have in fact doubled the duration of twilight to sunrise to have your transition length.

So you can use that to have a transition (from twilight to twilight+2xduration), that may works pretty well. And reverse the thing for sunset : (from twilight-2xduration to twilight).

And maybe have the "x2" coefficient being modified by user at will, with the center of the period being the sunset (or sunrise). This way in morning, the transition slowly start with twilight ("before sun") and stop after an equivalent amount of "after sun".

Is this more in line with what you were thinking ?

Tyrrrz commented 4 years ago

How about this:

slanglade commented 4 years ago

How about this:

* Calculate the transition duration automatically as the duration between sunset and twilight (or twilight and sunrise).

* Have an option to make the transition instant for those who want it.

What do you mean by "instant" ? As-is ? Or like on/off ?

* Add an option to "offset" sunrise/sunset time by a constant duration if you're using location-based solar configuration.

I really think having a transistion windows centered on sunset/sunrise is better : sun light start showing with twilight setting, but continue to intensify after sunrise. So this centered windows looks good to me, thus with a duration of 2 * (sunrise-twilight).

Settings could be :

And the very same but reversed for sunset.

Tyrrrz commented 4 years ago

Based on the suggestions in these comments, I made another change. Now the transition duration is solely a setting for manual solar configuration. It was renamed to twilight duration and moved from general settings to location settings.

For location-based configuration, the twilight duration is calculated automatically, so the transition should more-or-less match the light that reaches the user from the window. This effectively makes it easier for the user because they don't have to configure this anymore (if anyone even did at all). I've ran with this for some time and it appears to work quite well.

If you guys have time, please give a CI build a go and see how you like it. @slanglade @xcasxcursex

Tyrrrz commented 4 years ago

To clarify, the sunset transition starts at the official sunset time and then goes on until the civil dusk.

ghost commented 4 years ago

As a sailor, and pilot, I can assure you that the light which reaches my window depends on where my window is ;) I'm excited to see the three flavours of twilight recognised.... But then I tried it and I understand now, you're only using that one transition period, standard civil twilight.

What I've found is that basically no matter what latitude I set, the transition is around half an hour..... Which strikes me as kinda short. I had mine set at 2:30.

At first I thought it was a bug maybe because I'm in the Southern Hemisphere and upside-down so we make software bugs fly easily :) but I tried different latitudes with similar longitudes (Tokyo, Port Moresby, and Melbourne) and found it about the same. No bug.

So, given I have this page bookmarked for my sailing planning , it was easy to check, and sure enough, your math is working as intended. If I compare the sunset and civil twilight times for every day of the year from my local marina, sure enough it's about 30 minutes. So, why on Earth did I have it set to 2:30? 2:30 seems much more like the time I see the light disappear when I'm on the water. It doesn't go from light to "turn on the navigation lights" in 30 minutes, it's more like an hour, and I don't bother with searchlights or cabin lights until an hour after that. Well, it turns out 2:30 about right for astronomical twilight (actually it's more like 2:10, I guess I rounded up) . So I have to ask myself, why am I doing that?

You're absolutely right, that the colour temps that the app is setting are appropriate for the times of day, when using civil twilight, the 6 degree zenith (at least, when I'm at home, at sea level, or close to it, let's not even get started on when I'm airborne). I checked on this and it turns out that photography nerds are really into this, so it was easy to confirm. You're totally doing it right.

So why am I stretching it out so much? Am I just weird? Then I realised, this is related so something I've asked about before - offsetting the brightness and the gamma setting. I'm ready for the red light when it's red outside, but I'm not ready for the darkness when it's still light outside, and it's still light outside until astronomical dusk. The app is hitting minimum gamma at civil dusk but it's also hitting minimum brightness at civil dusk and to match the sunlight, it really should be hitting minimum brightness at astronomical dusk.

And I know, the result of our brief discussion about this earlier was that it was too complex to implement, but, this is a real thing.... and I never would have even considered it until this change, but now I understand why I had that 'feeling' of wanting to offset the brightness setting, and why I always pushed the transition time out to the maximum. I was screwing up the gamma so that the brightness was correct. Now that you've made the gamma objectively correct, I've found out why the brightness feels wrong.

I'm sorry mate, I know this throws a spanner in the works. I'm hoping that it might not be too difficult to set the .brightness and .gamma variables, using a different zenith in the new CalculateSolarTime() function? I haven't looked at it much. Just enough to find a problem, but not sure of the solution. I am totally willing to donate my free time (I have a lot right now!) to help with this.

Tyrrrz commented 4 years ago

@xcasxcursex thanks for the feedback!

Indeed, I'm worried that ~30 mins transition duration might feel too short for some people. Separating brightness could be possible but I also suspect some people would want to configure that the opposite way as well.

If I were to add an option to configure the twilight in location-based mode, say between civil, nautical, and astronomical twilight, would that be enough to solve the problem? I guess with the option to use astronomical twilight, you will be able to achieve the same behavior as in the current version.

ghost commented 4 years ago

Well, I did think to myself, if I could use astronomical twilight, then at least I could get it to behave like it did before, which I would prefer..... So I guess that selectable twilight would be a nice change.

But this latest change really has got me thinking about this more than ever. In the past, I honestly just installed redshift, then when I was forced to Windows, flux, then upgraded to this, and didn't really give it too much thought. It was more comfortable, I rested better, it worked, that was all. Lightbulb has constantly improved over time and it's always really nice to be able to experience the new stuff :)

This change has got me really looking into the details of how and why this kind of software does what it does, and why I use it the way I do, and why others might use it differently. It's been interesting .... but wow there's a lot to read and consider and experience - I've now read far too many research papers filled with neurochemicals with names I care not to pronounce ;)..... and set an early alarm to watch a few sunrises since my last post.... and from a programmer's perspective, there are sure a lot of ways to make things complex and inelegant....

Sine you've mentioned upcoming refactoring, I might leave some more indepth thoughts for a new issue.... but until then, yes, it would be good to have adjustable twilights for transition durations.

Tyrrrz commented 4 years ago

I'm thinking of trying a different approach with regards to twilight. You are right, the way you observe twilight heavily relies on which side your window is facing, if there are any obstructions on the horizon, etc. This makes the "real" twilight time ultimately useless, because even if it's off by 5 or 10 minutes compared to how the user perceives it, it will ruin the experience.

I think the original proposed solution to add free hand configuration for this makes more sense. I was initially against it because I want to avoid adding additional settings if I can help it, to make it easier for both the users and myself.

The way I see it now is:

For location-based solar configuration, sunrise and sunset are set automatically, but the user still can configure the transition offsets. Effectively, this should let the user set their transition to start earlier or later, or end earlier or later, while using actual sunrise/sunset as anchor points.

The problem here is that the user will probably have to adjust these settings throughout the year because the sun rises and sets from different directions (does it? I'm not sure) and thus affects how the twilight is perceived. Granted, it shouldn't change too much I think, but the difference would be around 20 minutes from one extreme to another.

Thoughts?

ghost commented 4 years ago

For now: Change it to astronomical twilight

Rångtell and colleagues [64] examined the effects of reading a novel on a tablet computer (~102 ± 41 lx, 7718 K) vs. in a physical book (~67 ± 50 lx, 2674 K) for two hours following prolonged (6.5 h) exposure to bright light (~569 lx, 3149 K) between 2:30 pm and 9 pm. Contrasting other findings, the light from the tablet did not suppress melatonin or alter subjective and objective sleep parameters. Note though that also exposure was shorter than in studies that reported significant effects

Half an hour just doesn't have the desired effect - at least, not after a full day of bright light.

...but

Thoughts?

I have a lot. Too many. Sorry I'm taking a long time to reply, I'm just trying to take a bunch of science and thinking and stuff, and turn it into something that is not a boring annoying wall of text ;)

The shortest way I can say it is this: I think you should do away with "daytime" and nighttime" and "transitions" and treat the entire day/night as a constant transition. Obviously, this reflects the physical reality of our solar system, but it has serious practical limitations (I'm sure you can imagine many of them), so there should be user ability to modify the waveforms. And I say "waveforms" plural because it turns out that separating temperature and brightness is actually super important.... *I'll come back to this

Although, they would still be based on one single waveform, resulting from the position of the sun (the existing astronomy class), that would then generate two waveforms, one for temperature and one for brightness.... These would be not modified by the user, but a simple representation of the physics involved...... And then two associated 'modifier' waveforms, one for temperature and one for brightness, would modify the results of their 'parents', to suit practical and preferential requirements.

Part of me is concerned that this might be computationally intensive but when I think about it it is going to just be a few extra floating point mults/clamps/sin operations, I don't think it would be too heavy. It might be a hell of a re-write though. I'm not going to drop this on your lap and run away, I will offer as much time as you need to assist....

[“night shift” mode] amounts to a reduction of melanopsin activation by 67% at full display brightness. This might seem like a large reduction at first, though by simply dimming the smartphone to its minimum level, the melanopsin activation can be reduced to less than 1% of the activation at maximum display brightness.....

So it seems simple, just drop the brightness when you warm the temp....but..... Firstly, the body does not expect these two things to happen simultaneously - let's consider the sun at 4pm, it is low in the sky, and the colour temp has begun to drop a little - but the brightness is still near to its peak. They do not rise/fall in sync with each other (although they are in phase). Then, there is sunset, when temp is at minimum, but brightness is still somewhere in the middle. Then, let's consider an hour after sunset. There is still light in the sky from the sun, but the colour temp is now rising again as we head toward the blueish light of the stars and moon. (Again, these waveforms are in phase but out of sync)

It turns out, this is actually really important, and something that EVERY 'night mode' type application is doing wrong (Window's built in one, lightbulb, f.lux, redshift, all of them!) This is because the lack of blue light signals the brain to produce more sleepy neurochemical (melatonin), which was the whole idea....but it also slows our body clock (delays the circadian rhythm), making it later and later in the day, the longer we have the light, warm temp or not... The brightness needs to drop after the temp drops.

The effects of light on the phase of the circadian clock depend on the timing of light exposure. This is formally summarised in the phase response curve (PRC), which describes the amount of phase shift (in minutes and hours) achieved by exposure of light at a given circadian phase. Roughly speaking, the effect of morning light is that it advances the clock, while evening and night light delays the clock.

It's actually important to not have the warmer colour temp late at night, especially if the brightness is too high, otherwise our body clock keeps shifting later until it gets blue light again. This means that having the warmer colour temperature at sunset is good, but at night is no better, because it makes our body think the next morning is later, and the next night will be later, and every time after that is later. Treating all night as though it is sunset, turns out to be a known way to screw up your body clock. We're 'stretching' the sunset for hours and hours.... So our body is 'stretching' the day to be longer, too......And EVERYONE making this kind of software, does it! (So don't feel bad lol)

Hopefully this begins (I could go on but I'm really trying not to wall of text) to explain why I think a 'constant transition' approach would be better. There are really four separate phases here: Pre-sunrise, morning, afternoon, post-sunset,... Or perhaps it could be considered by the peak/trough/zero-crossings: Sunrise, midday, sunset, midnight - which you already calculate very well with your algorithm borrowed from a fairly reliable source (The US Navy ought to know! heheh)

The trick here is to come up with an intuitive method for the users to modify (and probably to use as a default or have some 'presets') the 'modifier' waveforms which would shift the temperature and brightness as desired/appropriate. For example, having the temperature come to maximum and stay that way for an extended period (as it does now in the 'daytime' phase). I have a funny feeling you'll be able to think of a nice way to do that with something more intuitive, like using time rather than magnitude.

Some links:

https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6751071/#Sec4title (also five bazillion papers linked from this one) https://www.circadiansleepdisorders.org/info/PRC.php

I'll shut up for now and see what you think.

Tyrrrz commented 4 years ago

So I had some time to think about it. I'll be reverting all changes made regarding this for now and release 2.1 with other features.

The reason for that is:

Tyrrrz commented 4 years ago

So it's time to address the elephant in the room once again. This is the only feature I believe is missing for optimal experience.

I've gone through multiple ideas and have reached the following conclusions:

To that end, I think the best way to cover this missing area is to provide just one slider, in addition to existing "Transition duration", which can then be used to offset the transition relative to sunrise/sunset.

For example, if the transition duration is 30 minutes and the offset is at 0%, then the transition starts 15 minutes before sunset and ends 15 minutes after sunset (and same for sunrise). If the offset is at +100% then the transition starts at sunset and ends 30 minutes after (conversely for sunrise it starts 30 minutes before and ends exactly at sunrise); this behavior is equivalent to the current behavior in LightBulb v2.1. Finally, if the offset is set to -100% then the transition starts 30 minutes before sunset and ends exactly on sunset (and inverse for sunrise). Of course, the slider can be set to any value in-between as well.

This way there's some loss in flexibility due to the fact that the transition offset cannot be configured for sunrise/sunset independently, but at the end of the day this is still much better than nothing.

Tyrrrz commented 4 years ago

Done. You're welcome to test the latest master build.

Explanation on how it works is here: https://github.com/Tyrrrz/LightBulb/wiki/How-the-transition-offset-works

ghost commented 4 years ago

Dude, you're fast! This is a great addition, thanks!!

ghost commented 4 years ago

Sorry to repeat myself but this is working out really well. I keep forgetting that lightbulb is even running.

slanglade commented 4 years ago

I was leaving you guys arguing on this topic, about which I was at lost trying to get all the details. Glad to see this came to master, I'm going to test it myself ! Thanks a lot !

ghost commented 4 years ago

Well, since really digging into this, I hadn't even been running lightbulb until this update. I realised that the way it was behaving was messing with my eyes. I tried it a few times, and kept finding myself thinking that my screen was 'too bright' or 'too red' or 'too dark' or whatever. It just never seemed right. Now, it's so "right" that I keep wondering if I've turned it on, and have to show my hidden systray icons to check. "Oh hey, it's running? OK then, it just looks normal!"

As per the above discussion, I've gone for a cooler night-time temp than default (because moonlight), but a darker brightness than default (because brightness is more important than temp). I've also gone for a longer transition time (to make it smooth because the sky is round after all), and 50% offset (to balance the transition around the horizon, again , like IRL) ln attempt to mimic real-life light, as best as possible. I don't know if this will be right for you (I'd like to know!!) but it really matches what's happening outside my window (until late night-time when the moon is out and the temp should be cool, but by then, the brightness is so low, it barely matters)

My settings, in case you'd like to try them:

Day temp: default 6600 Night temp: 5200 Day brightness: default 100% Night brightness: 65% Transition length: 3 hours (shorter should be OK, but the long transition makes it subtle) Transition duration: 50% (I think this is the big one!)

Let me know if you find better, but at least until we can have red light at sunset but blue light at night, I feel like this is great.

Tyrrrz commented 4 years ago

Glad to hear it works well for you! @xcasxcursex Was it simple to understand the way offset affects the transition?

ghost commented 4 years ago

Was it simple to understand the way offset affects the transition?

Sure was. The way you explained it made sense to me, but I wanted to be sure I understood, so I just set it to 0% and looked at the main screen and then set it to 100% and looked at the main screen again. A picture tells 1000 words as they say :)