figurefirst icon indicating copy to clipboard operation
figurefirst copied to clipboard

support for axis rotation

Open neurochen opened this issue 2 years ago • 1 comments

Thanks for the amazing work on FigureFirst! I am wondering if it's possible to add support for rotation of axis. The original package gives rise to an error if the axis contains a rotation transform. I made some changes to handle the rotation parameter, but the SVG output is not as expected. So, it seemed that there are some other code change requirements somewhere else.

Note that the matrix transform implementation also doesn't work if we modify the matrix using the rotation matrix directly.

Please see below for amendments in svg_to_axes.py

def parse_transform(transform_str):
    """convert transforms into transformation matrix"""
    #print transform_str
    import re
    # regex for extracting numbers from transform string
    scanfloat =  r"[+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?"
    tr = None;tr_pos = None
    mt = None;mt_pos = None
    sc = None;sc_pos = None
    rt = None;rt_pos = None
    ##################
    if 'translate' in transform_str:
        translate_str = re.findall(r'translate\(.*?\)',transform_str)[0]
        txy = re.findall(scanfloat,translate_str)
        if type(txy) is list and len(txy) == 2:
            tx,ty = txy
        else: # deal with rare situation of exact resizing
            tx = txy[0]
            ty = txy[0]
        tr = np.array([[1.,0,float(tx)],
                       [0,1.,float(ty)],
                       [0,0,1.        ]])
        tr_pos = transform_str.find('translate')
    ##################
    if 'scale' in transform_str:
        translate_str = re.findall(r'scale\(.*?\)',transform_str)[0]
        sx,sy = re.findall(scanfloat,translate_str)
        sc = np.array([[float(sx),0,         0],
                       [0,        float(sy), 0],
                       [0,        0,        1.]])
        sc_pos = transform_str.find('scale')
    ##################
    if 'matrix' in transform_str:
        matrix_str = re.findall(r'matrix\(.*?\)',transform_str)[0]
        a,b,c,d,e,f = re.findall(scanfloat,matrix_str)
        a,b,c,d,e,f = [float(s) for s in [a,b,c,d,e,f]]
        mt = np.array([[a,c,e],
                       [b,d,f],
                       [0,0,1.]])
        mt_pos = transform_str.find('matrix')
    ##################
    if 'rotate' in transform_str:
        rotation_str = re.findall(r'rotate\(.*?\)',transform_str)[0]
        theta = re.findall(scanfloat,rotation_str)
        theta = -int(theta[0])/180*np.pi
        cos, sin = np.cos(theta), np.sin(theta)
        rt = np.array([[cos, -sin, 0],
                       [sin,  cos, 0],
                       [  0,    0, 1.]])
        rt_pos = transform_str.find('rotate')
    ##################
    tr_pos = {False:tr_pos,True:0}[tr_pos is None]
    mt_pos = {False:mt_pos,True:0}[mt_pos is None]
    sc_pos = {False:sc_pos,True:0}[sc_pos is None]
    rt_pos = {False:rt_pos,True:0}[rt_pos is None]
    s = [tr_pos,mt_pos,sc_pos,rt_pos]
    def take0(x):
        return x[0]
    trnsfrms = [mtrx for pos,mtrx in sorted(zip(s,[tr,mt,sc,rt]),key =take0)]
    trnsfrms = [m for m in trnsfrms if not(m is None)]
    from numpy import dot
    from functools import reduce
    if len(trnsfrms) >= 1:
        mtrx = reduce(lambda x,y:dot(x,y.T),trnsfrms)
    return mtrx

neurochen avatar Jul 20 '22 14:07 neurochen

I'm glad you're finding the package useful!

Could you give an example image of the template file, what you are hoping the output would look like, and what it does look like? (if github does not allow uploading an image you can email me directly at @.*** )

