👋

構造一貫解析ソフトSS7をPythonで実行する #2 ループ処理例(コマンド実行)

2023/12/20に公開

フォルダ構成

src
├─ss7_make_command.py :: 入力csv -> 解析のループを行う。
├─ss7_make_command_GUI.py
├─ module/
│   ├─ ss7_SB1.py :: ss7出力csvの読書きを行う。
│   └─ ss7_scmd.py :: scmdファイルを作成する
└─ data/  
    ├─ csv/
    │   ├─ exp.csv :: ss7.iknから生成。順次書替え。
    │   └─ inp.csv :: ss7.iknから生成。順次書替え。
    └─ scmd/
        ├─ ss01_0001.scmd :: 1回目解析用テンプレート 
        ├─ ss01_0002.scmd :: 2回目解析用テンプレート
        └─ ss03.scmd :: 順次更新。

プログラムの流れ

① 解析済ss7.iknファイル -> exp.csv, inp.csv出力
② exp.csvとinp.csvを読取る。
exp.csvより小梁の断面算定情報を取得し、設定クライテリアと比較する。
NGの場合の小梁配置情報をリスト化する。
③ NGの小梁を書換してinp.csvを作成する。
④ imp.csvから.iknを生成し、解析実行。-> exp.csv, inp.csv出力。
以降②~④のループをNGがなくなるまで繰返し。

ss7_make_command.py

import module.ss7_SB1 as sb
import module.ss7_scmd as sc
import subprocess
import sys
import os

#メインファイルTkinter追加必要あり。
print(sys.getdefaultencoding()) #文字コードの確認
path = os.getcwd() #カレントディレクトリの取得
print("カレントディレクトリ ::", path)

path_ikn = "C:\\UsrData\\Ss7Data\\物件A_Auto2023.ikn"
path_ikn1 = "C:\\UsrData\\Ss7Data\\物件A_Auto2023_1.ikn"
base_scmd = ".\data\scmd\ss01_0001.scmd" #1回目に実行するscmdファイル
base_scmd1 = '.\data\scmd\ss01_0002.scmd' #csvからss7に変換する部分が追加されたベースファイル

newfile = ".\data\scmd\ss03.scmd" #実行ファイル
inpath = "data\csv\inp.csv"
expath = "data\csv\exp.csv"
nwinpath = "data\csv\inp0.csv"
inpath = os.path.join(path, inpath)
expath = os.path.join(path, expath)
nwinpath = os.path.join(path, nwinpath)

def main(crit0, crit1):
    count = 1
    print("\n計算回数 = %i"%count)

    #scmdファイル実行(SS7コマンド実行)
    #第1回目の実行(結果1に実行済ファイルが存在する前提)
    sc.go_scmd(path_ikn, base_scmd, newfile, inpath, expath, nwinpath)
    subprocess.run(newfile, shell=True)

    #csv読み書きとエラー個数取得
    n1 = sb.csvmaker(inpath, expath, nwinpath, crit0, crit1)
    print("エラー個数 = ", n1) 

    #whileループになるか判断(n1=0の時、ループには入らない)
    if n1 == 0:
        n = 0 #下記のwhileループに入らない。
    else:
        n = 100 #初期値>1 ならなんでもOK whileループに入る。

    count += 1
    while n >= 1: #エラーがある場合ループ入り
        print("\n計算回数 = %i"%count)

        #scmdファイル実行(SS7コマンド実行)
        sc.go_scmd(path_ikn1, base_scmd1, newfile, inpath, expath, nwinpath)
        subprocess.run(newfile, shell=True)

        #csvの読み書きとエラー個数
        n1 = sb.csvmaker(inpath, expath, nwinpath, crit0, crit1)
        print("エラー個数 = ", n1)
        
        n = n1
        count += 1

crit0 = 0.9 # 検定比
crit1 = 300 # 変形
main(crit0, crit1)

ss7_make_command_GUI.py

import module.ss7_SB1 as sb
import module.ss7_scmd as sc
import subprocess
import sys
import os

#GUI用
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
from tkinter import filedialog
import datetime
now = datetime.datetime.now()
now = now.strftime("%y%m%d_%H%M")

# フォルダ指定の関数
def dirdialog_clicked():
    iDir = 'C:\\UsrData\\Ss7Data'
    iDirPath = filedialog.askdirectory(initialdir = iDir)
    entry1.set(iDirPath)

