blueshift -- Automatically adjust the colour temperature
********************************************************

Copyright © 2014 Mattias Andrée

     Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled ``GNU Free Documentation License''.

Overview
********

Inspired by Redshift, Blueshift adjusts the colour temperature of your monitor according to brightness outside to reduce eye strain and make it easier to fall asleep when going to bed. It can also be used to increase the colour temperature and make the monitor bluer, this helps you focus on your work.

Blueshift is not user friendly and it is not meant too be. Blueshift does offer limited use of command line options to apply settings, but it is really meant for you to have configuration files (written in Python 3) where all the policies are implemented, Blueshift is only meant to provide the mechanism for modifying the colour curves. Blueshift neither provides any means of automatically getting your geographical position; the intention is that you should implement that in the policy yourself using library which can do that. Additionally Blueshift provides not safe guards from making your screen unreadable or otherwise miscoloured; and Blueshift will never, officially, add support specifically for any proprietary operating system. Blueshift is fully extensible so it is possible to make extensions that make it usable under unsupported systems, the base code is written in Python 3 without calls to any system dependent functions. If Blueshift does not work for you for any of these reasons, you should take a look at Redshift.

Invoking
********

Blueshift uses argparser to read options from the commnad line. It inherits a few properaties from this: abbreviations are supported, you only need to type the beginning of the long options so that the rest can be filled in unambiguously by the program; -- can be used, as usual, to make all following options being parsed as just arguments; and ++ works like --, except it only allied to the next option. Any argument that is not parsed as an option for Blueshift is passed onto the configuration script.

Blueshift recognises the following options:

-c
--configurations FILE
     Select configuration script. This defaults to the first file of the following the exists:

       * $XDG_CONFIG_HOME/blueshift/blueshiftrc

       * $HOME/.config/blueshift/blueshiftrc

       * $HOME/.blueshiftrc

       * /etc/blueshiftrc

     Blueshift does not check the user home, rather it checks HOME which should be the user home, unless you change it yourself.

-p
--panic-gate
--panicgate
     Applies the settings directly instead of transitioning into the initial settings. There is not option for doing this when the program exists. But you press Control+c twice, or send SIGTERM twice, to skip transition into default settings.

-h
-?
--help
     Prints help information.

-C
--copying
--copyright
     Prints copyright information.

-W
--warranty
     Prints non-warranty information, included in the copyright information.

-v
--version
     Prints the name of the program and the installed version of the program

Blueshift also supports a few options for ad-hoc settings. These are ignored (unlessed fetched by the configuration file) if -c (--configurations) is used.

-g
--gamma RGB
     Apply gamma correction to the colour curves. All values in the three colour curves are raised to the power of 1 divided by RGB. Assuming no values in the curves are larger than 1 (100 %) the curves are bent upwards if RGB is larger than 1.

-g
--gamma R:G:B
     This works as --gamma RGB, except the gamma is applied separately for the three colour curves. If we want to apply the 0,9 gamma to the red colour component, and 1,1 and 1,2 for the green and blue colour components, respectively use -g 0.9:1.1:1.2 or -gamma 0.9:1.1:1.2.

-b
--brightness RGB
     This multiplies all values in the colour curves with RGB, effectively making the display RGB times as bright. Values larger than 1, will be clipped to 1. This is indented to be used to make the screen slightly darker during the night.

-b
--brightness R:G:B
     This option is to --brightness RGB as --gamma R:G:B is to --gamma RGB.

+b
++brightness Y
     This option works as --brightness RGB, except the CIE xyY colour spaces is used instead of sRGB and will probably make the colour curves look better.

