Source code for lfd.analysis.profiles.convolution

"""This module contains various convolution functionality specifically suited
to work with provided convolutional objects.

"""
import inspect
import itertools

import numpy as np
from scipy import signal

from lfd.analysis.profiles.convolutionobj import ConvolutionObject
from lfd.analysis.profiles import consts
from lfd.analysis.profiles.objectprofiles import *
from lfd.analysis.profiles.seeing import *
from lfd.analysis.profiles.defocusing import *

__all__ = ["largest_common_scale", "convolve_seeing", "convolve_defocus",
           "convolve_seeing_defocus", "convolve"]


[docs]def largest_common_scale(*args): """Finds the new appropriate common scale between given objects such that the new boundaries start at the leftmost and end at the rightmost object and the step between two points is the smallest step value for all objects. It is very important that the scale of the two convolved functions is the same! F.e. convolving a functions with scale lengths of 1 arcsecond and 1 degree is drastically different than convolving functions with the same scale length. Parameters ---------- *args : list, tuple set of objects we wish to reduce to the largest common scale Example ------- >>> newscale = largest_common_scale(obj1, obj2, obj3, ...) """ left = min([obj.scaleleft for obj in args]) right = max([obj.scaleright for obj in args]) step = min([obj.step for obj in args]) newscale = np.arange(1.1*left, 1.1*right, step) return newscale
def convolve_two(obj1, obj2, name="convolved"): """Rescales, normalizes and convolves two ConvolutionObjects. Parameters ---------- obj1 : lfd.analysis.profile.ConvolutionObject first object to be convolved obj2 : lfd.analysis.profile.ConvolutionObject second object to be convolved name : str ConvolutionObjects can be assigned names, or will default to an appropriate name based on instantiation, which helps with tracking the current object status and with plotting. """ newscale = largest_common_scale(obj1, obj1) obj1.rescale(newscale) obj2.rescale(newscale) obj1.norm() obj2.norm() conv = signal.fftconvolve(obj1.obj, obj2.obj) return ConvolutionObject.fromConvolution(conv, newscale, name) def convolve_three(obj1, obj2, obj3, name="convolved"): """Rescales, normalizes and then convolves three ConvolutionObjects. Parameters ---------- obj1 : lfd.analysis.profile.ConvolutionObject first object to be convolved, usually starting profile obj2 : lfd.analysis.profile.ConvolutionObject second object to be convolved, usually seeing obj3 : lfd.analysis.profile.ConvolutionObject second object to be convolved, usually defocusing effects name : str ConvolutionObjects can be assigned names, or will default to an appropriate name based on instantiation, which helps with tracking the current object status and with plotting. """ newscale = largest_common_scale(obj1, obj2, obj3) obj1.rescale(newscale) obj2.rescale(newscale) obj3.rescale(newscale) obj1.norm() obj2.norm() obj3.norm() convs = signal.fftconvolve(obj1.obj, obj2.obj) convs = ConvolutionObject.fromConvolution(convs, newscale) convsd = signal.fftconvolve(convs.obj, obj3.obj) return ConvolutionObject.fromConvolution(convsd, newscale, name)
[docs]def convolve_seeing(obj, seeing, name="seeing-convolved"): """Rescales, normalizes and convolves object and seeing. Parameters ---------- obj : lfd.analysis.profile.ConvolutionObject brightness profile of object to be convolved obj2 : lfd.analysis.profile.ConvolutionObject seeing profile that will be convolved with object name : str ConvolutionObjects can be assigned names, or will default to an appropriate name based on instantiation, which helps with tracking the current object status and with plotting. """ return convolve_two(obj, seeing, name)
[docs]def convolve_defocus(obj, defocus, name="defocus-convolved"): """Rescales, normalizes and convolves object and defocus. Parameters ---------- obj : lfd.analysis.profile.ConvolutionObject brightness profile of object to be convolved defocus : lfd.analysis.profile.ConvolutionObject defocus profile that will be convolved with object name : str ConvolutionObjects can be assigned names, or will default to an appropriate name based on instantiation, which helps with tracking the current object status and with plotting. """ return convolve_two(obj, defocus, name)
[docs]def convolve_seeing_defocus(obj, seeing, defocus, name="seeing-defocus-convolved"): """Rescales, normalizes and then convolves object, seeing and defocus. Parameters ---------- obj : lfd.analysis.profile.ConvolutionObject brightness profile of object to be convolved defocus : lfd.analysis.profile.ConvolutionObject defocus profile that will be convolved with object seeing : lfd.analysis.profile.ConvolutionObject seeing profile that will be convolved with the previous convolution result name : str ConvolutionObjects can be assigned names, or will default to an appropriate name based on instantiation, which helps with tracking the current object status and with plotting. """ return convolve_three(obj, seeing, defocus, name)
[docs]def convolve(*args, name=None): """Rescales, normalizes and convolves the provided ConvolutionObjects. Functionality applied in convolve_seeing/defocus or convolve_seeing_defocus functions is used when two or three ConvolutionObjects are provided. Otherwise the convolution is performed recursively which can be slow. Parameters ---------- *args : tuple, list set of objects that will be convolved name : str ConvolutionObjects can be assigned names, or will default to an appropriate name based on instantiation, which helps with tracking the current object status and with plotting. If left None will default to "convolved" Example ------- >>> convolve(obj, seeing, defocus) """ # with the changes on Jan 2018 this achieves 500x speedups over previous # recursive convolutions and 2x speedups over specified convolutions # as the scales increase speedup increases as previously map depended on N # elements. if len(args) == 2: return convolve_two(*args, name=name) if len(args) == 3: return convolve_three(*args, name=name) newscale = largest_common_scale(*args) for obj in args: obj.rescale(newscale) obj.norm() def recursion(index=1, result=args[0]): if index == len(args): return result else: result = signal.fftconvolve(result.obj, args[index].obj) result = ConvolutionObject.fromConvolution(result, newscale, name) return recursion(index+1, result) return recursion()