From 016dacb735766063917f237514cd28a27731bed0 Mon Sep 17 00:00:00 2001 From: endolith Date: Sun, 2 Jun 2024 22:23:31 -0400 Subject: [PATCH 1/4] Remove np.float references AttributeError: module 'numpy' has no attribute 'float'. `np.float` was a deprecated alias for the builtin `float`. To avoid this error in existing code, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here. The aliases was originally deprecated in NumPy 1.20; for more details and guidance see the original release note at: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations --- ehtplot/color/cmap.py | 4 ++-- ehtplot/color/cmath.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ehtplot/color/cmap.py b/ehtplot/color/cmap.py index 5d97fb5..810d176 100644 --- a/ehtplot/color/cmap.py +++ b/ehtplot/color/cmap.py @@ -117,7 +117,7 @@ def ehtrainbow(N=Nq, Jp=73.16384, # maximizing minimal Cp for all hue Cp=None, hp0=32.1526953043875, # offset the hue so that value==0 is red - eps=1024*np.finfo(np.float).eps, + eps=1024*np.finfo(float).eps, **kwargs): """Create a perceptually uniform rainbow colormap""" name = kwargs.pop('name', "new eht colormap") @@ -191,7 +191,7 @@ def ehtuniform(N=Nq, JpL=6.25, JpR=93.75, # consistent with 17 quantize levels CpL=0.0, CpR=64.0, hpL='coral', hpR='gold', hpD=None, - eps=1024*np.finfo(np.float).eps, + eps=1024*np.finfo(float).eps, **kwargs): """Create a perceptually uniform colormap""" name = kwargs.pop('name', "new eht colormap") diff --git a/ehtplot/color/cmath.py b/ehtplot/color/cmath.py index a56938f..67f9312 100644 --- a/ehtplot/color/cmath.py +++ b/ehtplot/color/cmath.py @@ -182,7 +182,7 @@ def adjust_divergent(Jpapbp, roundup=None): def max_chroma(Jp, hp, Cpmin=0.0, Cpmax='auto', - eps=1024*np.finfo(np.float).eps, + eps=1024*np.finfo(float).eps, clip=True): """Compute the maximum allowed chroma given lightness J' and hue h'""" Jpmin = 5.54015251457561e-22 From 6299e9378b82e535ec9e545a5a200f084641355b Mon Sep 17 00:00:00 2001 From: endolith Date: Sun, 2 Jun 2024 23:15:44 -0400 Subject: [PATCH 2/4] Notebook: Remove __future__ imports Python 2 is obsolete, so no reason to keep these. --- docs/COLORMAPS.ipynb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/COLORMAPS.ipynb b/docs/COLORMAPS.ipynb index 030b535..bc7090d 100644 --- a/docs/COLORMAPS.ipynb +++ b/docs/COLORMAPS.ipynb @@ -23,10 +23,6 @@ "# Disable cell scrolling\n", "display(Javascript(\"IPython.OutputArea.prototype._should_scroll = function(lines) { return false; }\"))\n", "\n", - "# Python2--3 compatibility\n", - "from __future__ import absolute_import\n", - "from __future__ import print_function\n", - "\n", "# Enable autoreload for easy module development\n", "%load_ext autoreload\n", "%autoreload 2" From 17ef5623368ed08dc01aecb5838a02857bfe347a Mon Sep 17 00:00:00 2001 From: endolith Date: Sun, 2 Jun 2024 23:15:33 -0400 Subject: [PATCH 3/4] Notebooks: Remove HTML/Javascript hacks These do not work and don't seem important anyway; the cells do not scroll regardless. First I changed IPython.core.display to IPython.display because of: DeprecationWarning: Importing display from IPython.core.display is deprecated since IPython 7.14, please import from IPython display But it still didn't work, so I just removed it --- docs/COLORMAPS.ipynb | 8 -------- examples/ehtcmap.ipynb | 11 +---------- 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/docs/COLORMAPS.ipynb b/docs/COLORMAPS.ipynb index bc7090d..a0bc416 100644 --- a/docs/COLORMAPS.ipynb +++ b/docs/COLORMAPS.ipynb @@ -15,14 +15,6 @@ "metadata": {}, "outputs": [], "source": [ - "from IPython.core.display import display, HTML, Javascript \n", - "\n", - "# Display text with 16px fonts\n", - "display(HTML(\"\"))\n", - "\n", - "# Disable cell scrolling\n", - "display(Javascript(\"IPython.OutputArea.prototype._should_scroll = function(lines) { return false; }\"))\n", - "\n", "# Enable autoreload for easy module development\n", "%load_ext autoreload\n", "%autoreload 2" diff --git a/examples/ehtcmap.ipynb b/examples/ehtcmap.ipynb index 30cd8f9..7bd1318 100644 --- a/examples/ehtcmap.ipynb +++ b/examples/ehtcmap.ipynb @@ -19,20 +19,11 @@ "%load_ext autoreload\n", "%autoreload 2\n", "\n", - "# Load the necessary libraries\n", - "from IPython.core.display import display, HTML, Javascript \n", - "\n", "import numpy as np\n", "\n", "import ehtplot as ep\n", "from ehtplot.color import vis as ev\n", - "from ehtplot.color import cmap as ec\n", - "\n", - "# Display text with 16px fonts\n", - "display(HTML(\"\"))\n", - "\n", - "# Disable cell scrolling\n", - "display(Javascript(\"IPython.OutputArea.prototype._should_scroll = function(lines) { return false; }\"))" + "from ehtplot.color import cmap as ec" ] }, { From f1a47f0f9a564136230ea628eb51e66fe0cd811f Mon Sep 17 00:00:00 2001 From: endolith Date: Mon, 3 Jun 2024 11:03:18 -0400 Subject: [PATCH 4/4] Notebook: Fix some spelling/language issues --- docs/COLORMAPS.ipynb | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/docs/COLORMAPS.ipynb b/docs/COLORMAPS.ipynb index a0bc416..d561cbe 100644 --- a/docs/COLORMAPS.ipynb +++ b/docs/COLORMAPS.ipynb @@ -46,9 +46,9 @@ "## 1. Background\n", "\n", "\n", - "The [Event Horizon Telescope (EHT)](https://eventhorizontelescope.org/) is a Very-long-baseline interferometry (VLBI) experiment aiming at capture of the first pictures of black holes. While an image worth a thousand words, the interpretation of an image is subjective. The presentation of an image can strongly affect how human eyes identify features. This is especially true for two-dimensional intensity maps, where the value of each pixel is represented by a color. A poorly chosen colormap between values and colors can fool the human eyes to, e.g., pick out non-existing features, or to hide important features.\n", + "The [Event Horizon Telescope (EHT)](https://eventhorizontelescope.org/) is a Very-long-baseline interferometry (VLBI) experiment aiming at capturing the first pictures of black holes. While an image is worth a thousand words, the interpretation of an image is subjective. The presentation of an image can strongly affect how human eyes identify features. This is especially true for two-dimensional intensity maps, where the value of each pixel is represented by a color. A poorly chosen colormap between values and colors can fool the human eyes to, e.g., pick out non-existing features, or to hide important features.\n", "\n", - "In order to present the resulting images of the EHT as accurate as possible, we take into account how human eyes work and provide a few guidance on the colormap usages in different situations." + "In order to present the resulting images of the EHT as accurate as possible, we take into account how human eyes work and provide some guidance on the colormap usages in different situations." ] }, { @@ -58,7 +58,7 @@ "## 2. Basic Requirements\n", "\n", "\n", - "Without putting in too much details, a good colormap for scientific representation of a scalar image should:\n", + "Without going into too much detail, a good colormap for scientific representation of a scalar image should:\n", "\n", "1. give readers a correct sense on the scalar values (intensities) in the image;\n", "\n", @@ -70,7 +70,7 @@ "\n", "5. be device-independent.\n", "\n", - "We summarize some works on human visual perceptual and standards created by the [International Commission on Illumination (ICE)](https://en.wikipedia.org/wiki/International_Commission_on_Illumination) below. We will then use these basic knowledge to derive general guidance on deriving and using colormaps." + "We summarize some works on human visual perceptual and standards created by the [International Commission on Illumination (ICE)](https://en.wikipedia.org/wiki/International_Commission_on_Illumination) below. We will then use this basic knowledge to derive general guidance on deriving and using colormaps." ] }, { @@ -82,11 +82,11 @@ "\n", "The \"raw\" [RGB](https://en.wikipedia.org/wiki/RGB_color_model) and [CMYK](https://en.wikipedia.org/wiki/CMYK_color_model) [color models](https://en.wikipedia.org/wiki/Color_model) are device-dependent. In order to describe device-independent color, companies create \"standardized\" [color spaces](https://en.wikipedia.org/wiki/Color_space) such as [sRGB](https://en.wikipedia.org/wiki/SRGB) (standard RGB by HP and Microsoft) and [Adobe RGB](https://en.wikipedia.org/wiki/Adobe_RGB_color_space). A [color profile](https://en.wikipedia.org/wiki/ICC_profile), either characterizes a device or a color space, can then be used to accurately map the color in an image to a device.\n", "\n", - "The [CIELAB](https://en.wikipedia.org/wiki/CIELAB_color_space) (also CIE L\\*a\\*b\\*, hereafter Lab) color space, introduced by the CIE in 1976, was the first attempt to take into account the the perceptual aspects of human vision. Here, L\\* is the lightness; a\\* and b\\* are the green-red and blue-yellow color components. The [CIECAM02](https://en.wikipedia.org/wiki/CIECAM02) [color appearance model (CAM)](https://en.wikipedia.org/wiki/Color_appearance_model) published by the CIE in 2002 defines six color appearances: brightness Q, lightness J, colorfulness M, chroma C, saturation s, and hue h. And the [iCAM06](https://en.wikipedia.org/wiki/Color_appearance_model#iCAM06) model is capable of handling spatial appearance phenomena such as contrast.\n", + "The [CIELAB](https://en.wikipedia.org/wiki/CIELAB_color_space) (also CIE L\\*a\\*b\\*, hereafter Lab) color space, introduced by the CIE in 1976, was the first attempt to take into account the perceptual aspects of human vision. Here, L\\* is the lightness; a\\* and b\\* are the green-red and blue-yellow color components. The [CIECAM02](https://en.wikipedia.org/wiki/CIECAM02) [color appearance model (CAM)](https://en.wikipedia.org/wiki/Color_appearance_model) published by the CIE in 2002 defines six color appearances: brightness Q, lightness J, colorfulness M, chroma C, saturation s, and hue h. And the [iCAM06](https://en.wikipedia.org/wiki/Color_appearance_model#iCAM06) model is capable of handling spatial appearance phenomena such as contrast.\n", "\n", "In 2006, [Luo et al.](https://www.researchgate.net/publication/229879898_Uniform_colour_spaces_based_on_CIECAMO2_colour_appearance_model) introduced three modifications to CIECAM02 to make it more uniform. The CAM02-UCS, stands for \"Uniform Colour Space\", is not popular in computer graphics. Its three coordinates are usually denoted by J', a', and b'. And its cylindrical coordinates are J', C', and h'.\n", "\n", - "It is useful to transform the Cartesian Lab and CIECAM02 color spaces to the cylindrical [CIELCh](https://en.wikipedia.org/wiki/CIELAB_color_space#Cylindrical_representation:_CIELCh_or_CIEHLC) (hereafter LCh) and CIEJCh (hereafter JCh) color spaces which has coordinates L\\*, J\\*, C\\*, and h. The lightness coordinates L\\* and J\\* are identical to Lab and Jab. The chroma (relative saturation) C\\* and hue h (in degree h°) are simply `C* = sqrt(a*^2 + b*^2)` and `h = atan2(b*, a*)` according to Redness-Greenness a and Yellowness-Blueness b in their own coordinates." + "It is useful to transform the Cartesian Lab and CIECAM02 color spaces to the cylindrical [CIELCh](https://en.wikipedia.org/wiki/CIELAB_color_space#Cylindrical_representation:_CIELCh_or_CIEHLC) (hereafter LCh) and CIEJCh (hereafter JCh) color spaces which have coordinates L\\*, J\\*, C\\*, and h. The lightness coordinates L\\* and J\\* are identical to Lab and Jab. The chroma (relative saturation) C\\* and hue h (in degree h°) are simply `C* = sqrt(a*^2 + b*^2)` and `h = atan2(b*, a*)` according to Redness-Greenness a and Yellowness-Blueness b in their own coordinates." ] }, { @@ -96,7 +96,7 @@ "## 4. Color Appearance Parameters\n", "\n", "\n", - "We ignore spatial appearance phenomena and consider only the the six color appearance parameters defined by CIECAM02. They can be grouped into three classes, correspond to the three coordinates of LCh:\n", + "We ignore spatial appearance phenomena and consider only the six color appearance parameters defined by CIECAM02. They can be grouped into three classes, corresponding to the three coordinates of LCh:\n", "\n", "- [Brightness](https://en.wikipedia.org/wiki/Brightness) and [lightness](https://en.wikipedia.org/wiki/Lightness): they are the extrinsic and intrinsic \"tones\" or \"values\", respectively.\n", "\n", @@ -124,7 +124,7 @@ "\n", "- *hue h' can encode an additional physical quantity* in an image (when used in this way, the change of hue should be linearly proportional to the quantity);\n", "\n", - "- *hue h' is also ideal in making an image more attractive* without interferencing the representation of pixel values.\n", + "- *hue h' is also ideal for making an image more attractive* without interfering with the representation of pixel values.\n", "\n", "The other dimension chroma is less recognizable and should not be used to encode physical information. Since sRGB is only a subset of the Lab color space, there are human recognizable color that are not displayable. In order to accurately represent the physical quantities,\n", "\n", @@ -190,7 +190,7 @@ "source": [ "Here, we look at three popular warm colormaps: `hot`, `afmhot`, and `inferno`. The thick colorful curves are the lightness J', the black dashed lines are the chroma C', and the black dots are the hue h'.\n", "\n", - "It is clear that the popular `hot` and `afmhot` colormaps are not J'-linear, while `interno` is. It is interesting that both `hot` and `afmhot` are almost linear in the low J' regime, and become flat in the high J' regime---we will have a discuss about this in the next section. The colormaps' peak chroma decreases from `hot`, to `afmhot`, and `inferno`. In layperson's term, this means that `hot` is the \"sharpest\" or \"brightest\" colormap, while `inferno` is the \"flattest\". Finally, according to the hue curve, none of above colormaps is in a single color---they actually transit from red (for `hot` and `afmhot`) or blue (for `inferno`) to yellow in different ways. Also, the `hot` chroma curve is very uneven and not even bi-tonic. It saturates at red and yellow. The `afmhot` chroma is at least bi-tonic. And the `inferno` colormap's chroma is both smooth and bi-tonic.\n", + "It is clear that the popular `hot` and `afmhot` colormaps are not J'-linear, while `inferno` is. It is interesting that both `hot` and `afmhot` are almost linear in the low J' regime, and become flat in the high J' regime---we will have a discussion about this in the next section. The colormaps' peak chroma decreases from `hot`, to `afmhot`, and `inferno`. In layperson's terms, this means that `hot` is the \"sharpest\" or \"brightest\" colormap, while `inferno` is the \"flattest\". Finally, according to the hue curve, none of above colormaps is in a single color---they actually transit from red (for `hot` and `afmhot`) or blue (for `inferno`) to yellow in different ways. Also, the `hot` chroma curve is very uneven and not even bi-tonic. It saturates at red and yellow. The `afmhot` chroma is at least bi-tonic. And the `inferno` colormap's chroma is both smooth and bi-tonic.\n", "\n", "To demonstrate how non-uniform colormaps can lead to faulty feature extraction, we create a pyramid function and plot it with different colormaps. In the ideal situation, our eyes should only pick out the corners in the pyramid. That is, we should pick out a cross \"X\" in the image, in addition to the color gradient." ] @@ -210,7 +210,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The above figure shows the visualization using matplotlib's built-in colormaps. For `hot` and `hot_r`, we artificially see red and yellow squares in them. If we go back to the J'(v) plots, we can identical these squares come from features in J'. These artifacts are much weaker in `afmhot` and `afmhot_r`, although we can still see a yellow, orange, and brown squares them, which correspond to the features in their J' curves. Being J'-linear, the square artifacts are weakest in `inferno` and `inferno_r`, although it is still possible to identify orange and purple squares because of the color transitions.\n", + "The above figure shows the visualization using matplotlib's built-in colormaps. For `hot` and `hot_r`, we artificially see red and yellow squares in them. If we go back to the J'(v) plots, we can identify that these squares come from features in J'. These artifacts are much weaker in `afmhot` and `afmhot_r`, although we can still see a yellow, orange, and brown squares them, which correspond to the features in their J' curves. Being J'-linear, the square artifacts are weakest in `inferno` and `inferno_r`, although it is still possible to identify orange and purple squares because of the color transitions.\n", "\n", "To see how good/bad these colormaps are, let's load up some components of a Principal Component Analysis (PCA) of a numerical simulation of a black hole (see [Medeiros et al. 2018](http://adsabs.harvard.edu/abs/2018ApJ...864....7M)) and plot them in the `inferno`, `hot`, and `afmhot` colormaps." ] @@ -254,7 +254,7 @@ "source": [ "The panels above plot the same images (0th PCA component in top row, 1st PCA component in bottom row) in `hot`, `hot_r`, `afmhot`, `afmhot_r`, `inferno`, and `inferno_r`. The `_r` postfixed colormaps are simply reversed of their non-`_r` counter parts.\n", "\n", - "Although the accretion funnel, shown in light yellow in `hot_r` and `afmhot_r`, is difficult to see in both `hot`, `afmhot`, it is still more visible in the `_r` colormaps than non-`_r` colormaps. Similar effect is also seen in `inferno_r` and `infreno`, where we can identify the brown funnel in `inferno_r` but difficult to pick out the very dark funnel in `inferno`. This is indeed a consequence of our eyes being less sensitive to color in dim light." + "Although the accretion funnel, shown in light yellow in `hot_r` and `afmhot_r`, is difficult to see in both `hot`, `afmhot`, it is still more visible in the `_r` colormaps than non-`_r` colormaps. Similar effect is also seen in `inferno_r` and `inferno`, where we can identify the brown funnel in `inferno_r` but difficult to pick out the very dark funnel in `inferno`. This is indeed a consequence of our eyes being less sensitive to color in dim light." ] }, { @@ -264,7 +264,7 @@ "## 7. Colormap Uniformization\n", "\n", "\n", - "As demostrated by the pyramid function above, non-uniformality in lightness is the main reason of faulty feature extractions from image. To correct for this, we implement a colormap uniformization algorithm in `ehtplot` to redistribute colors in a colormap. The resulting colormap is J'-linear and it contains only color in the original colormap.\n", + "As demonstrated by the pyramid function above, non-uniformity in lightness is the main reason for faulty feature extraction from images. To correct for this, we implement a colormap uniformization algorithm in `ehtplot` to redistribute colors in a colormap. The resulting colormap is J'-linear and it contains only color in the original colormap.\n", "\n", "Actually, whenever `ehtplot` is loaded, there are 364 new colormaps automatically made available to `matplotlib`." ] @@ -283,7 +283,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The colormap loading mechaism is intentionally designed that it needs only `numpy` and `matplotlib`. Even if a user doesn't need the plotting features in `ehtplot`, they can still use its colormaps without installing additional python module.\n", + "The colormap loading mechanism is intentionally designed that it needs only `numpy` and `matplotlib`. Even if a user doesn't need the plotting features in `ehtplot`, they can still use its colormaps without installing additional python module.\n", " \n", "Among the 182 new colormaps, 90 of them are uniformized versions of matplotlib's built-in colormaps. They are postfixed with `_u`. Note that matplotlib's built-in uniform colormaps `viridis`, `plasma`, `inferno`, `magma`, and `cividis` are not linearized.\n", "\n", @@ -322,7 +322,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Although some artifacts can still be identified in `hot` and `hot_r` because of the peaks in the chroma C' curve, they are much weaker (hence good) compare to the top row. In fact, the uniformized `afmhot_u` map `afmhot_ur` shows almost no artifactial square feature, which is in some sense even better than `inferno`.\n", + "Although some artifacts can still be identified in `hot` and `hot_r` because of the peaks in the chroma C' curve, they are much weaker (hence good) compared to the top row. In fact, the uniformized `afmhot_u` map `afmhot_ur` shows almost no artifactual square feature, which is in some sense even better than `inferno`.\n", "\n", "We can perform similar comparison for black hole images." ] @@ -341,7 +341,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Comparing `hot_r` and `afmhot_r` with the uniformized `hot_ur` and `afmhot_ur`, in the high lightness regime, a lot more features (funnel) of the image are now visible. Comparing `hot_u` with `hot_ur` or `afmhot_u` with `afmhot_ur` indications that the same features are not visible in `hot` and `afmhot`. This \"asymmetry\" between low and high lightness suggests that linear in J' is not enough to provide a subjective representation of an image. In fact, the images are more \"symmetric\" in `hot`-`hot_r` and `afmhot`-`afmhot_r`. This is an interesting observation that the flatten top of the `hot` and `afmhot` colormaps actually counter acts the effect they color are less distingisble in dim light.\n", + "Comparing `hot_r` and `afmhot_r` with the uniformized `hot_ur` and `afmhot_ur`, in the high lightness regime, a lot more features (funnel) of the image are now visible. Comparing `hot_u` with `hot_ur` or `afmhot_u` with `afmhot_ur` indications that the same features are not visible in `hot` and `afmhot`. This \"asymmetry\" between low and high lightness suggests that linearity in J' is not enough to provide a subjective representation of an image. In fact, the images are more \"symmetric\" in `hot`-`hot_r` and `afmhot`-`afmhot_r`. This is an interesting observation that the flattened top of the `hot` and `afmhot` colormaps actually counteracts the effect that colors are less distinguishable in dim light.\n", "\n", "Since we want to keep the linearity in high J', this suggests that one way to \"symmetrize\" the colormaps is to lift up the lower bound of J'. Among the colormaps `ehtplot` provides, there are number of them have numbers in their names." ] @@ -392,7 +392,7 @@ "## 8. Colormap Symmetrization\n", "\n", "\n", - "Given that lifting the lightness floor of a colormap cannot completely resolve the asymmetry between high and low lightness, we need to adjust another quality. From the above plot, one of the most distingishable asymmetric feature is the jump in chroma C' near value 1.0. Hence, our next natural modification to matplotlib colormap is to symmetrize chroma C'.\n", + "Given that lifting the lightness floor of a colormap cannot completely resolve the asymmetry between high and low lightness, we need to adjust another quality. From the above plot, one of the most distinguishable asymmetric feature is the jump in chroma C' near value 1.0. Hence, our next natural modification to matplotlib colormap is to symmetrize chroma C'.\n", "\n", "Because sRGB only cover part of the Lab colorspace, it we use standard mathematical symmetrization, i.e., C'' = (C' + revert(C'))/2, then large parts of the symmetrized colormap will become irrenderable. Hence, we take the more conservative approach to use C'' = pointwisemin(C', revert(C')). This makes most parts of the colormap renderable except very few color with high lightness and low chroma. To address these exceptions, we introduce a softening constant and clip the color tables.\n", "\n", @@ -427,7 +427,7 @@ "## A. Appendix: List of Modified Colormaps\n", "\n", "\n", - "The colormaps made available by `ehtplot` are all modifications of `matplotlib`'s built-in colormaps. We list all of them alongside with the original ones in this appendix:" + "The colormaps made available by `ehtplot` are all modifications of `matplotlib`'s built-in colormaps. We list all of them alongside the original ones in this appendix:" ] }, {