Source code for scri.plotting

# Copyright (c) 2015, Michael Boyle
# See LICENSE file for details: <https://github.com/moble/spherical_functions/blob/master/LICENSE>

import numpy as np
from matplotlib import scale as mscale
from matplotlib import transforms as mtransforms
from matplotlib.ticker import MaxNLocator


[docs] class WaveformTimeScale(mscale.ScaleBase): name = "merger_zoom" def __init__(self, axis, **kwargs): mscale.ScaleBase.__init__(self, axis) self.t_initial = float(kwargs.pop("t_initial", 0.0)) self.t_merger = float(kwargs.pop("t_merger")) self.t_ringdown = float(kwargs.pop("t_ringdown")) self.t_final = float(kwargs.pop("t_final")) self.merger_stretch = float( kwargs.pop("merger_stretch", 0.75 * (self.t_final - self.t_initial) / (self.t_ringdown - self.t_merger)) )
[docs] def get_transform(self): return self.WaveformTimeTransform( self.merger_stretch, self.t_initial, self.t_merger, self.t_ringdown, self.t_final )
[docs] def set_default_locators_and_formatters(self, axis): class StretchingLocator(MaxNLocator): def __init__(self, t_initial, t_merger, t_ringdown, t_final): MaxNLocator.__init__(self, nbins=9, steps=[1, 2, 5, 10]) self.t_initial = t_initial self.t_merger = t_merger self.t_ringdown = t_ringdown self.t_final = t_final def tick_values(self, vmin, vmax): self.set_params(nbins=6, prune=None) ticks = list(super().tick_values(max(vmin, self.t_initial), min(vmax, self.t_merger))) self.set_params(nbins=11 - len(ticks), prune="both") ticks += list(super().tick_values(max(vmin, self.t_merger), min(vmax, self.t_ringdown))) self.set_params(nbins=9, prune=None) return np.array(ticks) axis.set_major_locator(StretchingLocator(self.t_initial, self.t_merger, self.t_ringdown, self.t_final))
[docs] def limit_range_for_scale(self, vmin, vmax, minpos): return max(vmin, self.t_initial), min(vmax, self.t_final)
[docs] class WaveformTimeTransform(mtransforms.Transform): input_dims = 1 output_dims = 1 is_separable = True has_inverse = True def __init__(self, merger_stretch, t_initial, t_merger, t_ringdown, t_final): mtransforms.Transform.__init__(self) self.merger_stretch, self.t_initial, self.t_merger, self.t_ringdown, self.t_final = ( merger_stretch, t_initial, t_merger, t_ringdown, t_final, )
[docs] def transform_non_affine(self, a): return np.piecewise( a, [(a < self.t_merger), (a >= self.t_merger) & (a < self.t_ringdown), a >= self.t_ringdown], [ lambda x: x, lambda x: self.t_merger + self.merger_stretch * (x - self.t_merger), lambda x: (self.merger_stretch - 1) * (self.t_ringdown - self.t_merger) + x, ], )
[docs] def inverted(self): return WaveformTimeScale.InvertedWaveformTimeTransform( self.merger_stretch, self.t_initial, self.t_merger, self.t_ringdown, self.t_final )
[docs] class InvertedWaveformTimeTransform(mtransforms.Transform): input_dims = 1 output_dims = 1 is_separable = True has_inverse = True def __init__(self, merger_stretch, t_initial, t_merger, t_ringdown, t_final): mtransforms.Transform.__init__(self) self.merger_stretch, self.t_initial, self.t_merger, self.t_ringdown, self.t_final = ( merger_stretch, t_initial, t_merger, t_ringdown, t_final, )
[docs] def transform_non_affine(self, f_a): return np.piecewise( f_a, [ (f_a < self.t_merger), ( (f_a >= (1 - self.merger_stretch) * self.t_merger + self.merger_stretch * self.t_merger) & (f_a < (1 - self.merger_stretch) * self.t_merger + self.merger_stretch * self.t_ringdown) ), f_a >= self.merger_stretch * self.t_ringdown - (self.merger_stretch - 1) * (self.t_merger), ], [ lambda x: x, lambda x: (x - (1 - self.merger_stretch) * self.t_merger) / self.merger_stretch, lambda x: x - (self.merger_stretch - 1) * (self.t_ringdown - self.t_merger), ], )
[docs] def inverted(self): return WaveformTimeScale.WaveformTimeTransform( self.merger_stretch, self.t_initial, self.t_merger, self.t_ringdown, self.t_final )
mscale.register_scale(WaveformTimeScale)