Feb-05-2020, 05:25 PM
import os import shutil ##from tkinter import filedialog,messagebox ##from tkinter import * import glob ##import pandas as pd ##import pyodbc[quote][/quote] ##import bz2 from Tkinter import * import Tkinter, Tkconstants, tkFileDialog, tkMessageBox from datetime import datetime import arcpy import openpyxl import sys import datetime import logging import kcmoDataFunc as DF ### class for MACP User Interface class MACP_GUI: initdir = os.getcwd() def __init__(self, master): self.master = master master.title("KCMO Processing - Set Data Paths") ## create main containers self.frameGDB = Frame(master, width=890, height=25, pady=3) self.frameMDB = Frame(master, width=890, height=25, pady=3) self.frameParams = Frame(master, width=890, height=100, pady=3) self.frameButtons = Frame(master, width=890, height=50, pady=3) ## layout main containers master.grid_rowconfigure(1, weight=1) master.grid_columnconfigure(0, weight=1) self.frameGDB.grid(row=0, sticky="ew") self.frameMDB.grid(row=1, sticky="ew") self.frameParams.grid(row=2, sticky="nsew") self.frameButtons.grid(row=3, sticky="ew") # create widgets for top and bottom frames self.gdb_button = Button(self.frameGDB, text="Set GDB Path", command=self.setFulcrumGDBPath) self.gdbEntryTitle = Entry(self.frameGDB,width=130, textvariable=gdbPath) self.mdb_button = Button(self.frameMDB, text="Set MDB Path", command=self.setMDBPath) self.mdbEntryTitle = Entry(self.frameMDB, width=130, textvariable=mdbPath) self.run_button = Button(self.frameButtons, text="Run Processs", command=startProcess,state=NORMAL,anchor=CENTER) self.close_button = Button(self.frameButtons, text="Close", command=root.destroy) self.lblProjName = Label(self.frameParams, text="Project Name:",width=10) self.tbxProjName = Entry(self.frameParams, textvariable=projNum) self.gdb_button.grid(row=1,column=1) self.gdbEntryTitle.grid(row=1,column=2,columnspan=6) self.mdb_button.grid(row=1,column=1) self.mdbEntryTitle.grid(row=1,column=2,columnspan=6) self.run_button.grid(row=1,column=1) self.close_button.grid(row=1,column=2) self.lblProjName.grid(row=1, column=3,padx=5) self.tbxProjName.grid(row=1,column=4) def setFulcrumGDBPath(self): gdbFName = tkFileDialog.askdirectory(initialdir = self.initdir,title = "Select Fulcrum database") if os.path.isdir(gdbFName): gdbPath.set(gdbFName) else: tkMessageBox.showinfo("Error Setting Path", "Invalid Fulcrum GDB Path") def setMDBPath(self): macpFName = tkFileDialog.askopenfilename(initialdir = self.initdir,title = "Select MDB database",filetypes = (("mdb files","*.mdb"),("all files","*.*"))) if os.path.isfile(macpFName): ##self.MACPlabelPath.config(text=macpFName) mdbPath.set(macpFName) else: tkMessageBox.showinfo("Error Setting Path", "Invalid MDB Path") def ValidDBPaths(self): tfVal = False tfGDBVal = False tfMDBVal = False tfProjNameVal = False if not gdbPath.get() == '': if os.path.isdir(gdbPath.get()): tfGDBVal = True else: tfGDBVal = False else: tfGDBVal = False if not mdbPath.get() == '': if os.path.isfile(mdbPath.get()): tfMDBVal = True else: tfMDBVal = False else: tfMDBVal = False if not projNum.get()== '': tfProjNameVal = True else: tfProjNameVal = False if tfGDBVal == True and tfMDBVal == True: ##and tfProjNameVal == True: tfVal = True return tfVal ### end class for MACP User Interface ####### ### start code for data processing ####### def startLogging(): dt = datetime.datetime.now().strftime("%Y_%m%d_%I%M%S") ##dirpath = os.getcwd() logfilePath = os.getcwd() + "\\Logs\\KCMOData_" print logfilePath LOG_FILENAME = logfilePath + dt + '.log' ##LOG_FILENAME = parser.get('LOGS','LOGFILEPATHNAME') + dt + '.log' logPath = os.path.dirname(LOG_FILENAME) if not os.path.exists(logPath): os.makedirs(logPath) print LOG_FILENAME logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG,filemode='w',format='%(asctime)s %(levelname)s %(message)s') return def createDictsFromXL(wbPath): try: logging.info("createDictsFromXL - creating field dictionaries...") print("createDictsFromXL - creating field dictionaries...") wb = openpyxl.load_workbook(wbPath) wsForm = wb['FormFlds'] wsPipe = wb['PipeFlds'] wsDetail = wb['DetailFlds'] totalRowCnt = wsForm.max_row print(totalRowCnt) rwCnt = 0 sheet_range = 'A1:B1' + str(totalRowCnt) for row in wsForm[sheet_range]: rwCnt += 1 mdbFld = wsForm.cell(row=rwCnt, column=1).value fulFld = wsForm.cell(row=rwCnt, column=2).value if (mdbFld != None): ##print(mdbFld + " - " + fulFld) dictFormFldsMap[mdbFld] = fulFld totalRowCnt = wsPipe.max_row print(totalRowCnt) rwCnt = 0 sheet_range = 'A1:B1' + str(totalRowCnt) for row in wsPipe[sheet_range]: rwCnt += 1 mdbFld = wsPipe.cell(row=rwCnt, column=1).value fulFld = wsPipe.cell(row=rwCnt, column=2).value if (mdbFld != None): ##print(mdbFld + " - " + fulFld) dictPipeFldsMap[mdbFld] = fulFld totalRowCnt = wsDetail.max_row print(totalRowCnt) rwCnt = 0 sheet_range = 'A1:B1' + str(totalRowCnt) for row in wsDetail[sheet_range]: rwCnt += 1 mdbFld = wsDetail.cell(row=rwCnt, column=1).value fulFld = wsDetail.cell(row=rwCnt, column=2).value if (mdbFld != None): print(mdbFld + " - " + fulFld) dictDetailFldsMap[mdbFld] = fulFld except Exception as e: logging.exception("Error in createDictsFromXL - exiting...") print "Error in createDictsFromXL - exiting..." sys.exit(1) return def copyImageFile(fromImgName,toImgName): try: logging.info("copyImageFile - copying image...") print("copyImageFile - copying image...") ##fromPath = r"G:\ArcGIS\Kansas_City_MO\18-218\TREKK\Berts_workspace\FulcrumExport" fromPath = os.path.dirname(gdbPath.get()) ##toPath = r"G:\ArcGIS\Kansas_City_MO\18-218\TREKK\Berts_workspace\AccessDB\MHPhotos" toPath = os.path.dirname(mdbPath.get()) + "\\MHPhotos" if not os.path.exists(toPath): os.mkdir(toPath) oldImgName = fromPath + "\\" + fromImgName + ".jpg" newImgName = toPath + "\\" + toImgName ##os.rename(oldImgName,newImgName) if os.path.exists(oldImgName): logging.info("copyImageFile - copying... " + oldImgName + " to " + newImgName) print("copying... " + oldImgName + " to " + newImgName) shutil.copyfile(oldImgName,newImgName) else: logging.info("!!!!!!!! copyImageFile - file does not exists - " + fromImgName) except Exception as e: logging.exception("Error in copyImageFile - exiting...") print "Error in copyImageFile - exiting..." sys.exit(1) return def processData(): try: logging.info("processData - start processing data...") print("processData - start processing data...") accDB = str(mdbPath.get()) ## r"G:\ArcGIS\Kansas_City_MO\18-218\TREKK\Berts_workspace\AccessDB\Brookside_Master_Database.mdb" arcGDB = str(gdbPath.get()) ## r"G:\ArcGIS\Kansas_City_MO\18-218\TREKK\Berts_workspace\FulcrumExport\kcmo_brookside_manhole_inspection_18_218.gdb" lstPipeTbls = ["pipes"] ## includes pipe phot and seal photo lstDefectTbls = ["bench_defects","channel_defects","chimney_defects","cone_defects" ,"cover_defects","frame_defects","ring_defects","seal_defects","steps_defects","wall_defects"] ## includes photos dictDefectAbbreve = { "bench": "bnch", "channel": "chnl", "chimney": "chim", "cone": "cone", "cover": "cvr", "frame": "frm", "ring": "rng", "steps": "step", "wall": "wall", 'seal': "FCS" } dictLocation = { "Street": "St", "Parking": "Park", "Easement": "Ease", "Alley": "Al" } mhTblName = os.path.basename(arcGDB).split('.')[0] ##mhTblName = arcGDB.split('\\')[-1].split('.')[0] mdbFormTbls = accDB +"\ww_junction_survey_form" mdbPipeTbl = accDB +"\ww_junction_survey_form_pipes" mdbDetailTbl = accDB +"\ww_junction_survey_form_detail" ##print(mhTblName) tblMH = arcGDB + "\\" + mhTblName tblPipes = arcGDB + "\\" + mhTblName + "_pipes" print(tblMH) lstFulIdFlds = ['manhole_id','fulcrum_id'] whereCl = "status not like 'Needs%'" ##"status in ('Inspection Complete')" dictFulcIDS = {f[0]:f[1:] for f in arcpy.da.SearchCursor(tblMH,lstFulIdFlds,whereCl)} lstGdbFlds = "*" lstMDbFlds = list(dictFormFldsMap.keys()) lstMDbPipeFlds = list(dictPipeFldsMap.keys()) lstMDbDetailFlds = list(dictDetailFldsMap.keys()) ##search_feats = {f[0]:f[1:] for f in arcpy.da.SearchCursor(tbl_completed_inspections,lstGdbFlds)} ##cursMH_FormTbl = arcpy.da.InsertCursor(mdbFormTbls,lstMDbFlds) lstDepthFlds = ["surchrg_depth","debr_silt_depth","GRADE_ELEV"] ##('S099-115','S099-119','S100-028','S102-526','S100-548','S100-083','S103-721','S101-281','BMcDVP106','S100-093','S101-283','S101-296','S100-188','S102-490','S102-401') ##whereCl = "status not like 'Needs%'" ## AND manhole_id in ('S099-115','S099-119','S100-028','S102-526','S100-548','S100-083','S103-721','S101-281','BMcDVP106','S100-093','S101-283','S101-296','S100-188','S102-490','S102-401')" ## S099-115 S099-119"status in ('Inspection Complete')" "status not like 'Needs%'" S099-119 ##whereCl = "status = 'Could Not Access'" whereCl = "manhole_id in ('S085-068'status in ('Inspection Complete')" "status not like 'Needs%'" logging.info("processData - start main search cursor...") with arcpy.da.SearchCursor(tblMH, lstGdbFlds,whereCl) as cursFulMH: for rec in cursFulMH: mhid = "" inspDate = "" photoCnt = 3 dictMH_Info = {} dictMHDetail_Info = {} mhid = rec[cursFulMH.fields.index("manhole_id")] logging.info("**********processData - processing manhole - " + mhid) mhStatus = rec[cursFulMH.fields.index("status")] rimval = rec[cursFulMH.fields.index("rim")] ventedval = rec[cursFulMH.fields.index("vented")] pondingval = rec[cursFulMH.fields.index("ponding")] print(mhid) dictMHDetail_Info["wwtmnhl_id"] = mhid inspDate = str(rec[cursFulMH.fields.index("startcomplete_date")]).replace("-","") lstData = [] logging.info("processData - processing manhole attributes") for fldNameMDB in lstMDbFlds: fulcFld = dictFormFldsMap[fldNameMDB] ##fulcFldIdx = cursFulMH.fields.index(fld) val = "" if fldNameMDB == "add_house_no": val = rec[cursFulMH.fields.index("address_sub_thoroughfare")] if val is not None: val = val.encode('ascii','ignore') if "-" in val: val = val.split("-")[0] if len(val) > 5: val = val[:5] dictMH_Info[fldNameMDB] = int(val) else: dictMH_Info[fldNameMDB] = 0 elif fldNameMDB == "add_str_pre_dir": addr = rec[cursFulMH.fields.index("address_thoroughfare")] if addr is not None: val = DF.parseAddress("stdir",addr) dictMH_Info[fldNameMDB] = val else: dictMH_Info[fldNameMDB] = "" elif fldNameMDB == "add_str_name": addr = rec[cursFulMH.fields.index("address_thoroughfare")] if addr is not None: val = DF.parseAddress("stname",addr) dictMH_Info[fldNameMDB] = val else: dictMH_Info[fldNameMDB] = "" elif fldNameMDB == "add_str_suf": addr = rec[cursFulMH.fields.index("address_thoroughfare")] if addr is not None: val = DF.parseAddress("sttype",addr) dictMH_Info[fldNameMDB] = val else: dictMH_Info[fldNameMDB] = "" elif fldNameMDB == "problm_d": val = "no" dictMH_Info[fldNameMDB] = val elif fldNameMDB == "inspecting_firm": val = "TREKK" dictMH_Info[fldNameMDB] = val elif fldNameMDB == "add_state": val = "MO" dictMH_Info[fldNameMDB] = val elif fldNameMDB == "prior_hist_d": val = "No" dictMH_Info[fldNameMDB] = val elif fldNameMDB == "add_city": val = rec[cursFulMH.fields.index("address_locality")] if val is None: val = "Kansas City" dictMH_Info[fldNameMDB] = val elif fldNameMDB == "weath": val = rec[cursFulMH.fields.index(fulcFld)] if val is not None: dictMH_Info[fldNameMDB] = val.split(")")[1].strip() else: dictMH_Info[fldNameMDB] = "Dry" elif fldNameMDB == "location": val = rec[cursFulMH.fields.index(fulcFld)] if val is not None: dictMH_Info[fldNameMDB] = dictLocation[val] else: dictMH_Info[fldNameMDB] = "St" elif fldNameMDB == "start": sd = rec[cursFulMH.fields.index("startcomplete_date")] if sd is not None: st = str(rec[cursFulMH.fields.index("start_time")]) + ":00" val = datetime.datetime.strptime(sd + " " + st, '%Y-%m-%d %H:%M:%S') dictMH_Info[fldNameMDB] = val else: dictMH_Info[fldNameMDB] = None elif fldNameMDB == "complete": cd = rec[cursFulMH.fields.index("startcomplete_date")] if cd is not None: ct = str(rec[cursFulMH.fields.index("complete_time")]) + ":00" val = datetime.datetime.strptime(cd + " " + ct, '%Y-%m-%d %H:%M:%S') dictMH_Info[fldNameMDB] = val else: dictMH_Info[fldNameMDB] = None elif fldNameMDB == "crew": cr = rec[cursFulMH.fields.index("crew")] cro = rec[cursFulMH.fields.index("crew_other")] val = str(cr) if cro is not None: val = val + "," + str(cro) if len(val) > 10: val = val[:10] dictMH_Info[fldNameMDB] = val elif fldNameMDB == "area_photo": val = mhid + "_01_" + inspDate + ".jpg" photoIDNum = rec[cursFulMH.fields.index(fulcFld)] if photoIDNum is not None: copyImageFile(photoIDNum,val) dictMH_Info[fldNameMDB] = val else: dictMH_Info[fldNameMDB] = "" elif fldNameMDB == "top_photo": val = mhid + "_02_" + inspDate + ".jpg" photoIDNum = rec[cursFulMH.fields.index(fulcFld)] if photoIDNum is not None: copyImageFile(photoIDNum,val) dictMH_Info[fldNameMDB] = val else: dictMH_Info[fldNameMDB] = "" elif fldNameMDB in lstDepthFlds: val = rec[cursFulMH.fields.index(fulcFld)] if val == None and mhStatus in ["Inspection Complete","Surcharged"]: val = 0 dictMH_Info[fldNameMDB] = val elif fldNameMDB == "proj": val = projNum.get() ## string variable set in UI. dictMH_Info[fldNameMDB] = val elif fldNameMDB == "vent_num" or fldNameMDB == "vent_diam_in": val = rec[cursFulMH.fields.index(fulcFld)] if mhStatus in ["Inspection Complete","Could Not Open"]: if val == None: val = 0 dictMH_Info[fldNameMDB] = val elif fldNameMDB == "GRADE_ELEV": val = rec[cursFulMH.fields.index(fulcFld)] if mhStatus == "Could Not Open" and rimval == "At Grade": val = 0 dictMH_Info[fldNameMDB] = val elif fldNameMDB =='POND_DEPTH': val = rec[cursFulMH.fields.index(fulcFld)] if pondingval == "No": val = 0 dictMH_Info[fldNameMDB] = val else: val = rec[cursFulMH.fields.index(fulcFld)] if "(" in str(val): val = val.split('(', 1)[1].split(')')[0] xx = "" dictMH_Info[fldNameMDB] = val ##lstData.append(val) logging.info("processData - processing manhole details") for fldNameMDBDetails in lstMDbDetailFlds: fulcFldDetail = dictDetailFldsMap[fldNameMDBDetails] val = "" val = rec[cursFulMH.fields.index(fulcFldDetail)] if "comment" in fldNameMDBDetails and val is not None: val = val[:40] if val == None and "material" in fulcFldDetail and "cover" not in fulcFldDetail and mhStatus in ["Inspection Complete","Surcharged"]: if "FCS" in fldNameMDBDetails: val = "12" else: val = "Z" if "(" in str(val): val = val.split('(', 1)[1].split(')')[0] dictMHDetail_Info[fldNameMDBDetails] = val logging.info("processData - inserting manhole attributes") print(dictMH_Info) lstFlds = list(dictMH_Info.keys()) cursMH_FormTbl = arcpy.da.InsertCursor(mdbFormTbls,lstFlds) newrowMH = list(dictMH_Info.values()) cursMH_FormTbl.insertRow(newrowMH) del cursMH_FormTbl ## insert mh detail info to detail table logging.info("processData - inserting manhole details") lstFldsDetails = list(dictMHDetail_Info.keys()) cursMH_DetailTbl = arcpy.da.InsertCursor(mdbDetailTbl,lstFldsDetails) newrowMHDetail = list(dictMHDetail_Info.values()) cursMH_DetailTbl.insertRow(newrowMHDetail) del cursMH_DetailTbl whereClParent = "fulcrum_parent_id = '" + ''.join(dictFulcIDS[mhid]) + "'" logging.info("processData - processing pipes") pipecnt = 1 dictPipe_Info = {} with arcpy.da.SearchCursor(tblPipes, lstGdbFlds,whereClParent) as cursFulPipe: for pipe in cursFulPipe: if pipecnt == 1: dictPipe_Info["wwtmnhl_id"] = mhid replaceval = "p" + str(pipecnt) for pipeFldMdb in lstMDbPipeFlds: fulcPipeFld = dictPipeFldsMap[pipeFldMdb] if "image" in pipeFldMdb: ## == "p1_image" or pipeFldMdb == "p1_2_image": photoNum = str(photoCnt) if photoCnt < 10: photoNum = "0" + str(photoCnt) val = mhid + "_" + photoNum + "_" + inspDate + ".jpg" photoIDNum = str(pipe[cursFulPipe.fields.index(fulcPipeFld)]) copyImageFile(photoIDNum,val) pipeFldMdb = pipeFldMdb.replace("p1", replaceval) dictPipe_Info[pipeFldMdb] = val photoCnt = photoCnt + 1 else: val = pipe[cursFulPipe.fields.index(fulcPipeFld)] if "(" in str(val): val = val.split('(', 1)[1].split(')')[0] pipeFldMdb = pipeFldMdb.replace("p1", replaceval) dictPipe_Info[pipeFldMdb] = val pipecnt = pipecnt + 1 ##print(dictPipe_Info) logging.info("processData - inserting pipe info") if len(dictPipe_Info.keys()) > 0: lstFldsPipe = list(dictPipe_Info.keys()) cursPipeTbl = arcpy.da.InsertCursor(mdbPipeTbl,lstFldsPipe) newrowPipe = list(dictPipe_Info.values()) cursPipeTbl.insertRow(newrowPipe) del cursPipeTbl logging.info("processData - processsing defects") dictDefectCnt = {} dictDefect_Info = {} lstCheckCond = ["FCS_cond","cvr_cond","frm_cond","rng_cond"] for key in dictMHDetail_Info: if str(key) in lstCheckCond: val = dictMHDetail_Info[key] if val == "G": pfx = str(key).split('_')[0] defKey = pfx + "_def_1" dictDefect_Info[defKey] = 1 dictDefectCnt[pfx] = 1 for defTbl in lstDefectTbls: defTblPath = arcGDB + "\\" + mhTblName + "_" + defTbl defFlds = "*" defectCat = defTbl.split("_")[0] lstDefFlds = [] lstDefFlds = [defectCat + "_defect",defectCat + "_photo"] if defectCat == "seal": lstDefFlds = [d.replace('photo','photos') for d in lstDefFlds] if defectCat == "cone": lstDefFlds = [d.replace('photo','photo1') for d in lstDefFlds] mdbDefPrefix = dictDefectAbbreve[defectCat] ##print(lstDefFlds) with arcpy.da.SearchCursor(defTblPath, lstDefFlds,whereClParent) as cursFulDefect: for defect in cursFulDefect: if mdbDefPrefix in dictDefectCnt: dictDefectCnt[mdbDefPrefix] = dictDefectCnt[mdbDefPrefix] + 1 else: dictDefectCnt[mdbDefPrefix] = 1 defVal = str(defect[0]) if "(" in defVal: defVal = defVal.split('(', 1)[1].split(')')[0] defPhoto = str(defect[1]) photoNum = str(photoCnt) if photoCnt < 10: photoNum = "0" + str(photoCnt) photoFileName = mhid + "_" + photoNum + "_" + inspDate + ".jpg" copyImageFile(defPhoto,photoFileName) photoCnt = photoCnt + 1 mdbDefFld = mdbDefPrefix + "_def_" + str(dictDefectCnt[mdbDefPrefix]) if dictDefectCnt[mdbDefPrefix] > 1: thePfx = mdbDefPrefix if "FCS" in mdbDefPrefix: thePfx = mdbDefPrefix + "eal" mdbDefPhotoFld = thePfx + "_photo_" + str(dictDefectCnt[mdbDefPrefix]) else: thePfx = mdbDefPrefix if "FCS" in mdbDefPrefix: thePfx = mdbDefPrefix + "eal" mdbDefPhotoFld = thePfx + "_photo" dictDefect_Info[mdbDefFld] = defVal dictDefect_Info[mdbDefPhotoFld] = photoFileName logging.info("processData - inserting defects - update cursor") if len(dictDefect_Info.keys()) > 0: whereClDetail = "wwtmnhl_id = '" + mhid + "'" logging.info("processData - inserting defects - " + whereClDetail) lstFldsDefs = list(dictDefect_Info.keys()) lstDefVals = list(dictDefect_Info.values()) logging.info("processData - insert fields...") logging.info(lstFldsDefs) logging.info("processData - insert values...") logging.info(lstDefVals) with arcpy.da.UpdateCursor(mdbDetailTbl,lstFldsDefs,whereClDetail) as cursDetailTbl: for row in cursDetailTbl: cntVals = 0 for defval in lstDefVals: row[cntVals] = defval cntVals = cntVals + 1 cursDetailTbl.updateRow(row) del cursDetailTbl except Exception as e: logging.exception("Error in processData - exiting...") print "Error in processData - exiting..." sys.exit(1) return ##sys.exit(1) def startProcess(): if not macp_gui.ValidDBPaths(): print "valid paths - false" logging.info('+++++++++++++++++++++++ Invalid value(s) enter in form...') tkMessageBox.showinfo("Error in Form values", "Invalid value(s) enter in form...") else: startLogging() xlsPath = os.getcwd() + "\AccessDBFields_bert.xlsx" createDictsFromXL(xlsPath) logging.info('+++++++++++++++++++++++ Process Started...') logging.info('++++++++++++++++++++++++++++++++++++++++++') logging.info('++++++++++++++++++++++++++++++++++++++++++') print '+++++++++++++++++++++++ Process Started...' print '++++++++++++++++++++++++++++++++++++++++++' print '++++++++++++++++++++++++++++++++++++++++++' processData() print '++++++++++++++++++++++++++++++++++++++++++' print '++++++++++++++++++++++++++++++++++++++++++' print '+++++++++++++++++++++++ Process Completed...' logging.info('++++++++++++++++++++++++++++++++++++++++++') logging.info('++++++++++++++++++++++++++++++++++++++++++') logging.info('+++++++++++++++++++++++ Process Completed...') return dictFormFldsMap = {} dictPipeFldsMap = {} dictDetailFldsMap = {} ##createDictsFromXL() ##rocessData() root = Tk() root.geometry("900x200") root.resizable(False,False) root.eval('tk::PlaceWindow %s center' % root.winfo_pathname(root.winfo_id())) root.attributes('-topmost', True) gdbPath = StringVar() mdbPath = StringVar() projNum = StringVar() macp_gui = MACP_GUI(root) root.mainloop()