Category: Python

[Tips]How to switch python3 and python2 in VSCode

I ‘ve been using python2 in VSCode for a long time, but I have to run python3 code this time. How to switch python2 and python3?

GOAL

To switch python2 and python3 in VSCode

Environment

Windows10
python2.7 and python3.8.5
Visual Studio Code1.49.0

Method

Open command palette with the shortcut Ctrl+Shift+P. *If you are working on macOS, use the shortcut Command+Shift+P.

And select “select interpreter”

from VSCode

And choose the python version that you’d like to use.

from VSCode

If you need, please install Linker such as pylint for the new version of python.

First PySide Application

GOAL

To understand Qt and PySide(PySide2) and create PySide application that

Emvironment

WIndows10
Python2.7.8

*I use python2 because python3 can’t be used in Maya, but I think python3 is better for general application development. And PySide2 which is used in Maya2017~ is easy to use in python3.

What is Qt?

Qt is a cross-platform application framework with many modules providing services like network abstraction and XML handling, along with a very rich GUI package.

Though Qt is developed in C++, it can be used in Python, Java, Perl and so on with API. The application developed with Qt can be executed in any platform such as Windows, Linux, macOS, desktop and mobile.

Qt has been upgraded constantly, and the latest version in 2020 is Qt5.

What is PySide?

PySide is the python module as a Python binding of Qt. Functions, variables and modules of Qt can be used in Python via PySide. GUI application can be developed on multi platform, windows, Linux and macOS using Python with PySide.

PySide and Pyside2

PySide2 is upgraded PySide. PySide2 provides access to the Qt 5 framework while PySide provide access to Qt4 or below. Qt4 and PySide can be used in Maya2016 and before, Qt5 and PySide2 is used in Maya2017 and after.

If you are using python2, it’s easy to install PySide by using pip install, but you should build PySide2 by yourself. So If you want to use PySide2, please use python3 and its pip install.

The difference between PySide and PyQt

PyQt is also one of the python modules as a Python binding of Qt. The document “Differences Between PySide and PyQt” is clear and detailed. And “PyQt vs Pyside” is easy to understand their advantages and disadvantages.

Method

The following is the method to create your first PySide application. This is for PySide so please replace words for PySide2 if you need.

Install PySide

Open Command prompt and input pip command. In my case, ‘pip2’ is used because python3 is installed and the command just ‘pip’ is equal to pip3.

> pip2 install pyside

Check if PySide is successfully installed.

>py -2
Python 2.7.8....
>>> import PySide
>>> PySide.__version__
'1.2.4'
>>>

Hello World

This is an application program to display HelloWorld.

import sys
from PySide.QtCore import *
from PySide.QtGui import *

#Create QApplication
firstApp = QApplication(sys.argv)
# Create a Label
label = QLabel("Hello World")
label.show()
# Enter Qt application main loop
firstApp.exec_()
sys.exit()

Execute and small window will appear.

QtGui

QtGui module contains classes that control widgets of PySide. Widget is a UI component that is used in GUI application such as button, label, Matrix, Layout and so on. You can see all class in PySide.QtGui.

Create Widget

You can create original widget as a Class. Add single widgets into QVBoxLayout.

import sys
from PySide.QtCore import *
from PySide.QtGui import *

class MyWidget(QWidget):
    def __init__(self):
        super(MyWidget, self).__init__()
        self.text = QLabel("Say Hello")
        self.text.setAlignment(Qt.AlignCenter)
        self.edit = QLineEdit("who?")
        self.button = QPushButton("Click here")
        self.output = QLabel("")
        self.layout = QVBoxLayout()
        self.layout.addWidget(self.text)
        self.layout.addWidget(self.edit)
        self.layout.addWidget(self.button)
        self.layout.addWidget(self.output)
        self.setLayout(self.layout)
        self.button.clicked.connect(self.sayHello)

    def sayHello(self):
        self.output.clear()
        self.output.setText("Hello " + self.edit.text()+"!")
        
if __name__ == '__main__':
    app = QApplication(sys.argv)

    widget = MyWidget()
    widget.resize(300, 100)
    widget.show()
    widget.setWindowTitle("My Widget Test")
    sys.exit(app.exec_())

This is the window. Input name into line edit and click the button.

Then name you enter in the field is displayed.

Union-Find in Python

GOAL

To understand and to implement union-find in Python.

