質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

0回答

2060閲覧

RuntimeError: Can not put single artist in more than one figureの解決の仕方がわからないです.

RyosukeSHIBATA

総合スコア11

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/08/03 01:37

編集2020/08/03 05:19

概要

pythonを使ってグラフをいっぱい書くプログラムを試しているのですが.
RuntimeError: Can not put single artist in more than one figure
というエラーが起きて困っています.

問題箇所

https://stackoverrun.com/ja/q/12300089
こちらのリンクでplt.figureを複数設定して解決されている話はあるのですが,
今のプログラムでうまくplt.figureを複数生成する方法が思いつきません.

def evalOneMax(ind): """Objective function.""" evaluation = 0 for dish in ind: evaluation += dish.calorie # TODO:グラフ領域を設定 #TODO:いい感じにトレーのサイズを外から引数として撮ってくるやり方がわからない直接書いた tray_size = np.array([370, 260]) fig = plt.figure() axis = fig.add_subplot(1, 1, 1, xlim=tray_size[0], ylim=tray_size[1], aspect='equal') for dish in ind: axis.add_patch(dish.fig)#<-----ここでエラーが発生 axis.axis("off") plt.savefig('tmp.png') fig.delaxes(axis) plt.clf() plt.cla() plt.close() del axis gray_img = cv2.imread('tmp.png') ind.img = gray_img ret, dishes_area_image = cv2.threshold(gray_img, 200, 255, cv2.THRESH_BINARY)#図形がある dishes_area = cv2.countNonZero(cv2.bitwise_not(cv2.cvtColor(dishes_area_image, cv2.COLOR_RGB2GRAY))) cv2.imwrite('dishes_area.png',dishes_area_image) ret, dishes_overlap_area_image = cv2.threshold(gray_img, 100, 255, cv2.THRESH_BINARY)#重なってて黒い cv2.imwrite('dishes_overlap_area.png',dishes_overlap_area_image) dishes_overlap_area = cv2.countNonZero(cv2.bitwise_not(cv2.cvtColor(dishes_overlap_area_image, cv2.COLOR_RGB2GRAY))) overlap_per = 1 - dishes_overlap_area/dishes_area return evaluation * overlap_per

プログラム全体

import random import numpy as np from operator import attrgetter import csv import matplotlib import matplotlib.pyplot as plt import cv2 # def main(): n_gene = 4 # The number of genes. n_ind = 300 # The number of individuals in a population. CXPB = 0.5 # The probability of crossover. MUTPB = 0.2 # The probability of individdual mutation. MUTINDPB = 0.05 # The probability of gene mutation. NGEN = 40 # The number of generation loop. dish_types= DishTypes() dish_types.load_file() random.seed(64) # --- Step1 : Create initial generation. pop = create_pop(n_ind, n_gene, dish_types) set_fitness(evalOneMax, pop) best_ind = max(pop, key=attrgetter("fitness")) # --- Generation loop. print("Generation loop start.") print("Generation: 0. Best fitness: " + str(best_ind.fitness)) fig_save(best_ind, '{:0=5}'.format(0)) for g in range(NGEN): # --- Step2 : Selection. offspring = selTournament(pop, n_ind, tournsize=3) # --- Step3 : Crossover. crossover = [] for child1, child2 in zip(offspring[::2], offspring[1::2]):# (偶数個目,奇数個目)で子孫を作成 if random.random() < CXPB: child1, child2 = cxTwoPointCopy(child1, child2) # child1.fitness = None # child2.fitness = None crossover.append(child1) crossover.append(child2) offspring = crossover[:] # --- Step4 : Mutation. mutant = [] for mut in offspring: if random.random() < MUTPB: mut = mutFlipBit(dish_types, mut, indpb=MUTINDPB) # mut.fitness = None mutant.append(mut) offspring = mutant[:] # --- Update next population. pop = offspring[:] set_fitness(evalOneMax, pop) # --- Print best fitness in the population. best_ind = max(pop, key=attrgetter("fitness")) print("Generation: " + str(g + 1) + ". Best fitness: " + str(best_ind.fitness)) fig_save(best_ind, dish_types, '{:0=5}'.format(g + 1)) print("Generation loop ended. The best individual: ") print(best_ind) class DishTypes: def __init__(self): self.num=0 self.type=[] self.size=[] self.name=[] self.calorie=[] self.protein=[] self.lipid=[] self.carbohydrate=[] self.calcium=[] self.price=[] self.tray_size=np.array([370, 260]) def load_file(self): with open('dish.csv') as f: reader = csv.reader(f) for row in reader: self.name.append(row[0]) self.type.append(int(row[1])) self.size.append(int(row[2])) self.calorie.append(float(row[3])) self.protein.append(float(row[4])) self.lipid.append(float(row[5])) self.carbohydrate.append(float(row[6])) self.calcium.append(float(row[7])) self.price.append(float(row[8])) self.num = len(self.name) class Dish: def __init__(self, id, dish_types): self.figure_type=dish_types.type[id] self.fig=create_figure(dish_types.type[id],dish_types.size[id],dish_types.tray_size) self.name=dish_types.name[id] self.calorie=dish_types.calorie[id] self.protein=dish_types.protein[id] self.lipid=dish_types.lipid[id] self.carbohydrate=dish_types.carbohydrate[id] self.calcium=dish_types.calcium[id] self.price=dish_types.price[id] class IndividualTray(list): """Container of a individual.""" fitness = None img = None def __new__(cls, a): return list.__new__(cls, a) def create_figure(fig_type, size, tray_size): x = random.randrange(size, tray_size[0] - size) y = random.randrange(size, tray_size[1] - size) if fig_type == 0: return matplotlib.patches.Rectangle((x, y), size, size, facecolor='black', alpha=0.5) if fig_type == 1: return matplotlib.patches.Circle((x, y), radius=size, facecolor='black', alpha=0.5) def create_ind(n_gene, dish_types): """Create a individual.""" return IndividualTray([Dish(random.randint(0, dish_types.num-1), dish_types) for i in range(n_gene)]) def create_pop(n_ind, n_gene, dish_types): """Create a population.""" pop = [] for i in range(n_ind): ind = create_ind(n_gene, dish_types) pop.append(ind) return pop def set_fitness(eval_func, pop): """Set fitnesses of each individual in a population.""" for i, fit in zip(range(len(pop)), map(eval_func, pop)): pop[i].fitness = fit def evalOneMax(ind): """Objective function.""" evaluation = 0 for dish in ind: evaluation += dish.calorie # TODO:グラフ領域を設定 #TODO:いい感じにトレーのサイズを外から引数として撮ってくるやり方がわからない直接書いた tray_size = np.array([370, 260]) fig = plt.figure() axis = fig.add_subplot(1, 1, 1, xlim=tray_size[0], ylim=tray_size[1], aspect='equal') for dish in ind: axis.add_patch(dish.fig) axis.axis("off") plt.savefig('tmp.png') fig.delaxes(axis) plt.clf() plt.cla() plt.close() del axis gray_img = cv2.imread('tmp.png') ind.img = gray_img ret, dishes_area_image = cv2.threshold(gray_img, 200, 255, cv2.THRESH_BINARY)#図形がある dishes_area = cv2.countNonZero(cv2.bitwise_not(cv2.cvtColor(dishes_area_image, cv2.COLOR_RGB2GRAY))) cv2.imwrite('dishes_area.png',dishes_area_image) ret, dishes_overlap_area_image = cv2.threshold(gray_img, 100, 255, cv2.THRESH_BINARY)#重なってて黒い cv2.imwrite('dishes_overlap_area.png',dishes_overlap_area_image) dishes_overlap_area = cv2.countNonZero(cv2.bitwise_not(cv2.cvtColor(dishes_overlap_area_image, cv2.COLOR_RGB2GRAY))) overlap_per = 1 - dishes_overlap_area/dishes_area return evaluation * overlap_per def selTournament(pop, n_ind, tournsize): """Selection function.""" chosen = [] for i in range(n_ind): aspirants = [random.choice(pop) for j in range(tournsize)]#適当にtournsizeこだけ個体を選ぶ chosen.append(max(aspirants, key=attrgetter("fitness")))#fitness属性の一番大きいものを選ぶ return chosen def cxTwoPointCopy(ind1, ind2): """Crossover function.""" size1 = len(ind1) size2 = len(ind2) tmp1 = ind1.copy() tmp2 = ind2.copy() cxpoint1 = int(size1/2) cxpoint2 = int(size2/2) tmp1, tmp2 = tmp2[:cxpoint2].copy()+tmp1[cxpoint1:].copy(), tmp1[:cxpoint1].copy()+tmp2[cxpoint2:].copy() return tmp1, tmp2 def mutFlipBit(dish_types, ind, indpb): """Mutation function.""" tmp = ind.copy() for i in range(len(ind)): if random.random() < indpb: rand = random.randint(0, 2) # 増やす if rand == 0: tmp[i] = ind.append(Dish(random.randint(0, dish_types.num-1), dish_types)) break # へらす if rand == 1: tmp[i] = ind.pop(random.randint(0,len(ind)-1)) break # 変える if rand == 2: randopos = random.randint(0, len(ind) - 1) tmp[i] = ind.pop(randopos) tmp[i] = ind.insert(randopos, random.randint(0, len(ind) - 1)) break return tmp def fig_save(ind, file_name): cv2.imwrite(',/img/'+file_name+'.png', ind.img) if __name__ == "__main__": main()

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2020/08/03 02:01

このままではコードが読めないので、質問を編集し、<code>ボタンを押し、出てくる’’’の枠の中にコードを貼り付けてください
RyosukeSHIBATA

2020/08/03 02:06

listで作ったらどうかと思ったのですが変わらずでした.
meg_

2020/08/03 03:43

エラー発生箇所はどこですか?
RyosukeSHIBATA

2020/08/03 05:18

``` for dish in ind: axis.add_patch(dish.fig)#ここでエラーが発生 ```
RyosukeSHIBATA

2020/08/03 05:35

``` File "/Users/hoge/Desktop/hoge/fig_ga.py", line 161, in evalOneMax axis.add_patch(dish.fig) File "/usr/local/lib/python3.7/site-packages/matplotlib/axes/_base.py", line 1916, in add_patch self._set_artist_props(p) File "/usr/local/lib/python3.7/site-packages/matplotlib/axes/_base.py", line 905, in _set_artist_props a.set_figure(self.figure) File "/usr/local/lib/python3.7/site-packages/matplotlib/artist.py", line 712, in set_figure raise RuntimeError("Can not put single artist in " RuntimeError: Can not put single artist in more than one figure ```
meg_

2020/08/03 08:09

・質問のプログラムは複雑そうですが、質問者さんご自身が作成されたものですか? ・問題を簡単にするためにもっと簡単なグラフから試された方が良いかと思います。(参考サイトのコードは動かしてみましたか?)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問