pythonplotly

2D plots in plotly cannot show small variations


I have to plot some kind of graphs to represent the data below:

[[ 0.        , 234.        , 568.33333333, 881.66666667],
 [ 0.        , 234.66888889, 569.44555556, 865.03806017],
 [ 0.        , 235.33627407, 570.06910753, 849.9592539 ],
 [ 0.        , 235.9989178 , 570.2632452 , 836.28943309]]

I tried the below code of plotly.

import numpy as np
from plotly.subplots import make_subplots
import plotly.graph_objects as go
from pathlib import Path
import os
import plotly.io as pio

Smax = 1000
T = 1

classical_2d_without_boundary = np.array([[ 0.        , 234.        , 568.33333333, 881.66666667],
       [ 0.        , 234.66888889, 569.44555556, 865.03806017],
       [ 0.        , 235.33627407, 570.06910753, 849.9592539 ],
       [ 0.        , 235.9989178 , 570.2632452 , 836.28943309]])

n_rows, n_cols = classical_2d_without_boundary.shape
x = np.linspace(0, Smax, n_cols)
y = np.linspace(T, 0, n_rows)

x, y = np.meshgrid(x,y)
fig = make_subplots(rows= 1, cols = 1)
quantum_contour = go.Contour(
    z=classical_2d_without_boundary,
    x=x[0, :],  # assuming x is 2D after meshgrid
    y=y[:, 0],  # assuming y is 2D after meshgrid
    colorscale='Inferno'
   
)

fig.add_trace(quantum_contour, row = 1, col = 1)

fig.update_layout(
title_x=0.5,
title_font = dict(size=40),
xaxis_title="x-axis",
yaxis_title="time (Year)",
height=900,
width=855,  # Earlier it was 750
xaxis_title_font = dict(size=36),  
yaxis_title_font = dict(size= 36),  
legend_title_font= dict(size=36), 
font= dict(size=30), 
paper_bgcolor ='white', 

margin=dict(l=20, r=20, t=350, b=20)  
)
fig.update_xaxes(title_font=dict(size=24))
fig.update_yaxes(title_font=dict(size=24))


for annotation in fig['layout']['annotations']:
    annotation['font'].update(size= 40)
    annotation.update(y=1.02)  # Increase the y value to move the title up

# display
fig.show()

The graph obtained is as below. My problem is that small variations in values along the columns are not at all captured and visible in the graph generated. Can something be done or some other way a 2D graph can be drawn with plotly that even these variations are very clearly visible? enter image description here


Solution

  • One fairly simple and effective way to regularise such data with a huge nearly constant value or linear trend is to subtract off the average value of each column (and/or row) before plotting it as a false colour map. Then you can plot the residuals for analysis after removing the main trend from the data. This makes it much easier to see the fine details that matter.

    Applying that simple operation to your data columns gives the new residuals matrix:

    0   -1.00101999 -1.194477075     23.42831321  
    0   -0.3321311  -0.082254845      6.799706712
    0    0.33525408  0.541297125     -8.279099557
    0    0.99789701  0.735434795    -21.94892037
    

    That will easily plot in a way that makes the variations very clear.

    The other alternative is to use a more sophisticated 256 shades false colour mapping and a colour LUT designed for visualising high dynamic range data. That will not be good enough to show smaller then 1 part in 256 changes in a satisfactory manner without some additional transform of your data. Most times we are looking for faint signals near a baseline so the majority of false colour palettes are designed for that purpose.

    My favourite for this wide range differences is from the Peano-Koch(*) family of space filling curves applied to the RGB colour cube. This can done right render fine details visible in high dynamic range data. It can also produce a mess out of noisy data so beware.

    (*) I have always called it that because that is how it was introduced to me and named in the image processing system but according to Wikipedia it is actually the 3D analogue of the Hilbert curve in a 2^N Cantor space.

    This is a realisation of the Peano_0 CLUT following the edges of the colour cube and my variant with a half twist to get black and white at opposite ends.

    Peano-Koch (Hilbert) curve on Colour cube

    The generating rules for a 252 length CLUT (4 entries are unused in this version) is:

     // Where N = CLUT index [0..252]
     short segment = (N-1)/36;
     short k = 1 + ((N-1) % 36); // range from 1 to 36
     short V = (255*k+18)/36;     
    
    Segment Colour R G B
    -1 black 0 0 0
    0 blue 0 0 V
    1 magenta V 0 255
    2 red 255 0 255-V
    3 yellow 255 V 0
    4 white 255 255 V
    5 cyan 255-V 255 255
    6 green 0 255 255 - V

    Looking at it I'm fairly sure we tweaked the simple linear table with some additional non-linear terms and a bit of extra luminance to make every step a just noticeable difference. That isn't quite possible with a linear step size. The saturated colours and black tend to look too much alike and the shades of orange-yellow too different otherwise. I can't recall the fiddle factors but I think the extra 4 entries were used on the segments which showed the most steplike behaviour.

    Alter rules 4,5,6 to obtain the alternative more pleasing variant. References to this once popular image processing trick are very thin on the ground. Nearest I found was this SPIEE Peano curve which is about a decade after the first one I still remember seeing by a researcher Steve Burch from Harwell. Obviously the starting colour blue is arbitrary could equally be red or green.

    In my search I did stumble upon the Fortran code for another family of high dynamic range false colour astronomical LUT which have the property of preserving luminance if you choose your parameters wisely. This one originally due to John Fielden was written up by his colleague David Green as "A colour scheme for displaying astronomical images" and is in CASA and AIPS as well as the much older Starlink software. It is decades since I last worked on this stuff.