def conductMain(): # 実行ボタン押下時の実行関数
    filePath1 = entry1.get() #INPUT FILE
    crit0 = float(text4.get(1.0, END+"-1c"))
    crit1 = float(text5.get(1.0, END+"-1c"))
    print(filePath1)
    print(crit0, crit1)
    main(crit0, crit1)

#メインファイルTkinter追加必要あり。
print(sys.getdefaultencoding()) #文字コードの確認
path = os.getcwd() #カレントディレクトリの取得
print("カレントディレクトリ ::", path)

path_ikn = "C:\\UsrData\\Ss7Data\\物件A_Auto2023.ikn"
path_ikn1 = "C:\\UsrData\\Ss7Data\\物件A_Auto2023_1.ikn"
base_scmd = ".\data\scmd\ss01_0001.scmd" #1回目に実行するscmdファイル
base_scmd1 = '.\data\scmd\ss01_0002.scmd' #csvからss7に変換する部分が追加されたベースファイル

newfile = ".\data\scmd\ss03.scmd" #実行ファイル
inpath = "data\csv\inp.csv"
expath = "data\csv\exp.csv"
nwinpath = "data\csv\inp0.csv"
inpath = os.path.join(path, inpath)
expath = os.path.join(path, expath)
nwinpath = os.path.join(path, nwinpath)

def main(crit0, crit1):
    count = 1
    print("\n計算回数 = %i"%count)

    #scmdファイル実行(SS7コマンド実行)
    #第1回目の実行(結果1に実行済ファイルが存在する前提)
    sc.go_scmd(path_ikn, base_scmd, newfile, inpath, expath, nwinpath)
    subprocess.run(newfile, shell=True)

    #csv読み書きとエラー個数取得
    n1 = sb.csvmaker(inpath, expath, nwinpath, crit0, crit1)
    print("エラー個数 = ", n1) 

    #whileループになるか判断(n1=0の時、ループには入らない)
    if n1 == 0:
        n = 0 #下記のwhileループに入らない。
    else:
        n = 100 #初期値>1 ならなんでもOK whileループに入る。

    count += 1
    while n >= 1: #エラーがある場合ループ入り
        print("\n計算回数 = %i"%count)

        #scmdファイル実行(SS7コマンド実行)
        sc.go_scmd(path_ikn1, base_scmd1, newfile, inpath, expath, nwinpath)
        subprocess.run(newfile, shell=True)

        #csvの読み書きとエラー個数
        n1 = sb.csvmaker(inpath, expath, nwinpath, crit0, crit1)
        print("エラー個数 = ", n1)
        
        n = n1
        count += 1

# rootの作成
root = Tk()
root.title("小梁順次変更 by_kitagawa")

# Frame1の作成
frame1 = ttk.Frame(root, padding=10)
frame1.grid(row=1, column=1, sticky=E)
# 「ファイル参照」ラベルの作成
IFileLabel = ttk.Label(frame1, text="ファイル参照(.ikn)>>", padding=(5, 2))
IFileLabel.pack(side=LEFT)
# 「ファイル参照」エントリーの作成
entry1 = StringVar()
IFileEntry = ttk.Entry(frame1, textvariable=entry1, width=30)
IFileEntry.pack(side=LEFT)
# 「ファイル参照」ボタンの作成
IFileButton = ttk.Button(frame1, text="参照", command=dirdialog_clicked)
IFileButton.pack(side=LEFT)

# Frame4の作成
frame4 = ttk.Frame(root, padding=10)
frame4.grid(row=2, column=1, sticky=E)
IFileLabel = ttk.Label(frame4, text="目標検定比 >>", padding=(5, 2))
IFileLabel.pack(side=LEFT) 
text4=Text(frame4, height=1)
text4.pack()
text4.insert(END, 0.9)

# Frame5の作成
frame5 = ttk.Frame(root, padding=10)
frame5.grid(row=3, column=1, sticky=E)
IFileLabel = ttk.Label(frame5, text="変形クライテリア1/ >>", padding=(5, 2))
IFileLabel.pack(side=LEFT) 
text5=Text(frame5, height=1)
text5.pack()
text5.insert(END, 300)

# Frame7の作成
frame7 = ttk.Frame(root, padding=10)
frame7.grid(row=4,column=1,sticky=W)

# 実行ボタンの設置
button1 = ttk.Button(frame7, text="実行", command=conductMain)
button1.pack(fill = "x", padx=30, side = "left")
# キャンセルボタンの設置
button2 = ttk.Button(frame7, text=("閉じる"), command=quit)
button2.pack(fill = "x", padx=30, side = "left")
root.mainloop()

ss7_SB1.py

import csv