I am guessing that perhaps you are rotating the rectangle in your template, would like the figure that gets plotted to also be rotated, but instead something else happens? If that is the case, I suspect that some changes would be needed in the code that sticks the matplotlib plot into the svg. Perhaps in the function append_figure_to_layer at line 1305?

  • Floris

On Wed, Jul 20, 2022 at 7:08 AM neurochen @.***> wrote:

Thanks for the amazing work on FigureFirst! I am wondering if it's possible to add support for rotation of axis. The original package gives rise to an error if the axis contains a rotation transform. I made some changes to handle the rotation parameter, but the SVG output is not as expected. So, it seemed that there are some other code change requirements somewhere else.

Please see below for svg_to_axes.py

def parse_transform(transform_str): """convert transforms into transformation matrix""" #print transform_str import re # regex for extracting numbers from transform string scanfloat = r"[+-]?(?:0|[1-9]\d*)(?:.\d*)?(?:[eE][+-]?\d+)?" tr = None;tr_pos = None mt = None;mt_pos = None sc = None;sc_pos = None rt = None;rt_pos = None ################## if 'translate' in transform_str: translate_str = re.findall(r'translate(.?)',transform_str)[0] txy = re.findall(scanfloat,translate_str) if type(txy) is list and len(txy) == 2: tx,ty = txy else: # deal with rare situation of exact resizing tx = txy[0] ty = txy[0] tr = np.array([[1.,0,float(tx)], [0,1.,float(ty)], [0,0,1. ]]) tr_pos = transform_str.find('translate') ################## if 'scale' in transform_str: translate_str = re.findall(r'scale(.?)',transform_str)[0] sx,sy = re.findall(scanfloat,translate_str) sc = np.array([[float(sx),0, 0], [0, float(sy), 0], [0, 0, 1.]]) sc_pos = transform_str.find('scale') ################## if 'matrix' in transform_str: matrix_str = re.findall(r'matrix(.?)',transform_str)[0] a,b,c,d,e,f = re.findall(scanfloat,matrix_str) a,b,c,d,e,f = [float(s) for s in [a,b,c,d,e,f]] mt = np.array([[a,c,e], [b,d,f], [0,0,1.]]) mt_pos = transform_str.find('matrix') ################## if 'rotate' in transform_str: rotation_str = re.findall(r'rotate(.?)',transform_str)[0] theta = re.findall(scanfloat,rotation_str) theta = -int(theta[0])/180*np.pi cos, sin = np.cos(theta), np.sin(theta) rt = np.array([[cos, -sin, 0], [sin, cos, 0], [ 0, 0, 1.]]) rt_pos = transform_str.find('rotate') ################## tr_pos = {False:tr_pos,True:0}[tr_pos is None] mt_pos = {False:mt_pos,True:0}[mt_pos is None] sc_pos = {False:sc_pos,True:0}[sc_pos is None] rt_pos = {False:rt_pos,True:0}[rt_pos is None] s = [tr_pos,mt_pos,sc_pos,rt_pos] def take0(x): return x[0] trnsfrms = [mtrx for pos,mtrx in sorted(zip(s,[tr,mt,sc,rt]),key =take0)] trnsfrms = [m for m in trnsfrms if not(m is None)] from numpy import dot from functools import reduce if len(trnsfrms) >= 1: mtrx = reduce(lambda x,y:dot(x,y.T),trnsfrms) return mtrx

— Reply to this email directly, view it on GitHub https://github.com/FlyRanch/figurefirst/issues/64, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAB4EPCOLE7AIRRLHNUY2KDVVAB4TANCNFSM54DZ7DRA . You are receiving this because you are subscribed to this thread.Message ID: @.***>

-- Floris van Breugel | http://www.florisvanbreugel.com Assistant Professor of Mechanical Engineering & Graduate Program for Neuroscience University of Nevada, Reno

Wildlife and Landscape Photography Galleries: http://www.ArtInNaturePhotography.com/ Blog: http://www.ArtInNaturePhotography.com/wordpress/

florisvb avatar Oct 11 '22 07:10 florisvb