-t
--temperature TEMP
     Changes the colour tempurature to TEMP Kelvin. The standard colour tempurature is 6500 K (Or actually 6504 K using revised constants in Plank's law). If not specified, the colour temperature will be 3700 K during high night and 6500 K during the high day.

-l
--location LAT:LON
     Specify your geographical coordinates. This is used to determine how dark it is outside. LAT is the latitude, floating point measured in degrees from the equator to the north. It is negative if you are on the southern hemisphere. LON is the longitude, floating point measured in degrees from Greenwich to the east. Negative if you are on the west side of the Earth.

-r
--reset
     Transition from the specified settings to normal, clean, settings.

-o
--output
--crtc CRTC
     Select CRTC to apply changes to. This is comma separated list, and multiple options may be used. It is best to start one instance per monitor with colour calibration.

-g, -b, +b, and -t can be use twice, each, to use different settings during the night and during the day. While this is possible for gamma, it is not recommended. The purpose of gamma is to adjust the same error that are present in minors and make all colours look correct in relation to each other.

Configuration API
*****************

Blueshift has three colour curves:

r_curve
     The curve for the red colour component.

g_curve
     The curve for the green colour component.

b_curve
     The curve for the blue colour component.

These are i_size sized floating point lists, where 0 is the darkest colour and 1 is the brightest colour. Values outside this range are clipped unless clip_result is set to False. By calling clip (has no parameters) this clipping is done independently of the value of clip_result. When applied these values are automatically translated to appropriate integer values: [0, o_size - 1].

Blueshift provides a set of functions to manipulate these curves:

rgb_contrast(rgb)
     Adjusts the contrast to rgb.

rgb_contrast(r, g, b)
     Adjusts the contrast to r, g and b on the red, green and blue curves, respectively.

cie_contrast(y)
     Adjusts the contrast to y. The function calculate the values by using the CIE xyY colour space instead of the sRGB colour space.

rgb_brightness(rgb)
     Adjusts the brightness to rgb.

rgb_brightness(r, g, b)
     Adjusts the brightness to r, g and b on the red, green and blue curves, respectively.

cie_brightness(y)
     Adjusts the brightness to y. The function calculate the values by using the CIE xyY colour space instead of the sRGB colour space.

linearise()
     Converts the colour curves from sRGB to linear RGB. sRGB is the default colour space.

standardise()
     Converts the colour curves from linear RGB to sRGB, the default colour space.

gamma(rgb)
     Adjusts the gamma to rgb.

gamma(r, g, b)
     Adjusts the gamma to r, g and b on the red, green and blue curves, respectively.

negative(rgb)
     Inverts the all values on the colour curves if rgb is True.

negative(r, g, b)
     Inverts the all values on the red, green and blue curves if r, g and b are True, respectively.

sigmoid(r, g, b)
     An inverted sigmoid curve function is applied to the values of in red, green and blue curves if r, g and b are not None, respectively. r, g and b are the curve sigmoid curve multipliers for the red, green and blue curves, respectively.

manipulate(rgb)
     Applies the function rgb : float -> float to colour curves.

manipulate(r, g, b)
     Applies the functions r, g and b : float -> float to red, green and blue colour curves, respectively.

temperature(temperature, algorithm)
     Applies the a blackbody colour temperature of temperature (Actually multiplied by 1.000556328, due to revisions of natural constants) Kelvin. Where the white point for that temperature is calculates by the function algorithm : temperature -> (red, green, blue). When the white point has been calculates, its components are used as parameters in a componentwise brightness adjustment.

     There are a few algorithm for calculating the white point included:

     series_d(temperature)
          Can only calculate the white point correctly for temperatures inside [4000, 7000]. The CIE illuminant series D is used to calculate the white point.

     simple_whitepoint(temperature)
          Can only calculate the white point accurately for temperatures inside [1000, 40000]. A mathematical model of the cmf_10deg function is used.

     cmf_2deg(temperature)
          Uses a lookup table with linear interpolation to calculate temperatures inside [1000, 40000]. CIE 1931 2 degree CMF is used.

     cmf_10deg(temperature)
          Uses a lookup table with linear interpolation to calculate temperatures inside [1000, 40000]. CIE 1964 10 degree CMF is used. This is the preferred algorithm.

     redshift(temperature, old_version, linear_interpolation = False)
          Uses the lookup table from Redshift with linear interpolation. If old_version is True the table Redshift<=1.8 is used, which is limited to [1000, 10000], and is not that accurate. Otherwise (the default) the table from Redshift>1.8 is used, which is limited to [1000, 25100], and is accurate.

          If linear_interpolation is False (the default) the sRGB colour space is used for interpolation, otherwise linear RGB is used.

     Some of these algorithms (including cmf_10deg) are not very good by themself and should be wrapped with divide_by_maximum or clip_whitepoint ((red, green, blue) -> (red, green, blue) functions.) For example, instead of using cmf_10deg, you can use lambda t : divide_by_maximum(cmf_10deg(t)).

Keep in mind that the order your call the function matters. For example, adjusting the gamma before the brightness does not yeild the same result as in the reverse order, the latter is the correct way to apply gamma correction.

Before performing adjusts you must (not required the very first time) reset the curves by invoking start_over (no parameters.) Otherwise the adjustments will accumulate.

If you want to write your own functions curves(r, g, b) returns a tuple containing the tuples (r_curve, r), (g_curve, g) and (b_curve, b). To make this easier Blueshift provies a set of functions used to convert colour space:

linear_to_standard(r, g, b)
     Convert [0, 1] linear RGB to [0, 1] sRGB

standard_to_linear(r, g, b)
     Convert [0, 1] sRGB to linear [0, 1] RGB

ciexyy_to_ciexyz(x, y, Y)
     Convert CIE xyY to CIE XYZ

ciexyz_to_ciexyy(X, Y, Z)
     Convert CIE XYZ to CIE xyY

ciexyz_to_linear(X, Y, Z)
     Convert CIE XYZ to [0, 1] linear RGB

linear_to_ciexyz(r, g, b)
     Convert [0, 1] linear RGB to CIE XYZ

srgb_to_ciexyy(r, g, b)
     Convert [0, 1] sRGB to CIE xyY

ciexyy_to_srgb(x, y, Y)
     Convert CIE xyY to [0, 1] sRGB

All these functions return lists with the three colour components, not tuples. Input and output is one colour instance.

To apply a colour curve to the display server, invoke the randr function; print_curves can be used to print the curves to stdout instead (for debugging). These functions apply the curves to all monitors, put you can also use select monitors by specifying each monitor in as separate arguments. The monitors are indexed from zero.

If you want to write your own curve flushing fucntion translate_to_integers can be used, it returned the colour curves converted from floating point lists to integer lists in a tuple of three (red, green and blue.) Replace the parameterless function close_c_bindings to make it free all used resource, this is invoked when Blueshift exits.

When Blueshift exists, it invoked the parameterless function reset which you should replace. By default it resets the colour curves and flushes it to all monitors. To restrict which monitors it applies the changes to replace monitor_controller with a parameterless function that sends the colour curves to the desired monitors to the display server. This is only done if Blueshift runs in continuous mode.

In continuous mode, there are some interesting variables you can adjust at any time:

wait_period
     The number of seconds to wait before updating the colour curves again. This is a floating point variable.

fadein_time
     he number of seconds used to fade in on start, None for no fading. This is a floating point variable.

fadeout_time
     The number of seconds used to fade out on exit, None for no fading. This is a floating point variable.

fadein_steps
     The number of steps in the fade in phase, if any.

fadeout_steps
     The number of steps in the fade out phase, if any.

running
     Set to False to exit the program. This is normally done when Control+c is pressed or a SIGTERM signal has been received.

panic
     This variable only have effect if running is False. If this variable is set to True, the program will immediately run reset and exit. This is normally done the second time Control+c is pressed or the second time a SIGTERM signal has been received. (Or if both has happend.)

Additionally if the variable panicgate is True, there is no fading when the program starts. And conf_opts is a list of command line arguments passed onto the configuration script.

The parameterless function continuous_run, may replace if you want to do something very special, is invoked to run the continuous mode, it the program shall run in continuous mode. Which is determined by whether the function periodically is defined.

You can also replace the function signal_SIGTERM. continuous_run sets up the program to run it when the program receive a SIGTERM signal. continuous_run also invokes it when Control+c is pressed. signal_SIGTERM has two parameters, the second can be ignored as it is normally None; the first parameter is the signal that is received (an integer), and zero if Control+c has been pressed.

To run in continuous mode, you must implement the function periodically. It takes 8 positional arguments:

year
     The year.

month
     The month, 1 = January, 12 = December.

day
     The day, minimum value is 1, probable maximum value is 31. Theoretically, but most probably not, a change in the calender system could happen and the month's could length could be increased. This has happend once, giving us 1712-(02)Feb-30.

hour
     The hour, minimum value is 0, maximum value is 23.

minute
     The minute, minimum value is 0, maximum value is 59

second
     The second, minimum value is 0, probable maximum value is 60. We can get 60, or even higher (but that has never happend yet) due to leapseconds. A minutes length could also be shortend, but that has never happend yet either.

weekday
     The weekday, 1 = Monday, 7 = Sunday

fade
     Normally, periodically is invoked with fade set to None. This is note the case when the program starts or exits. When fade is not None, wait_period is not honoured.

     Blueshift can use periodically to fade into a state when it start or exits. fade can either be negative, zero or positive or None, but the magnitude of value cannot exceed 1. When Blueshift starts, the function will be invoked multiple with the time parameters of the time it is invoked and each time fade will increase towards 1, starting at 0, when the value is 1, the settings should be applied to 100 %. After this this function will be invoked once again with fade being None. When Blueshift exits the same behaviour is used except, fade decrease towards -1 but start slightly below 0, when -1 is reached all settings should be normal. Then Blueshift will not invoke this function with fade being None, instead it will by itself revert all settings, by calling reset and quit.

Python does not specify that the exceptions can happen, but do not could on them not. Python's documentation could be work, or the API could change.

If you want higher time precision --- the time parameters are integers --- you are welcome to use Python's time API. periodically will never be invoked with fake time. Just do not mix as you could theoretically get on two different seconds, minutes, hours, or even days, months or years, the delay between Blueshifts time measure and yours could overlap an increase in the second.

GNU Free Documentation License
******************************

     [file fdl.texinfo not included]