Example of problems using union-find algorithm

Dividing clusters

There is a list of friends from N people. Divide them in cluster.

n = 6
friendship = [(1, 2), (3, 4), (1, 6)]
(more…)

[Blender] Warning: class CLASS_NAME contains a property which should be an annotation!

Warning Detail

When I install my custom addon in Blender2.80, the warning “class CLASS_NAME contains a property which should be an annotation!” occured. the class CLASS_NAME is an operator class that inherits bpy.types.Operator. And the class contains bpy.props properties as below.

class MY_OT_import_file(bpy.types.Operator):
    bl_idname = "my.import_file"
    bl_label = "My Import file"
    bl_description = "Custom import addon"
    bl_options = {'REGISTER', 'UNDO'}
    
    filepath = bpy.props.StringProperty(default="",subtype="FILE_PATH")
    
    def execute(self, context):
        ...

Cause

Reference: Blender 2.80: Addon API

Classes that contain properties from bpy.props now use Python’s type annotations (see PEP 526) and should be assigned using a single colon : in Blender 2.8x instead of equals = as was done in 2.7x

from Blender 2.80: Addon API

Correction

Use annotation in the class where warning occurred to set properties.

class MY_OT_import_file(bpy.types.Operator):
    bl_idname = "my.import_file"
    bl_label = "My Import file"
    bl_description = "Custom import addon"
    bl_options = {'REGISTER', 'UNDO'}
    
    filepath : bpy.props.StringProperty(default="",subtype="FILE_PATH")
    
    def execute(self, context):
        ...

Unpaired One-way ANOVA And Multiple Comparisons In Python

GOAL

To write program of unpaired one-way ANOVA(analysis of variance) and multiple comparisons using python. Please refer another article “Paired One-way ANOVA And Multiple Comparisons In Python” for paired one-way ANOVA.

What is ANOVA?

ANOVE is is a method of statistical hypothesis testing that determines the effects of factors and interactions, which analyzes the differences between group means within a sample.
Details will be longer. Please see the following site.

One-way ANOVA is ANOVA test that compares the means of three or more samples. Null hypothesis is that samples in groups were taken from populations with the same mean.

Implementation

The following is implementation example of one-way ANOVA.

Import Libraries

Import libraries below for ANOVA test.

import pandas as pd
import numpy as np
import scipy as sp
import csv # when you need to read csv data
from scipy import stats as st

import statsmodels.formula.api as smf
import statsmodels.api as sm
import statsmodels.stats.anova as anova #for ANOVA
from statsmodels.stats.multicomp import pairwise_tukeyhsd #for Tukey's multiple comparisons

Data Preparing

group A85908869789887
group B55826764785449
group C46955980527370

test_data.csv

85, 90, 88, 69, 78, 98, 87
55, 82, 67, 64, 78, 54, 49
46, 95, 59, 80, 52, 73, 70

Read and Set Data

csv_line = []
with open('test_data.csv', ) as f:
    for i in f:
        items = i.split(',')
        for j in range(len(items)):
            if '\n' in items[j]:
                items[j] =float(items[j][:-1])
            else:
                items[j] =float(items[j])
        print(items)
        csv_line.append(items)
groupA = csv_line [0]
groupB = csv_line [1]
groupC = csv_line [2]

tdata = pd.DataFrame({'A':groupA, 'B':groupB, 'C':groupC})
tdata.index = range(1,10)
tdata 

If you want to display data summary, use DataFrame.describe().

tdata.describe()

ANOVA

f, p = st.f_oneway(tdata['A'],tdata['B'],tdata['C'])
print("F=%f, p-value = %f"%(f,p))

>> F=4.920498, p-value = 0.019737

The smaller the p-value, the stronger the evidence that you should reject the null hypothesis.
When statistically significant, that is, p-value is less than 0.05 (typically ≤ 0.05), perform a multiple comparison.

Tukey’s multiple comparisons

Use pairwise_tukeyhsd(endog, groups, alpha=0.05) for tuky’s HSD(honestly significant difference) test. Argument endog is response variable, array of data (A[0] A[1]… A[6] B[1] … B[6] C[1] … C[6]). Argument groups is list of names(A, A…A, B…B, C…C) that corresponds to response variable. Alpha is significance level.