class sbdata:
    def __init__(self, inpath, expath):
        s = self
        #入力csvファイルを読み込んでリストに格納
        s.l = []
        with open(inpath, 'r') as f:
            reader = csv.reader(f)
            for row in reader:
                s.l.append(row)

        s.lxp = []
        with open(expath, 'r') as f:
            reader = csv.reader(f)
            for row in reader:
                s.lxp.append(row)

    def get_data_range(self, name, in_out): #name= name, l
        #データの範囲とデータリストを返す関数。
        s = self
        
        if in_out == 0:
            l = s.l
        else:
            l = s.lxp

        st = 0 #nameを見つけたフラグ
        count = 0 #デバッグ用
        for i in range(len(l)):
            li = l[i]
            if "name="+name in li:
                st = 1
                no0 = i
            else:
                None
            if st == 1:
                count += 1
                if "<data>" in li:
                    no1 = i
                elif not li: #リストのから判定
                    no2 = i
                    break
                else:
                    None
        #if count > 25:
        #    break
        dl = l[no1+1:no2]
        return(no0, no1, no2, dl) #[nameのある行i, <data>のある行i, deta終了行i, 範囲のテキストデータ]

def get_unique(names): #重複削除関数(登場の順番を守るもの)
    unique = []
    for name in names:
        if name not in unique:
            unique.append(name)
    return(unique)

def get_jrow(dl,j): #2次元配列の特定列を取得
    BL = []
    for i in range(len(dl)):
        BL.append(dl[i][j])
    return(BL)

def dls(dl, kai, iti, first, fugo): #小梁の位置と符号があっているものを返す。
        #print(kai, iti, first, fugo)
        ilis = []
        p = " "
        #print(dls)
        for i in range(len(dl)):
            li = dl[i] #一行取出し(S小梁断面の値)
            kai0 = li[0] #階
            iti0 = li[1] #位置
            first0 = li[3] #小梁ナンバー
            fugo0 = li[9] #符号名
            #以下判定用文字列
            han0 = str(kai) +p+str(iti) +p+str(first) +p+str(fugo)
            han1 = str(kai0)+p+str(iti0)+p+str(first0)+p+str(fugo0)
            #判定用文字列の確認
            if han0 == han1:
                ilis.append(i)
        print("ilis", ilis)
        return(ilis[0])

def list_no(li_in,search): #リストで何番目に指定文字があるのか
        for i in range(len(li_in)):
            li = li_in[i]
            if li == search:
                return(i)
            else:
                None

def killdata(sbd):
    #input = './inp.csv'
    #sbd = sbdata(input)
    no0,no1,no2,dl = sbd.get_data_range("小梁配置",0) #nameとリストを渡す。#[nameのある行i, <data>のある行i, deta終了行i, 範囲のテキストデータ]
    #小梁リストを抜き出す
    BL = get_jrow(dl,9) #9列目だけのデータ取得
    ul = (get_unique(BL)) #ユニークなリストのみ残す

    #配置されていない小梁断面を削除する予定(行リストを作成する、まだ削除しない)
    no0,no1,no2,dl = sbd.get_data_range("S小梁断面",0) #nameとリストを渡す #nameとリストを渡す。#[nameのある行i, <data>のある行i, deta終了行i, 範囲のテキストデータ]
    BL = get_jrow(dl,0)
    nox = no1 + 1 #dataのある行のナンバー
    kill = [] #最後に削除する行のリスト(このタイミングでは変えない)
    for i in range(len(BL)):
        li = BL[i]
        x = nox + i
        if li in ul:
            None
        else:
            kill.append(x)

def killer_kome(s):
    s = s.replace("*", "")
    return(s)

