Commit 56d76cec authored by Mihai Baltac's avatar Mihai Baltac
Browse files

re-factoring fixes; marker defaults; colormaps for heatmaps; added plot functions in figure_base

parent 6e832c74
Pipeline #11889 failed with stage
in 9 minutes and 54 seconds
from descriptors import *
from plots import *
from figures import *
from colormap import *
\ No newline at end of file
from colormap import Colormap
import colormaps
\ No newline at end of file
from nifty.plotting.plotly_wrapper import PlotlyWrapper
class Colormap(PlotlyWrapper):
def __init__(self, name, red, green, blue):
self.name = name
self.red = red
self.green = green
self.blue = blue
def validate_map(self):
def validade(m):
#TODO: implement validation
pass
@staticmethod
def from_matplotlib_colormap_internal(name, mpl_cmap): # no discontinuities only
red = [(c[0], c[2]) for c in mpl_cmap['red']]
green = [(c[0], c[2]) for c in mpl_cmap['green']]
blue = [(c[0], c[2]) for c in mpl_cmap['blue']]
return Colormap(name, red, green, blue)
def to_plotly(self):
r, g, b = 0, 0, 0
converted = list()
prev_split, prev_r, prev_g, prev_b = 0., 0., 0., 0.
while prev_split < 1:
next_split = min(self.red[r][0], self.blue[b][0], self.green[g][0])
if next_split == self.red[r][0]:
red_val = self.red[r][1]
r += 1
else:
slope = (self.red[r][1]-prev_r) / (self.red[r][0] - prev_split)
y = prev_r - slope * prev_split
red_val = slope * next_split + y
if next_split == self.green[g][0]:
green_val = self.green[g][1]
g += 1
else:
slope = (self.green[g][1] - prev_g) / (self.green[g][0] - prev_split)
y = prev_g - slope * prev_split
green_val = slope * next_split + y
if next_split == self.blue[b][0]:
blue_val = self.blue[b][1]
b += 1
else:
slope = (self.blue[b][1] - prev_b) / (self.blue[b][0] - prev_split)
y = prev_r - slope * prev_split
blue_val = slope * next_split + y
prev_split, prev_r, prev_g, prev_b = next_split, red_val, green_val, blue_val
converted.append([next_split,
'rgb(' +
str(int(red_val*255)) + "," +
str(int(green_val*255)) + "," +
str(int(blue_val*255)) + ")"])
return converted
from nifty.plotting.colormap.colormap import Colormap
def HighEnergyCmap():
"""
Returns a color map often used in High Energy Astronomy.
"""
red = [(0.0, 0.0),
(0.167, 0.0),
(0.333, 0.5),
(0.5, 1.0),
(0.667, 1.0),
(0.833, 1.0),
(1.0, 1.0)]
green = [(0.0, 0.0),
(0.167, 0.0),
(0.333, 0.0),
(0.5, 0.0),
(0.667, 0.5),
(0.833, 1.0),
(1.0, 1.0)]
blue = [(0.0, 0.0),
(0.167, 1.0),
(0.333, 0.5),
(0.5, 0.0),
(0.667, 0.0),
(0.833, 0.0),
(1.0, 1.0)]
return Colormap("High Energy", red, green, blue)
def FaradayMapCmap():
"""
Returns a color map used in reconstruction of the "Faraday Map".
References
----------
.. [#] N. Opermann et. al.,
"An improved map of the Galactic Faraday sky",
Astronomy & Astrophysics, Volume 542, id.A93, 06/2012;
`arXiv:1111.6186 <http://www.arxiv.org/abs/1111.6186>`_
"""
red = [(0.0, 0.35),
(0.1, 0.4),
(0.2, 0.25),
(0.41, 0.47),
(0.5, 0.8),
(0.56, 0.96),
(0.59, 1.0),
(0.74, 0.8),
(0.8, 0.8),
(0.9, 0.5),
(1.0, 0.4)]
green = [(0.0, 0.0),
(0.2, 0.0),
(0.362, 0.88),
(0.5, 1.0),
(0.638, 0.88),
(0.8, 0.25),
(0.9, 0.3),
(1.0, 0.2)]
blue = [(0.0, 0.35),
(0.1, 0.4),
(0.2, 0.8),
(0.26, 0.8),
(0.41, 1.0),
(0.44, 0.96),
(0.5, 0.8),
(0.59, 0.47),
(0.8, 0.0),
(1.0, 0.0)]
return Colormap("Faraday Map", red, green, blue)
def FaradayUncertaintyCmap():
"""
Returns a color map used for the "Faraday Map Uncertainty".
References
----------
.. [#] N. Opermann et. al.,
"An improved map of the Galactic Faraday sky",
Astronomy & Astrophysics, Volume 542, id.A93, 06/2012;
`arXiv:1111.6186 <http://www.arxiv.org/abs/1111.6186>`_
"""
red = [(0.0, 1.0),
(0.1, 0.8),
(0.2, 0.65),
(0.41, 0.6),
(0.5, 0.7),
(0.56, 0.96),
(0.59, 1.0),
(0.74, 0.8),
(0.8, 0.8),
(0.9, 0.5),
(1.0, 0.4)]
green = [(0.0, 0.9),
(0.2, 0.65),
(0.362, 0.95),
(0.5, 1.0),
(0.638, 0.88),
(0.8, 0.25),
(0.9, 0.3),
(1.0, 0.2)]
blue = [(0.0, 1.0),
(0.1, 0.8),
(0.2, 1.0),
(0.41, 1.0),
(0.44, 0.96),
(0.5, 0.7),
(0.59, 0.42),
(0.8, 0.0),
(1.0, 0.0)]
return Colormap("Faraday Uncertainty", red, green, blue)
def PlusMinusCmap():
"""
Returns a color map useful for a zero-centerd range of values.
"""
red = [(0.0, 1.0),
(0.1, 0.96),
(0.2, 0.84),
(0.3, 0.64),
(0.4, 0.36),
(0.5, 0.0),
(0.6, 0.0),
(0.7, 0.0),
(0.8, 0.0),
(0.9, 0.0),
(1.0, 0.0)]
green = [(0.0, 0.5),
(0.1, 0.32),
(0.2, 0.18),
(0.3, 0.08),
(0.4, 0.02),
(0.5, 0.0),
(0.6, 0.02),
(0.7, 0.08),
(0.8, 0.18),
(0.9, 0.32),
(1.0, 0.5)]
blue = [(0.0, 0.0),
(0.1, 0.0),
(0.2, 0.0),
(0.3, 0.0),
(0.4, 0.0),
(0.5, 0.0),
(0.6, 0.36),
(0.7, 0.64),
(0.8, 0.84),
(0.9, 0.96),
(1.0, 1.0)]
return Colormap("Plus Minus", red, green, blue)
def PlankCmap():
"""
Returns a color map similar to the one used for the "Planck CMB Map".
"""
red = [(0.0, 0.0),
(0.1, 0.0),
(0.2, 0.0),
(0.3, 0.0),
(0.4, 0.0),
(0.5, 1.0),
(0.6, 1.0),
(0.7, 1.0),
(0.8, 0.83),
(0.9, 0.67),
(1.0, 0.5)]
green = [(0.0, 0.0),
(0.1, 0.0),
(0.2, 0.0),
(0.3, 0.3),
(0.4, 0.7),
(0.5, 1.0),
(0.6, 0.7),
(0.7, 0.3),
(0.8, 0.0),
(0.9, 0.0),
(1.0, 0.0)]
blue = [(0.0, 0.5),
(0.1, 0.67),
(0.2, 0.83),
(0.3, 1.0),
(0.4, 1.0),
(0.5, 1.0),
(0.6, 0.0),
(0.7, 0.0),
(0.8, 0.0),
(0.9, 0.0),
(1.0, 0.0)]
return Colormap("Planck-like", red, green, blue)
......@@ -7,6 +7,7 @@ from nifty.plotting.plots import Heatmap, Mollweide
class Figure2D(FigureFromPlot):
def __init__(self, plots, title=None, width=None, height=None,
xaxis=None, yaxis=None):
super(Figure2D, self).__init__(plots, title, width, height)
# TODO: add sanitization of plots input
if isinstance(plots[0], Heatmap) and not width and not height:
......@@ -45,7 +46,7 @@ class Figure2D(FigureFromPlot):
showticklabels=False
)
if self.yaxis:
plotly_object['layout']['yaxis'] = self.yaxis._to_plotly()
plotly_object['layout']['yaxis'] = self.yaxis.to_plotly()
elif not self.yaxis:
plotly_object['layout']['yaxis'] = dict(showline=False)
......
# -*- coding: utf-8 -*-
import os
from PIL import Image
import plotly.offline as ply_offline
import plotly.plotly as ply
from nifty.plotting.plotly_wrapper import PlotlyWrapper
......@@ -8,3 +16,29 @@ class FigureBase(PlotlyWrapper):
self.title = title
self.width = width
self.height = height
def plot(self, filename=None, interactive=False):
if not filename:
filename = os.path.abspath('/tmp/temp-plot.html')
if interactive:
try:
__IPYTHON__
ply_offline.init_notebook_mode(connected=True)
ply_offline.iplot(self.to_plotly(), filename=filename)
except NameError:
ply_offline.plot(self.to_plotly(), filename=filename)
raise Warning('IPython not active! Running without interactive mode.')
else:
ply_offline.plot(self.to_plotly(), filename=filename)
def plot_image(self, filename=None, show=False):
if not filename:
filename = os.path.abspath('temp-plot.jpeg')
ply_obj = self.to_plotly()
ply.image.save_as(ply_obj, filename=filename)
if show:
img = Image.open(filename)
img.show()
# -*- coding: utf-8 -*-
import numpy as np
from nifty import dependency_injector as gdi
from figure_base import FigureBase
from figure_3D import Figure3D
plotly = gdi.get('plotly')
# TODO: add nice height and width defaults for multifigure
class MultiFigure(FigureBase):
def __init__(self, rows, columns, subfigures=None,
title=None, width=None, height=None):
def __init__(self, rows, columns, title=None, width=None, height=None,
subfigures=None):
if 'plotly' not in gdi:
raise ImportError("The module plotly is needed but not available.")
super(MultiFigure, self).__init__(title, width, height)
......@@ -31,42 +30,37 @@ class MultiFigure(FigureBase):
self.subfigures[row, column] = figure
def to_plotly(self):
sub_titles = self.subfigures.copy()
sub_titles = sub_titles.flatten
title_extractor = lambda z: z.title
sub_titles = np.vectorize(title_extractor)(sub_titles)
sub_specs = self.subfigures.copy_empty()
specs_setter = \
lambda z: {'is_3d': True} if isinstance(z, Figure3D) else {}
sub_specs = np.vectorize(specs_setter)(sub_specs)
title_extractor = lambda z: z.title if z else ""
sub_titles = tuple(np.vectorize(title_extractor)(self.subfigures.flatten()))
specs_setter = lambda z: {'is_3d': True} if isinstance(z, Figure3D) else {}
sub_specs = list(map(list, np.vectorize(specs_setter)(self.subfigures)))
multi_figure_plotly_object = plotly.tools.make_subplots(
self.rows,
self.columns,
subplot_titles=sub_titles,
specs=sub_specs)
#TODO resolve bug with titles and 3D subplots
for index, fig in np.ndenumerate(self.subfigures):
for plot in fig.plots:
multi_figure_plotly_object.append_trace(plot.to_plotly(),
index[0]+1,
index[1]+1)
if fig:
for plot in fig.plots:
multi_figure_plotly_object.append_trace(plot.to_plotly(),
index[0]+1,
index[1]+1)
multi_figure_plotly_object['layout'].update(height=self.height,
width=self.width,
title=self.title)
return multi_figure_plotly_object
@staticmethod
def from_figures_2cols(figures, title=None, width=None, height=None):
multi_figure = MultiFigure((len(figures)+1)/2, 2, title, width, height)
for i in range(0, len(figures), 2):
multi_figure.add_subfigure(figures[i], i/2, 0)
for i in range(1, len(figures), 2):
multi_figure.add_subfigure(figures[i], i/2, 1)
def from_figures_cols(figures, cols=2, title=None, width=None, height=None):
multi_figure = MultiFigure((len(figures) + cols -1)/cols , cols, title, width, height)
for i in range(len(figures)):
multi_figure.add_subfigure(figures[i], i/cols, i%cols)
return multi_figure
......
# -*- coding: utf-8 -*-
from nifty.plotting.plots.plot import Plot
from nifty.plotting.plotly_wrapper import PlotlyWrapper
class Heatmap(Plot):
def __init__(self, data, label='', line=None, marker=None, webgl=False,
class Heatmap(PlotlyWrapper):
def __init__(self, data, color_map=None, webgl=False,
smoothing=False): # smoothing 'best', 'fast', False
super(Heatmap, self).__init__(label, line, marker)
self.data = data
self.color_map = color_map
self.webgl = webgl
self.smoothing = smoothing
def to_plotly(self):
plotly_object = super(Heatmap, self).to_plotly()
plotly_object = dict()
plotly_object['z'] = self.data
plotly_object['showscale'] = False
if self.color_map:
plotly_object['colorscale'] = self.color_map.to_plotly()
plotly_object['colorbar'] = dict(title=self.color_map.name, x=0.42)
if self.webgl:
plotly_object['type'] = 'heatmapgl'
else:
......
......@@ -8,7 +8,7 @@ healpy = gdi.get('healpy')
class Mollweide(Heatmap):
def __init__(self, data, label='', line=None, marker=None, webgl=False,
def __init__(self, data, color_map=None, webgl=False,
smoothing=False): # smoothing 'best', 'fast', False
if 'pylab' not in gdi:
raise ImportError("The module pylab is needed but not available.")
......@@ -16,8 +16,7 @@ class Mollweide(Heatmap):
raise ImportError("The module healpy is needed but not available.")
data = self._mollview(data)
super(Mollweide, self).__init__(data, label, line, marker, webgl,
smoothing)
super(Mollweide, self).__init__(data, color_map, webgl, smoothing)
def _mollview(self, x, xsize=800):
x = healpy.pixelfunc.ma_to_array(x)
......
......@@ -2,13 +2,15 @@
from abc import abstractmethod
from nifty.plotting.plotly_wrapper import PlotlyWrapper
from nifty.plotting.descriptors import Marker
class Plot(PlotlyWrapper):
def __init__(self, label, line, marker):
self.label = label
self.line = line
self.marker = marker
if not self.line and not self.marker:
self.marker = Marker()
@abstractmethod
def to_plotly(self):
......@@ -19,10 +21,10 @@ class Plot(PlotlyWrapper):
ply_object['line'] = self.line.to_plotly()
ply_object['marker'] = self.marker.to_plotly()
elif self.line:
ply_object['mode'] = 'markers'
ply_object['mode'] = 'line'
ply_object['line'] = self.line.to_plotly()
elif self.marker:
ply_object['mode'] = 'line'
ply_object['mode'] = 'markers'
ply_object['marker'] = self.marker.to_plotly()
return ply_object
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment