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

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

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

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

受付中

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

RyosukeSHIBATA
RyosukeSHIBATA

総合スコア0

Python

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

0回答

0評価

0クリップ

4閲覧

投稿2020/08/03 01:37

編集2022/01/12 10:55

概要

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()

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

y_waiwai
y_waiwai

2020/08/03 02:01

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

2020/08/03 02:06

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

2020/08/03 03:43

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

2020/08/03 05:18

``` for dish in ind: axis\.add_patch\(dish\.fig\)#ここでエラーが発生 ```
RyosukeSHIBATA
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_
meg_

2020/08/03 08:09

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

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

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

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

ただいまの回答率
87.20%

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

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

質問する

関連した質問

同じタグがついた質問を見る

Python

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