def check_export(sbd, crit0, crit1):
    #input = './inp.csv'
    #標準S小梁リスト(北川作成)を呼び出す。(作成予定)
    #EXPファイルから"S小梁断面算定表"の項目を見て
    #小梁の断面算定結果を見て 設計を整える。
    #入力csvファイルを読み込んでリストに格納
    lxp = sbd.lxp
    no0,no1,no2,dl = sbd.get_data_range("S小梁断面算定表",1) #nameとリストを渡す。
    ITI = []
    ITIc = []
    
    for i in range(len(dl)):
        if "[" in dl[i][0] and "B" in dl[i][0]: #Bのついている小梁しか検討できないことになる。あとで直したい。
            hantei = "OK"
            bname = dl[i][0].replace(" ","")
            bname = bname.replace("[","")
            bname = bname.replace("]","")
            first = int(dl[i+1][1].split("=")[1]) #"一次="
            itii = [bname, dl[i][1].replace("[",""), dl[i][2], dl[i][3], dl[i][4], dl[i][5].replace("]",""),first]
            os = 2 #下方向のオフセット
            crit0org = float(killer_kome(dl[i+os][15]))
            crit1org = int(killer_kome(dl[i+os][21].split("/")[1].replace(" ","")))
            
            if crit0org <= crit0:
                print(crit0org,"<=",crit0,"...OK",itii)
            else:
                print(crit0org,">",crit0,"...NG",itii)
                hantei = "NG"
            if crit1org >= crit1:
                print(crit1org,">=",crit1,"...OK",itii)
            else:
                print(crit1org,"<",crit1,"...NG",itii)
                hantei = "NG"
            
            itii.append(hantei)
            ITI.append(itii)
            if hantei == "NG":
                ITIc.append(itii) #NGの位置のリスト
            else:
                None

    return(ITIc)

def change_inport(sbd, ITIc, nwpath):
    #inport のファイルで小梁の符号を書き変える。
    #小梁断面リスト
    l = sbd.l
    #nameとリストを渡す。#[nameのある行i, <data>のある行i, deta終了行i, 範囲のテキストデータ] = sbd.get_data_range()
    no0,no1,no2,dl = sbd.get_data_range("S小梁断面", 0) #nameとリストを渡す
    BLn = get_jrow(dl,0) #小梁断面の符号リスト
    no0,no1,no2,dl = sbd.get_data_range("小梁配置", 0) #nameとリストを渡す。
    
    ci = []
    for li in ITIc:
        sp = " - "
        print(li[1], li[3] + sp +li[5] + sp + li[2] + sp + li[4], li[6], li[0])
        iii = dls(dl, li[1], li[3] + sp +li[5] + sp + li[2] + sp + li[4], li[6], li[0])
        ci.append(iii)

    for li in ci: #ciは小梁配置の下方向番号
        ind = li+no1+1 #書き換える行ナンバー
        #print(ind)
        no = list_no(BLn, l[ind][9]) # 小梁の位置
        l[ind][9] = BLn[no+1] #小梁符号を書き換える

    #リストを新たなcsvファイルに保存
    with open(nwpath, 'w', newline = "") as f:
        writer = csv.writer(f)
        writer.writerows(l)

###################################################################################
# 同じディレクトリのinp.csv, exp.csvのファイルを読み込んで、
# S小梁断面を編集したinp2.csvを作成する。
#
#
###################################################################################
#def main():
def csvmaker(inpath, expath, nwpath, crit0, crit1):
    #inpath = "./data/csv/inp.csv"
    #expath = "./data/csv/exp.csv"
    #nwpath = "./data/cev/inp0.csv"
    sbd = sbdata(inpath, expath)
    l = sbd.l #入力のcsvリスト
    #lxp = sbd.lexp #出力のcsvリスト
    ITIc = check_export(sbd, crit0, crit1) #出力でクライリアを確認
    #ITIc :: S小梁断面算定表でNGとなる小梁のリスト

    print("NGlist=", ITIc)
    change_inport(sbd, ITIc, nwpath) #inportファイルの書き換え
    return(len(ITIc)) #小梁のエラー個数を返却

if __name__ == "__main__":
    main()

ss7_scmd.py

import codecs

def shift(s): 
    s = s.encode("shift_jis")
    return(s)

def rename_ikn(PATH_IKN):
    a = PATH_IKN.find(".")
    s = PATH_IKN[0:a] + "_Auto" + PATH_IKN[a:]
    return(s) 

#def main(PATH_IKN,base_scmd, openfile):
def go_scmd(PATH_IKN, base_scmd, openfile, inpath, expath, nwinpath):
    inpcsv0 = nwinpath
    inpcsv = inpath
    outcsv = expath
        
    fout = codecs.open(openfile, "w", "shift_jis") #実行ファイルはss03.scmd

    s = ""
    for line in codecs.open(base_scmd, "r", "shift_jis"): #データを読み込んですべて一つの文字列とする。
        s += line
    s.encode("utf-8")
    
    s = s.replace("PATH_IKN", PATH_IKN) #文字列のPATH_IKNをssデータの絶対パスに変更

    s = s.replace("PATH_CSV_0_inp", inpcsv0) #文字列の書き換え
    s = s.replace("PATH_CSVinp", inpcsv) #文字列の書き換え

    s = s.replace("PATH_CSVexp", outcsv) #文字列の書き換え

    fout.write(s)
    fout.close()

Discussion