def tukey_hsd(group_names , *args ):
    endog = np.hstack(args)
    groups_list = []
    for i in range(len(args)):
        for j in range(len(args[i])):
            groups_list.append(group_names[i])
    groups = np.array(groups_list)
    res = pairwise_tukeyhsd(endog, groups)
    print (res.pvalues) #print only p-value
    print(res) #print result
print(tukey_hsd(['A', 'B', 'C'], tdata['A'], tdata['B'],tdata['C']))
>>[0.02259466 0.06511251 0.85313142]
 Multiple Comparison of Means - Tukey HSD, FWER=0.05 
=====================================================
group1 group2 meandiff p-adj   lower    upper  reject
-----------------------------------------------------
     A      B -20.8571 0.0226 -38.9533 -2.7609   True
     A      C -17.1429 0.0651 -35.2391  0.9533  False
     B      C   3.7143 0.8531 -14.3819 21.8105  False
-----------------------------------------------------
None

Supplement

If you can’t find ‘pvalue’ key, check the version of statsmodels.

import statsmodels
statsmodels.__version__
>> 0.9.0

If the version is lower than 0.10.0, update statsmodels. Open command prompt or terminal and input the command below.

pip install --upgrade statsmodels
# or pip3 install --upgrade statsmodels

What is @classmethod in python

GOAL

To understand what @classmethod in python is and how to use it

What is classmethod?

@classmethod is a function decorator.

class C:
    @classmethod
    def f(cls, arg1, arg2, ...):

A class method can be called either on the class (such as C.f()) or on an instance (such as C().f()). The instance is ignored except for its class. If a class method is called for a derived class, the derived class object is passed as the implied first argument.

Python document >library >fuction

Features of class methods

  • class methods can be called as the form Classname.method_name() without generate instance.
  • class methods receive ‘cls’ not ‘self’ as argument.

How to use

Functions that access the internal data of the class can be managed collectively with class itself.

class Student:
    def __init__(self, name, grade):
        self.name = name
        self.grade = grade

    @classmethod
    def testpoint_to_grade(cls, name, testpoint):
        if testpoint > 90:
            return cls(name, 'A')
        elif testpoint > 80:
            return cls(name, 'B')
        elif testpoint > 60:
            return cls(name, 'C')
        else:
            return cls(name, 'D')

    def print_grade(self):
        print(self.grade) 

student1 = Student('Alice', 'C')
student2 = Student.testpoint_to_grade('Ben', 85)

student1.print_grade()
>> C
student2.print_grade()
>> B

Strange Warning with custom render Engine in Blender

Error

WARN (bpy.rna): c:\b\win64_cmake_vs2017\win64_cmake_vs2017\blender.git\source\blender\python\intern\bpy_rna.c:1476 pyrna_enum_to_py: current value ‘3’ matches no enum in ‘SpaceNodeEditor’, ‘(null)’, ‘tree_type’

Similar reports

Custom RenderEngine: Shader Editor issues

There’s also a corner case when having the Shader editor visible (for example when Cycles is active) and then switching to a render engine that has bl_use_shading_nodes_custom=True: the icon for the editor will become blank, but the Shader editor remains visible. In the console I warnings in this case:
WARN (bpy.rna): ../source/blender/python/intern/bpy_rna.c:1451 pyrna_enum_to_py: current value ‘3’ matches no enum in ‘SpaceNodeEditor’, ‘(null)’, ‘tree_type’

https://developer.blender.org/T68473

SpaceNodeEditor error for CustomRenderEngine example

When I activate my custom render engine and switch to the Shading workspace, the node menus disappear and I get the error:
WARN (bpy.rna): c:\b\win64_cmake_vs2017\win64_cmake_vs2017\blender.git\source\blender\python\intern\bpy_rna.c:1449 pyrna_enum_to_py: current value ‘0’ matches no enum in ‘SpaceNodeEditor’, ‘(null)’, ‘tree_type’

https://blenderartists.org/t/spacenodeeditor-error-for-customrenderengine-example/1162743

Cause

The cause is unclear. However, in my case, this error occurs when I access SpaceNodeEditor.tree_type in register() function with the flag “bl_use_shading_nodes_custom” set to True. My solution was one of the following:

  • To set SpaceNodeEditor.tree_type not to be accessed in register() function.
  • Set the flag “bl_use_shading_nodes_custom to False and use my node in ShaderEditor for existing Eevee, Cycles.

Thanks for more information and help…

Chi-Square Test in Python

GOAL

To write program of chi-square test using python. 

What is chi-square test?

Chi-square test which means “Pearson’s chi-square test” here, is a method of statistical hypothesis testing for goodness-of-fit and independence.

Goodness-of-fit test is the testing to determine whether the observed frequency distribution is the same as the theoretical distribution.
Independence test is the testing to determine whether 2 observations that is represented by 2*2 table, on 2 variables are independent of each other.

Details will be longer. Please see the following sites and document.

Implementation

The following is implementation for chi-square test.

Import libraries

import numpy as np
import pandas as pd
import scipy as sp
from scipy import stats

Data preparing

gourp Agroup Bgroup C
success2365158
failure10044119
success rate0.1870.5960.570

chi_square_data.csv

A,B,C
23,65,158
100,44,119

Read and Set Data

csv_line = []
with open('chi_square_data.csv', ) as f:
    for i in f:
        items = i.split(',')
        for j in range(len(items)):
            if '\n' in items[j]:
                items[j] =float(items[j][:-1])
            else:
                items[j] =float(items[j])
        csv_line.append(items)
group = csv_line[0]
success = [int(n) for n in csv_line[1]]
failure = [int(n) for n in csv_line[2]]

groups = [] 
result =[]
count = []
for i in range(len(group)):
    groups += [group[i], group[i]] #['A','A', 'B', 'B', 'C', 'C']
    result += ['success', 'failure'] #['success', 'failure', 'success', 'failure', 'success', 'failure']
    count += [success[i], failure[i]] #[23, 100, 65, 44, 158, 119]
    
data =  pd.DataFrame({
    'groups' : groups,
    'result' : result,
    'count' : count
})
cross_data = pd.pivot_table(
    data = data,
    values ='count',
    aggfunc = 'sum',
    index = 'groups',
    columns = 'result'
)
print(cross_data)
>>result  failure  success
groups                  
A           100       23
B            44       65
C           119      158

Chi-square test

print(stats.chi2_contingency(cross_data, correction=False))
>> (57.23616422920877, 3.726703617716424e-13, 2, array([[ 63.554,  59.446],
       [ 56.32 ,  52.68 ],
       [143.126, 133.874]]))
  • chi2 : 57.23616422920877
    • The test statistic
  • p : 3.726703617716424e-13
    • The p-value of the test
  • dof : 2
    • Degrees of freedom
  • expected : array
    • The expected frequencies, based on the marginal sums of the table.

The smaller the p-value, the stronger the evidence that you should reject the null hypothesis.
When statistically significant, that is, p-value is less than 0.05 (typically ≤ 0.05), the difference between groups is significant.

Paired One-way ANOVA And Multiple Comparisons In Python

GOAL

To write program of paired one-way ANOVA(analysis of variance) and multiple comparisons using python. Please refer another article “Unpaired One-way ANOVA And Multiple Comparisons In Python” for unpaired one-way ANOVA.

What is ANOVA

ANOVA(analysis of variance) is a method of statistical hypothesis testing that determines the effects of factors and interactions, which analyzes the differences between group means within a sample.
Details will be longer. Please see the following site.

One-way ANOVA is ANOVA test that compares the means of three or more samples. Null hypothesis is that samples in groups were taken from populations with the same mean.

Implementation

The following is implementation example of paired one-way ANOVA.

Import Libraries

Import libraries below for ANOVA test.

import statsmodels.api as sm
from statsmodels.formula.api import ols
import pandas as pd
import numpy as np
import statsmodels.stats.anova as anova

Data Preparing

id_1id_2id_3id_4id_5id_6id_7
condition A85908869789887
condition B55826764785449
condition C46955980527370

test_data.csv

85, 90, 88, 69, 78, 98, 87
55, 82, 67, 64, 78, 54, 49
46, 95, 59, 80, 52, 73, 70

Read and Set Data

csv_line = []
with open('test_data.csv', ) as f:
    for i in f:
        items = i.split(',')
        for j in range(len(items)):
            if '\n' in items[j]:
                items[j] =float(items[j][:-1])
            else:
                items[j] =float(items[j])
        print(items)
        csv_line.append(items)
groupA = csv_line [0]
groupB = csv_line [1]
groupC = csv_line [2]
tdata = pd.DataFrame({'A':groupA, 'B':groupB, 'C':groupC})
tdata.index = range(1,10)
tdata 

If you want to display data summary, use DataFrame.describe().

tdata.describe()

ANOVA

subjects=['id1','id2','id3','id4','id5','id6','id7']
points = np.array(groupA +groupB + groupC)
conditions = np.repeat(['A','B','C'],len(group0))
subjects = np.array(subjects+subjects+subjects)
df = pd.DataFrame({'Point':points,'Conditions':conditions,'Subjects':subjects})
aov=anova.AnovaRM(df, 'Point','Subjects',['Conditions'])
result=aov.fit()

print(result)

>>                 Anova
========================================
           F Value Num DF  Den DF Pr > F
----------------------------------------
Conditions  5.4182 2.0000 12.0000 0.0211
========================================

The smaller the p-value, the stronger the evidence that you should reject the null hypothesis.
When statistically significant, that is, p-value is less than 0.05 (typically ≤ 0.05), perform a multiple comparison. This p value is different between paired ANOVA and unpaired ANOVA.

Tukey’s multiple comparisons

Use pairwise_tukeyhsd(endog, groups, alpha=0.05) for tuky’s HSD(honestly significant difference) test. Argument endog is response variable, array of data (A[0] A[1]… A[6] B[1] … B[6] C[1] … C[6]). Argument groups is list of names(A, A…A, B…B, C…C) that corresponds to response variable. Alpha is significance level.

def tukey_hsd(group_names , *args ):
    endog = np.hstack(args)
    groups_list = []
    for i in range(len(args)):
        for j in range(len(args[i])):
            groups_list.append(group_names[i])
    groups = np.array(groups_list)
    res = pairwise_tukeyhsd(endog, groups)
    print (res.pvalues) #print only p-value
    print(res) #print result
print(tukey_hsd(['A', 'B', 'C'], tdata['A'], tdata['B'],tdata['C']))
>> [0.02259466 0.06511251 0.85313142]
 Multiple Comparison of Means - Tukey HSD, FWER=0.05 
=====================================================
group1 group2 meandiff p-adj   lower    upper  reject
-----------------------------------------------------
     A      B -20.8571 0.0226 -38.9533 -2.7609   True
     A      C -17.1429 0.0651 -35.2391  0.9533  False
     B      C   3.7143 0.8531 -14.3819 21.8105  False
-----------------------------------------------------
None

What is “getattr()” in Python?

GOAL

To understand getattr() function in python.

getattr(Object, name [, default])

Return the value of the named attribute of objectname must be a string. If the string is the name of one of the object’s attributes, the result is the value of that attribute. For example, getattr(x, 'foobar') is equivalent to x.foobar. If the named attribute does not exist, default is returned if provided, otherwise AttributeError is raised.

Python document > library > functions

What will happen

The following is sample code with Dog class and getattr().

class Dog():
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def sit(self):
        self.tired = False
        print("sit down")
    def bark(self, count):
        self.tired = True
        for i in range(count):
            print("bow wow")

dog1 = Dog("Poppy", 3)
val1 = getattr(dog1, "name")
val2 = getattr(dog1, "age")
val3 = getattr(dog1, "tired", "unknown")
val4 = getattr(dog1, "sit")()
val5 = getattr(dog1, "bark")(2)
val6 = getattr(dog1, "sit")
val7 = getattr(dog1, "bark")
val8 = getattr(dog1, "tired", "unknown")

Get attribute

# val1 = getattr(dog1, "name")
print(val1)
>> Poppy
# val2 = getattr(dog1, "age")
print(val2)
>> 3

Get default value

# val3 = getattr(dog1, "tired", "unknown")
print(val3)
>> unknown

Execute function

# val4 = getattr(dog1, "sit")()
print(val4)
>> None
# val5 = getattr(dog1, "bark")(2)
print(val5)
>> None

Get function

# val6 = getattr(dog1, "sit")
print(val6)
>> <bound method Dog.sit of <__main__.Dog object at 0x7f192a93f1d0>>
val6()
>> sit down
# val7 = getattr(dog1, "bark")
print(val7)
>> <bound method Dog.bark of <__main__.Dog object at 0x7fb2169ae1d0>>
val7(3)
>> bow wow
>> bow wow
>> bow wow

After Executing function

# val8 = getattr(dog1, "tired", "unknown")
print(val8)
>> True

getattr(dog1, sit)() and getattr(dog1, bark)(2) changed internal variable “tired”.