• <bdo id='B6INX'></bdo><ul id='B6INX'></ul>
    <tfoot id='B6INX'></tfoot>

      <legend id='B6INX'><style id='B6INX'><dir id='B6INX'><q id='B6INX'></q></dir></style></legend>
      <i id='B6INX'><tr id='B6INX'><dt id='B6INX'><q id='B6INX'><span id='B6INX'><b id='B6INX'><form id='B6INX'><ins id='B6INX'></ins><ul id='B6INX'></ul><sub id='B6INX'></sub></form><legend id='B6INX'></legend><bdo id='B6INX'><pre id='B6INX'><center id='B6INX'></center></pre></bdo></b><th id='B6INX'></th></span></q></dt></tr></i><div id='B6INX'><tfoot id='B6INX'></tfoot><dl id='B6INX'><fieldset id='B6INX'></fieldset></dl></div>
    1. <small id='B6INX'></small><noframes id='B6INX'>

      复制 matplotlib 艺术家

      时间:2023-08-31

      <small id='Oj70I'></small><noframes id='Oj70I'>

          <legend id='Oj70I'><style id='Oj70I'><dir id='Oj70I'><q id='Oj70I'></q></dir></style></legend>
        • <i id='Oj70I'><tr id='Oj70I'><dt id='Oj70I'><q id='Oj70I'><span id='Oj70I'><b id='Oj70I'><form id='Oj70I'><ins id='Oj70I'></ins><ul id='Oj70I'></ul><sub id='Oj70I'></sub></form><legend id='Oj70I'></legend><bdo id='Oj70I'><pre id='Oj70I'><center id='Oj70I'></center></pre></bdo></b><th id='Oj70I'></th></span></q></dt></tr></i><div id='Oj70I'><tfoot id='Oj70I'></tfoot><dl id='Oj70I'><fieldset id='Oj70I'></fieldset></dl></div>

              <tbody id='Oj70I'></tbody>

              <bdo id='Oj70I'></bdo><ul id='Oj70I'></ul>
                <tfoot id='Oj70I'></tfoot>
              1. 本文介绍了复制 matplotlib 艺术家的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                问题描述

                I created an array of Line2D-objects with matplotlib that I'd like to use in various plots. However, using the same artist in multiple plots doesn't work since I get:

                RuntimeError: Can not put single artist in more than one figure
                

                As I found out, the artists once attached to an axis, cannot be attached to another anymore. Well, my idea was to simply copy the array containing the lines with copy() but it won't work. The copied array still refers to the same objects. I suppose, that is because you simply cannot copy artists (?).

                Is there any way to avoid the recalculation of the Line2Ds and to only have to calculate them once?

                解决方案

                I so dearly wish there was a copy method in the Artist Class of matplotlibs!

                Perhaps, someone wants to adapt the code below into the Artist Class in order to have a kind of transfer method to copy one Artist object into another.

                Wrong way to go

                Using the standard copy or deepcopy functions for objects in the package copy does not work.

                For instance, it is useless to script:

                import matplotlib.pyplot as plt
                import numpy as np
                import copy
                
                x = np.linspace(0, 2*np.pi, 100)
                
                fig  = plt.figure()
                ax1 = plt.subplot(211)
                ax2 = plt.subplot(212)
                
                # create a Line2D object
                line1, = ax1.plot(x, np.sin(x))
                
                # copy the Line2D object 
                line2 = copy.deepcopy(line1) #ERROR!
                

                Solutions:

                So, the only way I found to copy an Artist object, is to create an empty object of the desired type, and then transfer via loop all necessary attributes from the original object into the new created one.

                The tool to transfer attributes values from one object to the other is this function I defined:

                # -- Function to attributes copy
                #It copies the attributes given in attr_list (a sequence of the attributes names as
                #  strings) from the object 'obj1' into the object 'obj2'
                #It should work for any objects as long as the attributes are accessible by
                # 'get_attribute' and 'set_attribute' methods.
                
                def copy_attributes(obj2, obj1, attr_list):
                        for i_attribute  in attr_list:
                            getattr(obj2, 'set_' + i_attribute)( getattr(obj1, 'get_' + i_attribute)() )
                

                In this function the most important parameter is attr_list. This is a list of the names of the attributes that we want to copy from obj1 into obj2, for example, for an object Artist.Line2D, it could be attr_list = ('xdata', 'ydata', 'animated', 'antialiased', 'color', 'dash_capstyle', 'dash_joinstyle', 'drawstyle')

                As any Artist object has different attributes, the key in this transfer process is to generate the list of attributes names with the right attributes to be transferred.

                There are two ways to generate the list of the attributes names:

                • First option: we specify the attributes to be selected. That is, we hard code a list with all attributes we want to transfer. It is more arduous than the second option. We have to fully specify the attributes for every type of object: these are usually long lists. It is only recommendable, when we deal with only one type of Artist object.

                • Second option: we specify the attributes that are not selected. That is, we write an "exceptions list" with the attributes that we do not want to transfer, we automatically choose all transferable attributes of the object, but those in our "exception list". This is the quickest option, and we can use it with different types of Artist objects simultaneously.

                First option: specifying the list of transferred attributes

                We just write an assignment to define the list of attributes we want to transfer, as we have shown above.

                The drawback of this option, is that it cannot be immediately extended to different Artist objects, for instance, Line2D and Circle. Because we have to hard code different lists of attributes names, one for each type of Artist object.

                Full Example

                I show an example for Line2D Artist class, as in the question specified.

                import matplotlib.pyplot as plt
                import numpy as np
                
                # -- Function to attributes copy
                #It copies the attributes given in attr_list (a sequence of the attributes names as
                #  strings) from the object 'obj1' into the object 'obj2'
                #It should work for any objects as long as the attributes are accessible by
                # 'get_attribute' and 'set_attribute' methods.
                def copy_attributes(obj2, obj1, attr_list):
                    for i_attribute  in attr_list:
                        getattr(obj2, 'set_' + i_attribute)( getattr(obj1, 'get_' + i_attribute)() )
                
                #Creating a figure with to axes
                fig  = plt.figure()
                ax1 = plt.subplot(211)
                ax2 = plt.subplot(212)
                plt.tight_layout() #Tweak to improve subplot layout
                
                #create a Line2D object 'line1' via plot
                x = np.linspace(0, 2*np.pi, 100)
                line1, = ax1.plot(x, np.sin(x))
                
                ax1.set_xlabel('line1 in ax1') #Labelling axis
                
                #Attributes of the old Line2D object that must be copied to the new object
                #It's just a strings list, you can add or take away attributes to your wishes
                copied_line_attributes = ('xdata', 'ydata', 'animated', 'antialiased', 'color',  
                                    'dash_capstyle', 'dash_joinstyle', 
                                    'drawstyle', 'fillstyle', 'linestyle', 'linewidth',
                                    'marker', 'markeredgecolor', 'markeredgewidth', 'markerfacecolor',
                                    'markerfacecoloralt', 'markersize', 'markevery', 'pickradius',
                                    'solid_capstyle', 'solid_joinstyle', 'visible', 'zorder')
                
                #Creating an empty Line2D object
                line2 = plt.Line2D([],[])
                
                #Copying the list of attributes 'copied_line_attributes' of line1 into line2
                copy_attributes(line2, line1, copied_line_attributes)
                
                #Setting the new axes ax2 with the same limits as ax1
                ax2.set_xlim(ax1.get_xlim())
                ax2.set_ylim(ax1.get_ylim())
                
                #Adding the copied object line2 to the new axes
                ax2.add_artist(line2)
                
                ax2.set_xlabel('line2 in ax2') #Labelling axis
                
                plt.show()
                

                Output

                Second Option: specifying the list of NOT transferred attributes

                In this case, we specify the names of the attributes, that we do not want to transfer: we make a exception list. We gather automatically all transferable attributes of the Artist object and exclude the names of our exception list.

                The advantage is that usually for different Artist objects the excluded attributes are the same short list and, consequently, this option can be more quickly scripted. In the example below, the list is as short as except_attributes = ('transform', 'figure')

                The key function in this case is list_transferable_attributes as shown below:

                #Returns a list of the transferable attributes, that is the attributes having
                # both a 'get' and 'set' method. But the methods in 'except_attributes' are not
                # included
                def list_transferable_attributes(obj, except_attributes):
                    obj_methods_list = dir(obj)
                
                    obj_get_attr = []
                    obj_set_attr = []
                    obj_transf_attr =[]
                
                    for name in obj_methods_list:
                        if len(name) > 4:
                            prefix = name[0:4]
                            if prefix == 'get_':
                                obj_get_attr.append(name[4:])
                            elif prefix == 'set_':
                                obj_set_attr.append(name[4:])
                
                    for attribute in obj_set_attr:
                        if attribute in obj_get_attr and attribute not in except_attributes:
                            obj_transf_attr.append(attribute)
                
                    return obj_transf_attr
                

                Full Example

                import matplotlib.pyplot as plt
                import numpy as np
                
                # -- Function to copy, or rather, transfer, attributes
                #It copies the attributes given in attr_list (a sequence of the attributes names as
                #  strings) from the object 'obj1' into the object 'obj2'
                #It should work for any objects as long as the attributes are accessible by
                # 'get_attribute' and 'set_attribute' methods.
                def copy_attributes(obj2, obj1, attr_list):
                    for i_attribute  in attr_list:
                        getattr(obj2, 
                                'set_' + i_attribute)( getattr(obj1, 'get_' + i_attribute)() )
                
                # #Returns a list of pairs (attribute string, attribute value) of the given 
                # # attributes list 'attr_list' of the given object 'obj'                
                # def get_attributes(obj, attr_list):
                #     attr_val_list = []
                #     for i_attribute  in attr_list:
                #         i_val = getattr(obj, 'get_' + i_attribute)()
                #         attr_val_list.append((i_attribute, i_val))
                #     
                #     return attr_val_list
                
                #Returns a list of the transferable attributes, that is the attributes having
                # both a 'get' and 'set' method. But the methods in 'except_attributes' are not
                # included
                def list_transferable_attributes(obj, except_attributes):
                    obj_methods_list = dir(obj)
                
                    obj_get_attr = []
                    obj_set_attr = []
                    obj_transf_attr =[]
                
                    for name in obj_methods_list:
                        if len(name) > 4:
                            prefix = name[0:4]
                            if prefix == 'get_':
                                obj_get_attr.append(name[4:])
                            elif prefix == 'set_':
                                obj_set_attr.append(name[4:])
                
                    for attribute in obj_set_attr:
                        if attribute in obj_get_attr and attribute not in except_attributes:
                            obj_transf_attr.append(attribute)
                
                    return obj_transf_attr
                
                
                #Creating a figure with to axes
                fig  = plt.figure()
                ax1 = plt.subplot(211) #First axes
                ax2 = plt.subplot(212) #Second axes
                plt.tight_layout() #Optional: Tweak to improve subplot layout
                
                #create an artist Line2D object 'line1' via plot
                x = np.linspace(0, 2*np.pi, 100)
                line1, = ax1.plot(x, np.sin(x))
                
                #create an artist Circle object
                circle1 = plt.Circle([1,0], 0.5, facecolor='yellow', edgecolor='k')
                #Adding the object to the first axes
                ax1.add_patch(circle1)
                
                #Labelling first axis
                ax1.set_xlabel('line1 and circle1 in ax1') 
                
                #Methods that we should not copy from artist to artist
                except_attributes = ('transform', 'figure')
                
                #Obtaining the names of line2D attributes that can be transfered 
                transferred_line_attributes = list_transferable_attributes(line1, except_attributes)
                
                #Obtaining the names of Circle attributes that can be transfered
                transferred_circle_attributes = list_transferable_attributes(circle1, except_attributes)
                
                #Creating an empty Line2D object
                line2 = plt.Line2D([],[])
                circle2 = plt.Circle([],[])
                
                #Copying the list of attributes 'transferred_line_attributes' of line1 into line2
                copy_attributes(line2, line1, transferred_line_attributes)
                copy_attributes(circle2, circle1, transferred_circle_attributes)
                
                #attr_val_list_line2 = get_attributes(line2, line1_attr_list)
                
                #Setting the new axes ax2 with the same limits as ax1
                ax2.set_xlim(ax1.get_xlim())
                ax2.set_ylim(ax1.get_ylim())
                
                #Adding the copied object line2 to the new axes
                ax2.add_line(line2) #.add_artist(line2) also possible
                ax2.add_patch(circle2) #.add_artist(circle2) also possible
                
                ax2.set_xlabel('line2 and circle2 in ax2') #Labelling axis
                
                plt.show()
                

                Output

                这篇关于复制 matplotlib 艺术家的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                上一篇:如何将文件复制到 Python 脚本中的特定文件夹? 下一篇:Python 类 __div__ 问题

                相关文章

              2. <tfoot id='m4KNE'></tfoot>

                <small id='m4KNE'></small><noframes id='m4KNE'>

                <i id='m4KNE'><tr id='m4KNE'><dt id='m4KNE'><q id='m4KNE'><span id='m4KNE'><b id='m4KNE'><form id='m4KNE'><ins id='m4KNE'></ins><ul id='m4KNE'></ul><sub id='m4KNE'></sub></form><legend id='m4KNE'></legend><bdo id='m4KNE'><pre id='m4KNE'><center id='m4KNE'></center></pre></bdo></b><th id='m4KNE'></th></span></q></dt></tr></i><div id='m4KNE'><tfoot id='m4KNE'></tfoot><dl id='m4KNE'><fieldset id='m4KNE'></fieldset></dl></div>

                  • <bdo id='m4KNE'></bdo><ul id='m4KNE'></ul>
                  <legend id='m4KNE'><style id='m4KNE'><dir id='m4KNE'><q id='m4KNE'></q></dir></style></legend>