''' BSD 3-Clause License Copyright (c) 2019, Donald N. Bockoven III All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ''' import Tkinter as tk import tkMessageBox import ttk import tkFont import wood_classes as wood import matplotlib matplotlib.use('TKAgg') from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg from matplotlib.figure import Figure import matplotlib.pyplot as plt import tkFileDialog import os import math class Master_window: def __init__(self, master): self.master = master self.f_size = 8 helv = tkFont.Font(family='Helvetica',size=self.f_size, weight='bold') self.menubar = tk.Menu(self.master) self.menu = tk.Menu(self.menubar, tearoff=0) self.menu_props = tk.Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label = "File", menu=self.menu) self.menu.add_command(label="Open", command=self.file_open) self.menu.add_separator() self.menu.add_command(label="Calc", command=self.run) self.menu.add_command(label="Build P-lateral Pressure", command=self.generate_interaction_graph) self.menu.add_command(label="Build P-M Chart", command=self.generate_pm_graph) self.menu.add_separator() self.menu.add_command(label="Quit", command=self.quit_app) try: self.master.config(menu=self.menubar) except AttributeError: self.master.tk.call(master, "config", "-menu", self.menubar) #Main Frames self.main_frame = tk.Frame(master, bd=2, relief='sunken', padx=1,pady=1) self.main_frame.pack(anchor='c', padx= 1, pady= 1, fill=tk.BOTH, expand=1) self.base_frame = tk.Frame(master, bd=2, relief='sunken', padx=1,pady=1) self.base_frame.pack(side=tk.BOTTOM, padx= 1, pady= 1, fill=tk.X, expand=1) self.nb = ttk.Notebook(self.main_frame) self.nb.pack(fill=tk.BOTH, expand=1) #Tab 1 self.page1 = ttk.Frame(self.nb) self.nb.add(self.page1, text='Wall and Stud Information and Inputs - Find Axial Capacity Per Stud') self.pg1_frame = tk.Frame(self.page1, bd=2, relief='sunken', padx=1,pady=1) self.pg1_frame.pack(fill=tk.BOTH,expand=1, padx=2, pady=2) #user input frame self.input_frame = tk.LabelFrame(self.pg1_frame, text="Inputs", bd=2, relief='sunken', padx=2, pady=2, font=helv) #Wall Geometry Frame self.geo_frame = tk.LabelFrame(self.input_frame, text="Wall Stud Geometry: ", bd=2, relief='sunken', padx=2, pady=2, font=helv) #stud dimensions - nominal tk.Label(self.geo_frame, text='Nominal Stud Size:', font=helv).grid(row=1,column=1) self.b_nom = tk.StringVar() self.b_nom.set('2') self.b_nom_selection = tk.OptionMenu(self.geo_frame, self.b_nom, '2','3','4','(2)2','(3)2', command=self.actual_stud_size) self.b_nom_selection.grid(row=2,column=1) tk.Label(self.geo_frame, text='x', font=helv).grid(row=2,column=2) self.d_nom = tk.StringVar() self.d_nom.set('6') self.d_nom_selection = tk.OptionMenu(self.geo_frame, self.d_nom, '3','4','5','6','8','10','12','14','16', command=self.actual_stud_size) self.d_nom_selection.grid(row=2,column=3) #stud dimensions - actual tk.Label(self.geo_frame, text='Actual Stud Size:', font=helv).grid(row=1,column=4) self.b_actual_label = tk.Label(self.geo_frame, text='1.5', font=helv) self.b_actual_label.grid(row=2,column=4) tk.Label(self.geo_frame, text='x', font=helv).grid(row=2,column=5) self.d_actual_label = tk.Label(self.geo_frame, text='5.5', font=helv) self.d_actual_label.grid(row=2,column=6) #stud Spacing self.spacing_label = tk.Label(self.geo_frame, text='Stud Spacing: ', font=helv) self.spacing_label.grid(row=3,column=1, sticky=tk.E) self.stud_spacing = tk.StringVar() self.stud_spacing.set('16') self.spacing_entry = tk.Entry(self.geo_frame, textvariable=self.stud_spacing, width=10, font=helv) self.spacing_entry.grid(row=3,column=2, sticky=tk.W) tk.Label(self.geo_frame, text='in', font=helv).grid(row=3,column=3) #Wall Height self.height_label = tk.Label(self.geo_frame, text='Wall Height: ', font=helv) self.height_label.grid(row=4,column=1, sticky=tk.E) self.wall_height = tk.StringVar() self.wall_height.set('10') self.height_entry = tk.Entry(self.geo_frame, textvariable=self.wall_height, width=10, font=helv) self.height_entry.grid(row=4,column=2, sticky=tk.W) tk.Label(self.geo_frame, text='ft', font=helv).grid(row=4,column=3) #subtract wall plates from height self.sub_plates = tk.IntVar() tk.Checkbutton(self.geo_frame, text=': Subtract Wall Plates from Height (y/n)', variable=self.sub_plates, font=helv).grid(row=3, column=4, sticky=tk.W) self.plates_label = tk.Label(self.geo_frame, text='# of 1.5" Plates to subtract: ', font=helv) self.plates_label.grid(row=4,column=4, sticky=tk.E) self.num_plates = tk.StringVar() self.num_plates.set(0) self.num_plates_entry = tk.Entry(self.geo_frame, textvariable=self.num_plates, width=5, font=helv) self.num_plates_entry.grid(row=4,column=5, sticky=tk.W) #Consider plate crushing for common capacities self.consider_crushing = tk.IntVar() tk.Checkbutton(self.geo_frame, text=': Consider plate crushing for common capacities (y/n)', variable=self.consider_crushing, font=helv).grid(row=5, column=4, sticky=tk.W) self.geo_frame.pack(fill=tk.X, padx=2, pady=2) #Reference Stud Design Values - Frame self.ref_stud_properties_frame = tk.LabelFrame(self.input_frame, text="Reference Stud Design Values : ", bd=2, relief='sunken', padx=2, pady=2, font=helv) #Wall Stud Grade self.grade_label = tk.Label(self.ref_stud_properties_frame,text = 'Grade :', font=helv) self.grade_label.grid(row=1, column=1, sticky=tk.E) self.grade = tk.StringVar() self.grade.set('No.1/No.2') grades = ['Select Structural','No.1 & Better','No.1/No.2','No.1','No.2','No.3','Stud','Construction','Utility'] self.grade_selection = tk.OptionMenu(self.ref_stud_properties_frame, self.grade, *grades) self.grade_selection.grid(row=1,column=2) #Fb self.fb_label = tk.Label(self.ref_stud_properties_frame,text = 'Fb :', font=helv) self.fb_label.grid(row=2, column=1, sticky=tk.E) self.fb_psi = tk.StringVar() self.fb_psi.set(875) self.fb_entry = tk.Entry(self.ref_stud_properties_frame, textvariable=self.fb_psi, width=10, font=helv) self.fb_entry.grid(row=2, column=2, sticky=tk.W) tk.Label(self.ref_stud_properties_frame, text='psi', font=helv).grid(row=2,column=3, sticky=tk.W) #Fv self.fv_label = tk.Label(self.ref_stud_properties_frame,text = 'Fv :', font=helv) self.fv_label.grid(row=3, column=1, sticky=tk.E) self.fv_psi = tk.StringVar() self.fv_psi.set(135) self.fv_entry = tk.Entry(self.ref_stud_properties_frame, textvariable=self.fv_psi, width=10, font=helv) self.fv_entry.grid(row=3, column=2, sticky=tk.W) tk.Label(self.ref_stud_properties_frame, text='psi', font=helv).grid(row=3,column=3, sticky=tk.W) #Fc self.fc_label = tk.Label(self.ref_stud_properties_frame,text = 'Fc :', font=helv) self.fc_label.grid(row=4, column=1, sticky=tk.E) self.fc_psi = tk.StringVar() self.fc_psi.set(1150) self.fc_entry = tk.Entry(self.ref_stud_properties_frame, textvariable=self.fc_psi, width=10, font=helv) self.fc_entry.grid(row=4, column=2, sticky=tk.W) tk.Label(self.ref_stud_properties_frame, text='psi', font=helv).grid(row=4,column=3, sticky=tk.W) #E self.E_label = tk.Label(self.ref_stud_properties_frame,text = 'E :', font=helv) self.E_label.grid(row=5, column=1, sticky=tk.E) self.E_psi = tk.StringVar() self.E_psi.set(1400000) self.E_entry = tk.Entry(self.ref_stud_properties_frame, textvariable=self.E_psi, width=15, font=helv) self.E_entry.grid(row=5, column=2, sticky=tk.W) tk.Label(self.ref_stud_properties_frame, text='psi', font=helv).grid(row=5,column=3, sticky=tk.W) #Emin self.Emin_label = tk.Label(self.ref_stud_properties_frame,text = 'Emin :', font=helv) self.Emin_label.grid(row=6, column=1, sticky=tk.E) self.Emin_psi = tk.StringVar() self.Emin_psi.set(510000) self.Emin_entry = tk.Entry(self.ref_stud_properties_frame, textvariable=self.Emin_psi, width=15, font=helv) self.Emin_entry.grid(row=6, column=2, sticky=tk.W) tk.Label(self.ref_stud_properties_frame, text='psi', font=helv).grid(row=6,column=3, sticky=tk.W) #Fc_perp_pl self.fc_perp_label = tk.Label(self.ref_stud_properties_frame,text = 'Fc_perp,bottom pl :', font=helv) self.fc_perp_label.grid(row=7, column=1, sticky=tk.E) self.fc_perp_psi = tk.StringVar() self.fc_perp_psi.set(425) self.fc_perp_entry = tk.Entry(self.ref_stud_properties_frame, textvariable=self.fc_perp_psi, width=10, font=helv) self.fc_perp_entry.grid(row=7, column=2, sticky=tk.W) tk.Label(self.ref_stud_properties_frame, text='psi', font=helv).grid(row=7,column=3, sticky=tk.W) #FRT? self.frt_yn = tk.IntVar() tk.Checkbutton(self.ref_stud_properties_frame, text=': FRT (y/n)', variable=self.frt_yn, font=helv).grid(row=1, column=4) self.frt_fb_label = tk.Label(self.ref_stud_properties_frame,text = 'Cfrt,fb :', font=helv) self.frt_fb_label.grid(row=2,column=4, sticky=tk.E) self.frt_fb = tk.StringVar() self.frt_fb.set(0.88) self.frt_fb_entry = tk.Entry(self.ref_stud_properties_frame, textvariable=self.frt_fb, width=10, font=helv) self.frt_fb_entry.grid(row=2,column=5, sticky=tk.W) self.frt_fv_label = tk.Label(self.ref_stud_properties_frame,text = 'Cfrt,fv :', font=helv) self.frt_fv_label.grid(row=3,column=4, sticky=tk.E) self.frt_fv = tk.StringVar() self.frt_fv.set(0.93) self.frt_fv_entry = tk.Entry(self.ref_stud_properties_frame, textvariable=self.frt_fv, width=10, font=helv) self.frt_fv_entry.grid(row=3,column=5, sticky=tk.W) self.frt_fc_label = tk.Label(self.ref_stud_properties_frame,text = 'Cfrt,fc :', font=helv) self.frt_fc_label.grid(row=4,column=4, sticky=tk.E) self.frt_fc = tk.StringVar() self.frt_fc.set(0.94) self.frt_fc_entry = tk.Entry(self.ref_stud_properties_frame, textvariable=self.frt_fc, width=10, font=helv) self.frt_fc_entry.grid(row=4,column=5, sticky=tk.W) self.frt_fc_perp_label = tk.Label(self.ref_stud_properties_frame,text = 'Cfrt,fc_perp :', font=helv) self.frt_fc_perp_label.grid(row=5,column=4, sticky=tk.E) self.frt_fc_perp = tk.StringVar() self.frt_fc_perp.set(0.95) self.frt_fc_perp_entry = tk.Entry(self.ref_stud_properties_frame, textvariable=self.frt_fc_perp, width=10, font=helv) self.frt_fc_perp_entry.grid(row=5,column=5, sticky=tk.W) self.frt_E_label = tk.Label(self.ref_stud_properties_frame,text = 'Cfrt,E :', font=helv) self.frt_E_label.grid(row=6,column=4, sticky=tk.E) self.frt_E = tk.StringVar() self.frt_E.set(0.94) self.frt_E_entry = tk.Entry(self.ref_stud_properties_frame, textvariable=self.frt_E, width=10, font=helv) self.frt_E_entry.grid(row=6,column=5, sticky=tk.W) self.frt_Emin_label = tk.Label(self.ref_stud_properties_frame,text = 'Cfrt,Emin :', font=helv) self.frt_Emin_label.grid(row=7,column=4, sticky=tk.E) self.frt_Emin = tk.StringVar() self.frt_Emin.set(0.94) self.frt_Emin_entry = tk.Entry(self.ref_stud_properties_frame, textvariable=self.frt_Emin, width=10, font=helv) self.frt_Emin_entry.grid(row=7,column=5, sticky=tk.W) self.species_label = tk.Label(self.ref_stud_properties_frame,text = 'Species :', font=helv) self.species_label.grid(row=8,column=1, sticky=tk.E) self.species = tk.StringVar() self.species.set('Spruce-Pine-Fur') self.species_entry = tk.Entry(self.ref_stud_properties_frame, textvariable=self.species, width=50, font=helv) self.species_entry.grid(row=8,column=2,columnspan=3) self.is_syp = tk.IntVar() tk.Checkbutton(self.ref_stud_properties_frame, text=': Southern Pine (y/n)', variable=self.is_syp, font=helv).grid(row=8, column=5) self.ref_stud_properties_frame.pack(fill=tk.X, padx=2, pady=2) self.enviro_treatment_frame = tk.LabelFrame(self.input_frame, text="Enviroment and Treatment : ", bd=2, relief='sunken', padx=2, pady=2, font=helv) #Moisture % self.moisture_label = tk.Label(self.enviro_treatment_frame,text = 'Moisture % :', font=helv) self.moisture_label.grid(row=1,column=1, sticky=tk.E) self.moisture = tk.StringVar() self.moisture.set(19.0) self.moisture_entry = tk.Entry(self.enviro_treatment_frame, textvariable=self.moisture, width=10, font=helv) self.moisture_entry.grid(row=1,column=2, sticky=tk.W) #Temp F self.temp_label = tk.Label(self.enviro_treatment_frame,text = 'Temperature (F) - <= 150 :', font=helv) self.temp_label.grid(row=2,column=1, sticky=tk.E) self.temp = tk.StringVar() self.temp.set(90.0) self.temp_entry = tk.Entry(self.enviro_treatment_frame, textvariable=self.temp, width=10, font=helv) self.temp_entry.grid(row=2,column=2, sticky=tk.W) #Incised? self.incised_yn = tk.IntVar() tk.Checkbutton(self.enviro_treatment_frame, text=': Incised (y/n)', variable=self.incised_yn, font=helv).grid(row=3, column=1, sticky=tk.W) self.enviro_treatment_frame.pack(fill=tk.X, padx=2, pady=2) self.lateral_frame = tk.LabelFrame(self.input_frame, text="Lateral Pressure : ", bd=2, relief='sunken', padx=2, pady=2, font=helv) #Pressure self.pressure_label = tk.Label(self.lateral_frame,text = 'Pressure (psf) :', font=helv) self.pressure_label.grid(row=1,column=1, sticky=tk.E) self.pressure = tk.StringVar() self.pressure.set("5.0") self.pressure_entry = tk.Entry(self.lateral_frame, textvariable=self.pressure, width=10, font=helv) self.pressure_entry.grid(row=1,column=2, sticky=tk.W) #Cd self.cd_label = tk.Label(self.lateral_frame,text = 'Cd :', font=helv) self.cd_label.grid(row=2,column=1, sticky=tk.E) self.cd = tk.StringVar() self.cd.set('1.0') cds = ['0.9','1.0','1.15','1.25','1.6','2.0'] self.cd_selection = tk.OptionMenu(self.lateral_frame, self.cd, *cds) self.cd_selection.grid(row=2, column=2) #Min Eccentricity? self.min_ecc_yn = tk.IntVar() tk.Checkbutton(self.lateral_frame, text=': Min. Eccentricty of d/6 (y/n)', variable=self.min_ecc_yn, font=helv).grid(row=3, column=1, sticky=tk.W) #Stud Lateral Braced on Compression Face self.com_lat_brace_yn = tk.IntVar() self.com_lat_brace_yn.set(1) tk.Checkbutton(self.lateral_frame, text=': Stud laterally braced on compression face (y/n)', variable=self.com_lat_brace_yn, command=self.com_lat_brace_func, font=helv).grid(row=4, column=1, sticky=tk.W) self.no_sheathing_yn = tk.IntVar() self.no_sheathing_yn.set(0) tk.Checkbutton(self.lateral_frame, text=': No Sheathing (y/n)', variable=self.no_sheathing_yn, command=self.no_sheating_func, font=helv).grid(row=5, column=1, sticky=tk.W) self.blocking_label = tk.Label(self.lateral_frame, text = 'Blocking (ft):', font=helv).grid(row=6, column=1, sticky=tk.E) self.blocking_ft = tk.StringVar() self.blocking_ft.set("4.0") self.blocking_entry = tk.Entry(self.lateral_frame, textvariable = self.blocking_ft, width=10, font=helv) self.blocking_entry.grid(row=6, column=2) self.lateral_frame.pack(fill=tk.X, padx=2, pady=2) self.b_run = tk.Button(self.input_frame,text="Calc", command=self.run, font=helv) self.b_run.pack(side=tk.RIGHT) self.b_build_chart = tk.Button(self.input_frame,text="Build P-Lateral Pressure Chart", command=self.generate_interaction_graph, font=helv, state = tk.DISABLED) self.b_build_chart.pack(side=tk.RIGHT) self.b_build_pm = tk.Button(self.input_frame,text="Build P-M Chart", command=self.generate_pm_graph, font=helv, state = tk.DISABLED) self.b_build_pm.pack(side=tk.RIGHT) self.input_frame.pack(side=tk.LEFT, padx=2, pady=2) #results frame self.results_frame = tk.LabelFrame(self.pg1_frame, text="Results", bd=2, relief='sunken', padx=2, pady=2) self.nds_table_frame = tk.LabelFrame(self.results_frame, text="NDS 2005 - Table 4.3.1", bd=2, relief='sunken', padx=2, pady=2) self.res_labels = [] self.res_nds_table_output = [] for y in range(0,7): for i in range(0,16): label = tk.Label(self.nds_table_frame, text='--') label.grid(row=y+1,column=i+1) self.res_labels.append(label) self.res_nds_table_output.append('-') self.res_labels[0].configure(text='') self.res_nds_table_output[0] = '' self.res_labels[1].configure(text='') self.res_nds_table_output[1] = ',' self.res_labels[14].configure(text='') self.res_nds_table_output[14] = ',' self.res_labels[15].configure(text='') self.res_nds_table_output[15] = '\n' factors = ['Cd','Cm','Ct','CL','Cf','Cfu','Ci','Cr','Cp','CT','Cb','Cfrt'] i=2 for c in factors: self.res_labels[i].configure(text=c) self.res_nds_table_output[i] = c i+=1 row_headers = ["Fb' = Fb ","Fv' = Fv ","Fc' = Fc ","Fc_perp' = Fc_perp ","E' = E ","Emin' = Emin "] i=16 for header in row_headers: self.res_labels[i].configure(text=header) self.res_nds_table_output[i] = header i+=16 i=31 for y in range(1,7): self.res_labels[i].configure(text='psi') self.res_nds_table_output[i] = 'psi\n' i+=16 self.nds_table_frame.pack(side=tk.TOP, padx=2, pady=2) ## Text Results Frame self.text_results_frame = tk.LabelFrame(self.results_frame, text="Calculation Results: ", bd=2, relief='sunken', padx=2, pady=2, font=helv) self.results_text_box = tk.Text(self.text_results_frame, height = 10, width = 10, bg= "grey90", font= tkFont.Font(family='Helvetica',size=8, weight='normal'), wrap=tk.WORD) self.results_text_box.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) self.restxt_scroll = tk.Scrollbar(self.text_results_frame, command=self.results_text_box.yview) self.restxt_scroll.pack(side=tk.LEFT, fill=tk.Y) self.results_text_box['yscrollcommand'] = self.restxt_scroll.set self.text_results_frame.pack(side=tk.TOP, fill=tk.BOTH, expand=True) self.b_output_res= tk.Button(self.results_frame,text="Export Results", command=self.write_text_results_to_file, font=helv, state = tk.DISABLED) self.b_output_res.pack(side=tk.RIGHT) self.b_output_pp= tk.Button(self.results_frame,text="Export P-Pressure Curves", command=self.print_pp_graph_common, font=helv, state = tk.DISABLED) self.b_output_pp.pack(side=tk.RIGHT) self.b_output_pm= tk.Button(self.results_frame,text="Export P-M Curves", command=self.print_pm_graph_common, font=helv, state = tk.DISABLED) self.b_output_pm.pack(side=tk.RIGHT) self.results_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=2, pady=2) #Tab 2 -P vs Pressure Curve self.page2 = ttk.Frame(self.nb) self.nb.add(self.page2, text='P-Lateral Pressure Diagram', state = tk.DISABLED) self.pg2_frame = tk.Frame(self.page2, bd=2, relief='sunken', padx=1,pady=1) self.pg2_frame.pack(fill=tk.BOTH,expand=1, padx=2, pady=2) self.chart_frame = tk.Frame(self.pg2_frame, padx=2, pady=2) self.Fig = matplotlib.figure.Figure(figsize=(12,6),dpi=96) self.ax1 = self.Fig.add_subplot(111) self.ax1.minorticks_on() self.ax1.grid(b=True, which='major', color='k', linestyle='-', alpha=0.3) self.ax1.grid(b=True, which='minor', color='g', linestyle='-', alpha=0.1) self.ax2=self.ax1.twinx() #Prebuild chart lines so data can be refreshed to cut down on render time #['0.9','1.0','1.15','1.25','1.6','2.0'] self.line_cd009, = self.ax1.plot([0,10],[10,0], label='Cd = 0.9') self.line_cd100, = self.ax1.plot([0,15],[15,0], label='Cd = 1.0') self.line_cd115, = self.ax1.plot([0,25],[25,0], label='Cd = 1.15') self.line_cd125, = self.ax1.plot([0,35],[35,0], label='Cd = 1.25') self.line_cd160, = self.ax1.plot([0,50],[50,0], label='Cd = 1.6') self.line_cd200, = self.ax1.plot([0,75],[75,0], label='Cd = 2.0') self.line_pl_cb, = self.ax1.plot([0,10],[3,3], label='PL Crushing') self.line_pl_wo_cb, = self.ax1.plot([0,10],[1.5,1.5], label='PL Crushing w/o Cb') self.line_delta_cd009, = self.ax2.plot([0,10],[0,13], label='D - Cd = 0.9') self.line_delta_cd100, = self.ax2.plot([0,15],[15,0], label='D - Cd = 1.0') self.line_delta_cd115, = self.ax2.plot([0,25],[25,0], label='D - Cd = 1.15') self.line_delta_cd125, = self.ax2.plot([0,35],[35,0], label='D - Cd = 1.25') self.line_delta_cd160, = self.ax2.plot([0,50],[50,0], label='D - Cd = 1.6') self.line_delta_cd200, = self.ax2.plot([0,75],[75,0], label='D - Cd = 2.0') self.line_delta_180, = self.ax2.plot([6,6],[0,13], label='H/180', linestyle=':') self.line_delta_240, = self.ax2.plot([4,4],[0,13], label='H/240', linestyle=':') self.line_delta_360, = self.ax2.plot([1,1],[0,13], label='H/360', linestyle=':') self.line_delta_600, = self.ax2.plot([1,1],[0,13], label='H/600', linestyle=':') self.legend_ax1 = self.ax1.legend(loc=1, fontsize='x-small') self.legend_ax2 = self.ax2.legend(loc=4, fontsize='x-small') self.ax1.set_ylabel('Axial (lbs)') self.ax1.set_xlabel('Lateral Pressure (psf)') self.ax2.set_ylabel('Mid Height Deflection (in)') self.canvas = matplotlib.backends.backend_tkagg.FigureCanvasTkAgg(self.Fig, master=self.chart_frame) self.canvas.show() self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1) self.toolbar = NavigationToolbar2TkAgg(self.canvas, self.chart_frame) self.toolbar.update() self.canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1) self.chart_frame.pack(side=tk.TOP,expand=1, fill=tk.BOTH) #Tab 3 -P vs M Curve self.page3 = ttk.Frame(self.nb) self.nb.add(self.page3, text='P-M Diagram', state = tk.DISABLED) self.pg3_frame = tk.Frame(self.page3, bd=2, relief='sunken', padx=1,pady=1) self.pg3_frame.pack(fill=tk.BOTH,expand=1, padx=2, pady=2) self.chart_frameB = tk.Frame(self.pg3_frame, padx=2, pady=2) self.FigB = matplotlib.figure.Figure(figsize=(12,6),dpi=96) self.ax1B = self.FigB.add_subplot(111) self.ax1B.minorticks_on() self.ax1B.grid(b=True, which='major', color='k', linestyle='-', alpha=0.3) self.ax1B.grid(b=True, which='minor', color='g', linestyle='-', alpha=0.1) self.ax2B=self.ax1B.twinx() #Prebuild chart lines so data can be refreshed to cut down on render time #['0.9','1.0','1.15','1.25','1.6','2.0'] self.line_cd009B, = self.ax1B.plot([0,10],[10,0], label='Cd = 0.9') self.line_cd100B, = self.ax1B.plot([0,15],[15,0], label='Cd = 1.0') self.line_cd115B, = self.ax1B.plot([0,25],[25,0], label='Cd = 1.15') self.line_cd125B, = self.ax1B.plot([0,35],[35,0], label='Cd = 1.25') self.line_cd160B, = self.ax1B.plot([0,50],[50,0], label='Cd = 1.6') self.line_cd200B, = self.ax1B.plot([0,75],[75,0], label='Cd = 2.0') self.line_pl_cbB, = self.ax1B.plot([0,10],[3,3], label='PL Crushing') self.line_pl_wo_cbB, = self.ax1B.plot([0,10],[1.5,1.5], label='PL Crushing w/o Cb') self.line_delta_cd009B, = self.ax2B.plot([0,10],[0,13], label='D - Cd = 0.9') self.line_delta_cd100B, = self.ax2B.plot([0,15],[15,0], label='D - Cd = 1.0') self.line_delta_cd115B, = self.ax2B.plot([0,25],[25,0], label='D - Cd = 1.15') self.line_delta_cd125B, = self.ax2B.plot([0,35],[35,0], label='D - Cd = 1.25') self.line_delta_cd160B, = self.ax2B.plot([0,50],[50,0], label='D - Cd = 1.6') self.line_delta_cd200B, = self.ax2B.plot([0,75],[75,0], label='D - Cd = 2.0') self.line_delta_180B, = self.ax2B.plot([6,6],[0,13], label='H/180', linestyle=':') self.line_delta_240B, = self.ax2B.plot([4,4],[0,13], label='H/240', linestyle=':') self.line_delta_360B, = self.ax2B.plot([1,1],[0,13], label='H/360', linestyle=':') self.line_delta_600B, = self.ax2B.plot([1,1],[0,13], label='H/600', linestyle=':') self.legend_ax1B = self.ax1B.legend(loc=1, fontsize='x-small') self.legend_ax2B = self.ax2B.legend(loc=4, fontsize='x-small') self.ax1B.set_ylabel('Axial (lbs)') self.ax1B.set_xlabel('Moment (in-lbs)') self.ax2B.set_ylabel('Mid Height Deflection (in)') self.canvasB = matplotlib.backends.backend_tkagg.FigureCanvasTkAgg(self.FigB, master=self.chart_frameB) self.canvasB.show() self.canvasB.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1) self.toolbarB = NavigationToolbar2TkAgg(self.canvasB, self.chart_frameB) self.toolbarB.update() self.canvasB._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1) self.chart_frameB.pack(side=tk.TOP, fill=tk.BOTH, expand=1) #Tab 4 -P vs M Curve self.page4 = ttk.Frame(self.nb) self.nb.add(self.page4, text='P-M Diagram - Stud', state = tk.DISABLED) self.pg4_frame = tk.Frame(self.page4, bd=2, relief='sunken', padx=1,pady=1) self.pg4_frame.pack(fill=tk.BOTH,expand=1, padx=2, pady=2) self.chart_frameD = tk.Frame(self.pg4_frame, padx=2, pady=2) self.FigD = matplotlib.figure.Figure(figsize=(12,6),dpi=96) self.ax1D = self.FigD.add_subplot(111) self.ax1D.minorticks_on() self.ax1D.grid(b=True, which='major', color='k', linestyle='-', alpha=0.3) self.ax1D.grid(b=True, which='minor', color='g', linestyle='-', alpha=0.1) self.ax2D=self.ax1D.twinx() #Prebuild chart lines so data can be refreshed to cut down on render time #['0.9','1.0','1.15','1.25','1.6','2.0'] self.line_cd009D, = self.ax1D.plot([0,10],[10,0], label='Cd = 0.9') self.line_cd100D, = self.ax1D.plot([0,15],[15,0], label='Cd = 1.0') self.line_cd115D, = self.ax1D.plot([0,25],[25,0], label='Cd = 1.15') self.line_cd125D, = self.ax1D.plot([0,35],[35,0], label='Cd = 1.25') self.line_cd160D, = self.ax1D.plot([0,50],[50,0], label='Cd = 1.6') self.line_cd200D, = self.ax1D.plot([0,75],[75,0], label='Cd = 2.0') self.line_pl_cbD, = self.ax1D.plot([0,10],[3,3], label='PL Crushing') self.line_pl_wo_cbD, = self.ax1D.plot([0,10],[1.5,1.5], label='PL Crushing w/o Cb') self.line_delta_cd009D, = self.ax2D.plot([0,10],[0,13], label='D - Cd = 0.9') self.line_delta_cd100D, = self.ax2D.plot([0,15],[15,0], label='D - Cd = 1.0') self.line_delta_cd115D, = self.ax2D.plot([0,25],[25,0], label='D - Cd = 1.15') self.line_delta_cd125D, = self.ax2D.plot([0,35],[35,0], label='D - Cd = 1.25') self.line_delta_cd160D, = self.ax2D.plot([0,50],[50,0], label='D - Cd = 1.6') self.line_delta_cd200D, = self.ax2D.plot([0,75],[75,0], label='D - Cd = 2.0') self.line_delta_180D, = self.ax2D.plot([6,6],[0,13], label='H/180', linestyle=':') self.line_delta_240D, = self.ax2D.plot([4,4],[0,13], label='H/240', linestyle=':') self.line_delta_360D, = self.ax2D.plot([1,1],[0,13], label='H/360', linestyle=':') self.line_delta_600D, = self.ax2D.plot([1,1],[0,13], label='H/600', linestyle=':') self.user_pmD, = self.ax1D.plot([1,1],[2,2], linestyle='None', marker= 'o') self.user_mdD, = self.ax2D.plot([1,1],[2,2], linestyle='None', marker= 'x') self.legend_ax1D = self.ax1D.legend(loc=1, fontsize='x-small') self.legend_ax2D = self.ax2D.legend(loc=4, fontsize='x-small') self.ax1D.set_ylabel('Axial (lbs)') self.ax1D.set_xlabel('Moment (in-lbs)') self.ax2D.set_ylabel('Mid Height Deflection (in)') self.canvasD = matplotlib.backends.backend_tkagg.FigureCanvasTkAgg(self.FigD, master=self.chart_frameD) self.canvasD.show() self.canvasD.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1) self.toolbarD = NavigationToolbar2TkAgg(self.canvasD, self.chart_frameD) self.toolbarD.update() self.canvasD._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1) self.chart_frameD.pack(side=tk.TOP, fill=tk.BOTH, expand=1) #Tab 5 - User Loads self.page5 = ttk.Frame(self.nb) self.nb.add(self.page5, text='User Loads', state = tk.DISABLED) self.pg5_frame = tk.Frame(self.page5, bd=2, relief='sunken', padx=1,pady=1) self.pg5_frame.pack(fill=tk.BOTH,expand=1, padx=2, pady=2) #user Loads input frame self.user_ins_top_frame = tk.Frame(self.pg5_frame) self.input_frame_loads = tk.LabelFrame(self.user_ins_top_frame, text="Loads Inputs (IBC 2012):", bd=2, relief='sunken', padx=2, pady=2) #Vertical Loads - [DL,LL,Lr,S,R] tk.Label(self.input_frame_loads, text='Vertical Loads: ').grid(column=1, row=1) self.user_vert_load_labels = ['D: ','L: ','Lr: ','S: ','R: '] self.user_load_trib_plf_label = [] tk.Label(self.input_frame_loads, text='Self Weight: ').grid(column=1, row=2) self.user_sw = tk.StringVar() self.user_sw.set(0.0) self.user_sw_psf_entry = tk.Entry(self.input_frame_loads, textvariable=self.user_sw, width=15).grid(column=2, row=2) tk.Label(self.input_frame_loads, text='psf x ').grid(column=3, row=2) self.user_sw_height_ft = tk.StringVar() self.user_sw_height_ft.set(0.0) self.user_sw_height_ft_entry = tk.Entry(self.input_frame_loads, textvariable=self.user_sw_height_ft, width=15).grid(column=4, row=2) self.user_sw_label = tk.Label(self.input_frame_loads, text='ft = x plf') self.user_sw_label.grid(column=5, row=2) i=2 for label in self.user_vert_load_labels: tk.Label(self.input_frame_loads, text=label).grid(column=1, row=i+1) tk.Label(self.input_frame_loads, text='psf x ').grid(column=3, row=i+1) self.user_load_trib_plf_label.append(tk.Label(self.input_frame_loads, text='ft = x plf')) self.user_load_trib_plf_label[i-2].grid(column=5, row=i+1) i+=1 self.user_vert_loads_psf = [tk.StringVar(),tk.StringVar(),tk.StringVar(),tk.StringVar(),tk.StringVar()] self.user_vert_loads_trib = [tk.StringVar(),tk.StringVar(),tk.StringVar(),tk.StringVar(),tk.StringVar()] i=2 for load in self.user_vert_loads_psf: load.set(0.0) self.user_vert_loads_trib[i-2].set(0.0) tk.Entry(self.input_frame_loads, textvariable=load, width=15).grid(column=2, row=i+1) tk.Entry(self.input_frame_loads, textvariable=self.user_vert_loads_trib[i-2], width=15).grid(column=4, row=i+1) i+=1 #Lateral Pressures #Lateral Loads - [L,W,ultimate] tk.Label(self.input_frame_loads, text='Lateral Loads: ').grid(column=7, row=1, padx=10) self.user_lat_load_labels = ['L: ','W_ultimate: '] i=1 for label in self.user_lat_load_labels: tk.Label(self.input_frame_loads, text=label).grid(column=7, row=i+1, padx=10) tk.Label(self.input_frame_loads, text='psf').grid(column=9, row=i+1) i+=1 self.user_lat_loads_psf = [tk.StringVar(),tk.StringVar()] i=1 for load in self.user_lat_loads_psf: load.set(0.0) tk.Entry(self.input_frame_loads, textvariable=load, width=15).grid(column=8, row=i+1) i+=1 self.input_frame_loads.pack(side=tk.LEFT, padx=2, pady=2) #user Loads input frame self.input_frame_user_wall = tk.LabelFrame(self.user_ins_top_frame, text="Wall Information:", bd=2, relief='sunken', padx=2, pady=2) tk.Label(self.input_frame_user_wall, text='Wall Height: ').grid(column=1, row=1) self.user_calc_wall_ht_ft = tk.Label(self.input_frame_user_wall, text='--') self.user_calc_wall_ht_ft.grid(column=2, row=1) tk.Label(self.input_frame_user_wall, text=' ft').grid(column=3, row=1) self.user_calc_spacing = tk.StringVar() self.user_calc_spacing.set(12.0) tk.Label(self.input_frame_user_wall, text='Spacing: ').grid(column=1, row=2) tk.Entry(self.input_frame_user_wall, textvariable=self.user_calc_spacing, width=15).grid(column=2, row=2) tk.Label(self.input_frame_user_wall, text=' in o.c.').grid(column=3, row=2) self.b_user_run = tk.Button(self.input_frame_user_wall,text="Check User loads", command=self.run_user_loads, font=helv) self.b_user_run.grid(column=4, row = 1, padx=10) self.b_user_solve = tk.Button(self.input_frame_user_wall,text="Optimize Spacing", command=self.solve_user_loads, font=helv) self.b_user_solve.grid(column=4, row = 2, padx=10) self.b_user_export = tk.Button(self.input_frame_user_wall,text="Export User Load Results", command=self.export_user_load_results, font=helv) self.b_user_export.grid(column=4, row = 3, padx=10) self.input_frame_user_wall.pack(side=tk.LEFT, padx=2, pady=2) self.user_ins_top_frame.pack(side=tk.TOP) self.user_res_bottom_frame = tk.LabelFrame(self.pg5_frame, text="Results (IBC 2012 - ASD):", bd=2, relief='sunken', padx=2, pady=2) res_headings = ['Combo:','Cd','P (lbs)', 'fc (psi)','Ke Le_d/d','FcE (psi)','c','Cp',"Fc' (psi)","fc/Fc'",'M_lat (in-lbs)','fb_lat (psi)',"Fb' (psi)","fb/Fb'",'V (lbs)','fv (psi)',"Fv' (psi)","fv/Fv'",'Ratio','D (H/--)','Status'] self.load_combos = [['D',0.9,1,0,0,0,0,0], ['D+L',1,1,1,0,0,0,0], ['D+Lr',1,1,0,1,0,0,0], ['D+S',1.15,1,0,0,1,0,0], ['D+R',1.15,1,0,0,0,1,0], ['D+.75L+.75Lr',1,1,0.75,0.75,0,0,0], ['D+.75L+.75S',1.15,1,0.75,0,0.75,0,0], ['D+.75L+.75R',1.15,1,0.75,0,0,0.75,0], ['D+.6W',1.6,1,0,0,0,0,0.6], ['D+.75(.6W)+.75L+.75Lr',1.6,1,0.75,0.75,0,0,0.45], ['D+.75(.6W)+.75L+.75S',1.6,1,0.75,0,0.75,0,0.45], ['D+.75(.6W)+.75L+.75R',1.6,1,0.75,0,0,0.75,0.45], ['.6D + .6W',1.6,0.6,0,0,0,0,0.6]] i=1 for heading in res_headings: tk.Label(self.user_res_bottom_frame, text = heading).grid(column=i, row=1, padx=4) i+=1 i=0 self.user_p_res_labels=[] self.user_fc_res_labels=[] self.user_kel_res_labels=[] self.user_FcE_res_labels=[] self.user_c_labels=[] self.user_cp_labels=[] self.user_fcprime_res_labels=[] self.user_fc_fc_res_labels=[] self.user_m_res_labels=[] self.user_fb_res_labels=[] self.user_fbprime_res_labels=[] self.user_fb_fb_res_labels=[] self.user_v_res_labels=[] self.user_fv_res_labels=[] self.user_fvprime_res_labels=[] self.user_fv_fv_res_labels=[] self.user_ratio_res_labels=[] self.user_deltaratio_res_labels=[] self.user_status_res_labels=[] for combo in self.load_combos: tk.Label(self.user_res_bottom_frame, text = combo[0]).grid(column=1, row=i+2, padx=4) tk.Label(self.user_res_bottom_frame, text = combo[1]).grid(column=2, row=i+2, padx=4) self.user_p_res_labels.append(tk.Label(self.user_res_bottom_frame, text = '--')) self.user_p_res_labels[i].grid(column=3, row=i+2, padx=4) self.user_fc_res_labels.append(tk.Label(self.user_res_bottom_frame, text = '--')) self.user_fc_res_labels[i].grid(column=4, row=i+2, padx=4) self.user_kel_res_labels.append(tk.Label(self.user_res_bottom_frame, text = '--')) self.user_kel_res_labels[i].grid(column=5, row=i+2, padx=4) self.user_FcE_res_labels.append(tk.Label(self.user_res_bottom_frame, text = '--')) self.user_FcE_res_labels[i].grid(column=6, row=i+2, padx=4) self.user_c_labels.append(tk.Label(self.user_res_bottom_frame, text = '--')) self.user_c_labels[i].grid(column=7, row=i+2, padx=4) self.user_cp_labels.append(tk.Label(self.user_res_bottom_frame, text = '--')) self.user_cp_labels[i].grid(column=8, row=i+2, padx=4) self.user_fcprime_res_labels.append(tk.Label(self.user_res_bottom_frame, text = '--')) self.user_fcprime_res_labels[i].grid(column=9, row=i+2, padx=4) self.user_fc_fc_res_labels.append(tk.Label(self.user_res_bottom_frame, text = '--')) self.user_fc_fc_res_labels[i].grid(column=10, row=i+2, padx=4) self.user_m_res_labels.append(tk.Label(self.user_res_bottom_frame, text = '--')) self.user_m_res_labels[i].grid(column=11, row=i+2, padx=4) self.user_fb_res_labels.append(tk.Label(self.user_res_bottom_frame, text = '--')) self.user_fb_res_labels[i].grid(column=12, row=i+2, padx=4) self.user_fbprime_res_labels.append(tk.Label(self.user_res_bottom_frame, text = '--')) self.user_fbprime_res_labels[i].grid(column=13, row=i+2, padx=4) self.user_fb_fb_res_labels.append(tk.Label(self.user_res_bottom_frame, text = '--')) self.user_fb_fb_res_labels[i].grid(column=14, row=i+2, padx=4) self.user_v_res_labels.append(tk.Label(self.user_res_bottom_frame, text = '--')) self.user_v_res_labels[i].grid(column=15, row=i+2, padx=4) self.user_fv_res_labels.append(tk.Label(self.user_res_bottom_frame, text = '--')) self.user_fv_res_labels[i].grid(column=16, row=i+2, padx=4) self.user_fvprime_res_labels.append(tk.Label(self.user_res_bottom_frame, text = '--')) self.user_fvprime_res_labels[i].grid(column=17, row=i+2, padx=4) self.user_fv_fv_res_labels.append(tk.Label(self.user_res_bottom_frame, text = '--')) self.user_fv_fv_res_labels[i].grid(column=18, row=i+2, padx=4) self.user_ratio_res_labels.append(tk.Label(self.user_res_bottom_frame, text = '--')) self.user_ratio_res_labels[i].grid(column=19, row=i+2, padx=4) self.user_deltaratio_res_labels.append(tk.Label(self.user_res_bottom_frame, text = '--')) self.user_deltaratio_res_labels[i].grid(column=20, row=i+2, padx=4) self.user_status_res_labels.append(tk.Label(self.user_res_bottom_frame, text = '--')) self.user_status_res_labels[i].grid(column=21, row=i+2, padx=4) i+=1 self.user_res_bottom_frame.pack(side=tk.TOP) self.b_quit = tk.Button(self.base_frame,text="Quit", command=self.quit_app, font=helv) self.b_quit.pack(side=tk.RIGHT) self.b_save = tk.Button(self.base_frame,text="Save Inputs", command=self.save_inputs, font=helv, state = tk.DISABLED) self.b_save.pack(side=tk.RIGHT) self.license_display() def license_display(self, *event): license_string = ("Copyright (c) 2019, Donald N. Bockoven III\n" "All rights reserved.\n\n" "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"" " AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE" " IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE" " DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE" " FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL" " DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR" " SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER" " CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY," " OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE" " OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n" "https://github.com/buddyd16/Structural-Engineering/blob/master/LICENSE" ) tkMessageBox.showerror("License Information",license_string) self.master.focus_force() def quit_app(self): self.master.destroy() self.master.quit() def enable_tab2(self): self.nb.tab(1,state=tk.NORMAL) self.nb.tab(2,state=tk.NORMAL) self.nb.tab(3,state=tk.NORMAL) self.nb.tab(4,state=tk.NORMAL) def com_lat_brace_func(self, *event): if self.com_lat_brace_yn.get() == 1: self.no_sheathing_yn.set(0) else: pass def no_sheating_func(self, *event): if self.no_sheathing_yn.get() == 1: self.com_lat_brace_yn.set(0) else: pass def actual_stud_size(self, *event): w = self.b_nom.get() if w == '2' or w== '3' or w=='4': b = float(self.b_nom.get()) self.b_actual = b - 0.5 elif w == '(2)2': self.b_actual = 2.0*1.5 else: self.b_actual = 3.0*1.5 d = float(self.d_nom.get()) if d > 6.0: self.d_actual = d - 0.75 else: self.d_actual = d - 0.5 self.b_actual_label.configure(text=self.b_actual) self.d_actual_label.configure(text=self.d_actual) def run(self, *event): self.results_text_box.delete(1.0,tk.END) self.actual_stud_size() self.enable_tab2() # (self,b_in=1.5,d_in=3.5,height_ft=10, spacing_in=12, grade="No.2", fb_psi=875, fv_psi= 150, fc_psi=1150, E_psi=1400000, Emin_psi=510000, fc_perp_pl_psi=565, moisture_percent = 19, temp = 90, incised = 0, num_plates = 0, c_frt=[1,1,1,1,1,1]): b = self.b_actual d = self.d_actual height = float(self.wall_height.get()) spacing = float(self.stud_spacing.get()) grade = self.grade.get() self.title = '{0}x{1} ({2:.2f}x{3:.2f})- Height:{4} ft - Species: {7} - Grade: {5} - Spacing: {6} in'.format(self.b_nom.get(),self.d_nom.get(),b,d,height,grade,spacing, self.species.get()) self.title_pm_stud = '{0}x{1} ({2:.2f}x{3:.2f})- Height:{4} ft - Species: {6} - Grade: {5}'.format(self.b_nom.get(),self.d_nom.get(),b,d,height,grade, self.species.get()) self.results_text_box.insert(tk.END, self.title) fb = float(self.fb_psi.get()) fv = float(self.fv_psi.get()) fc = float(self.fc_psi.get()) E = float(self.E_psi.get()) Emin = float(self.Emin_psi.get()) fc_perp = float(self.fc_perp_psi.get()) moisture = float(self.moisture.get()) temp = float(self.temp.get()) incise = self.incised_yn.get() sub_plates = self.sub_plates.get() if sub_plates == 1: num_pl = float(self.num_plates.get()) else: num_pl = 0 frt = self.frt_yn.get() if frt ==1: cfrt = [float(self.frt_fb.get()),float(self.frt_fv.get()),float(self.frt_fc.get()),float(self.frt_fc_perp.get()),float(self.frt_E.get()),float(self.frt_Emin.get())] else: cfrt =[1,1,1,1,1,1] min_ecc = self.min_ecc_yn.get() if min_ecc == 1: self.e_in = d/6.0 e_string = ' at min d/6 = {0:.3f} in eccentricity '.format(self.e_in) else: self.e_in = 0 e_string ='' self.wall = wood.wood_stud_wall(b,d,height,spacing,grade,fb,fv,fc,E,Emin,fc_perp,moisture,temp,incise,num_pl, cfrt, self.com_lat_brace_yn.get(), float(self.blocking_ft.get()), self.no_sheathing_yn.get(),self.is_syp.get()) pressure_psf = float(self.pressure.get()) self.pressure_moment_inlbs = (((pressure_psf*(self.wall.spacing_in/12.0))*(self.wall.height_in/12.0)**2)/8.0) * 12.0 self.pressure_shear_lbs = (((pressure_psf*(self.wall.spacing_in/12.0))*(self.wall.height_in/12.0))/2.0) ##Solve for maximum axial capacity cd = float(self.cd.get()) p_lbs = self.wall.axial_capacity_w_moment(cd,self.pressure_moment_inlbs,self.e_in) ##Create Text String and write Axial result to text box axial_string = '\n\n-- Pmax_allow = {0:.2f} lbs ({2:.2f} plf) {1} --'.format(p_lbs,e_string, p_lbs/(self.wall.spacing_in/12.0)) axial_string = axial_string + '\n-- PL Crushing (Cb): {0:.2f} lbs ({2:.2f} plf) --\n-- PL Crushing (w/o Cb): {1:.2f} lbs ({3:.2f} plf) --'.format(self.wall.crushing_limit_lbs,self.wall.crushing_limit_lbs_no_cb,self.wall.crushing_limit_lbs/(self.wall.spacing_in/12.0),self.wall.crushing_limit_lbs_no_cb/(self.wall.spacing_in/12.0)) ##Write out any warnings that occured during the wall creation or axial run if self.wall.warning == '': pass else: self.results_text_box.insert(tk.END, "\n*** ERROR/WARNING ***\n") self.results_text_box.insert(tk.END, self.wall.warning) common_capacities = self.wall.cap_at_common_spacing(cd,pressure_psf,self.e_in,self.consider_crushing.get()) axial_string = axial_string + '\n\n--Common Spacing Capacities--\n' + common_capacities self.results_text_box.insert(tk.END, axial_string) ##Pull Section properties from wall class and write out to results text box section_props_string = '\n\n--Section Properties--\nA = {0:.3f} in^2 -- S = {1:.3f} in^3 -- I = {2:.3f} in^4'.format(self.wall.area_in2,self.wall.s_in3,self.wall.I_in4) self.results_text_box.insert(tk.END, section_props_string) #Applied Loads - Axial self.loads_string = '\n\n--Applied Loads--\nPressure: {0:.2f} psf x Spacing x 1 ft / 12 in = {1:.2f} plf'.format(pressure_psf,pressure_psf * (spacing/12.0)) w_plf = pressure_psf * (spacing/12.0) deflection_lat = (5 * (w_plf) * (self.wall.height_in/12)**4)/(384*self.wall.E_prime_psi*self.wall.I_in4)*1728 if min_ecc == 1: self.ecc_moment_inlbs = p_lbs * self.e_in self.ecc_shear_lbs = self.ecc_moment_inlbs / self.wall.height_in deflection_axial = (((self.ecc_moment_inlbs)*self.wall.height_in**2)/(16.0*self.wall.E_prime_psi*self.wall.I_in4)) deflection = deflection_lat + deflection_axial applied_shear_string = '\nLateral Shear: {0:.2f} lbs + Gravity Shear: {1:.2f} lbs = Total Shear: {2:.2f} lbs'.format(self.pressure_shear_lbs, self.ecc_shear_lbs,self.pressure_shear_lbs+self.ecc_shear_lbs) applied_moment_string = '\nLateral Moment: {0:.2f} in-lbs + Gravity Moment: {1:.2f} in-lbs = Total Moment: {2:.2f} in-lbs'.format(self.pressure_moment_inlbs, self.ecc_moment_inlbs,self.pressure_moment_inlbs+self.ecc_moment_inlbs) deflection_string = '\nLateral Delta: {0:.3f} in + Gravity Delta: {1:.3f} in = Delta: {2:.3f} in - H / {3:.1f}'.format(deflection_lat, deflection_axial, deflection, self.wall.height_in/deflection) else: self.ecc_moment_inlbs = 0.0 self.ecc_shear_lbs = 0.0 applied_shear_string = '\nLateral Shear: {0:.2f} lbs'.format(self.pressure_shear_lbs) applied_moment_string = '\nLateral Moment: {0:.2f} in-lbs'.format(self.pressure_moment_inlbs) deflection_string = '\nLateral Delta: {0:.3f} - H / {1:.1f}'.format(deflection_lat, self.wall.height_in/deflection_lat) self.loads_string = self.loads_string + applied_shear_string + applied_moment_string + deflection_string self.results_text_box.insert(tk.END, self.loads_string) ##Stresses self.stress_string = '\n\n--Stresses--' axial_stress = p_lbs/self.wall.area_in2 self.stress_string = self.stress_string+'\nfc = P/A = {0:.3f} psi'.format(axial_stress) shear = self.pressure_shear_lbs + self.ecc_shear_lbs shear_stress = (3.0*shear)/(2.0*b*d) self.stress_string = self.stress_string+'\nfv = VQ/Ib = 3V/2bd = {0:.3f} psi'.format(shear_stress) if self.e_in == 0: moment = self.pressure_moment_inlbs + self.ecc_moment_inlbs bending_stress_lat = self.pressure_moment_inlbs/self.wall.s_in3 bending_stress = moment/self.wall.s_in3 self.stress_string = self.stress_string+'\nfb = Mc/I = M/s = 6M/bd^2 = {0:.3f} psi'.format(bending_stress_lat) #Combine ratio per NDS 2005 equation (3.9-3) #[fc/Fc]'^2 + fb / Fb' [ 1- (fc / FcE)] <= 1.0 ratio = (axial_stress/self.wall.fc_prime_psi)**2 + (bending_stress / (self.wall.fb_prime_calc(cd)*(1-(axial_stress/self.wall.fcE_psi)))) self.stress_string = self.stress_string+"\nCombined Axial+Bending:\n[fc/Fc]'^2 + fb / Fb' [ 1- (fc / FcE)] = {0:.3f} <= 1.0".format(ratio) else: moment = self.pressure_moment_inlbs + self.ecc_moment_inlbs bending_stress_ecc = self.ecc_moment_inlbs/self.wall.s_in3 bending_stress_lat = self.pressure_moment_inlbs/self.wall.s_in3 bending_stress = moment/self.wall.s_in3 self.stress_string = self.stress_string+'\nfb_lat = Mc/I = M/s = 6M/bd^2 = {0:.3f} psi + fb_gravity = {1:.3f} = {2:.3f}'.format(bending_stress_lat,bending_stress_ecc,bending_stress) #Combined Ratio per NDS 2005 equation 15.4-1 #[fc/Fc]'^2 + (fb + fc(6e/d)[1 + 0.234 (fc / FcE)])/ Fb' [ 1- (fc / FcE)] <= 1.0 b1 = self.pressure_moment_inlbs/self.wall.s_in3 ratio = (axial_stress/self.wall.fc_prime_psi)**2 + ((b1+(axial_stress*(6*self.e_in/d)*(1+(0.234*(axial_stress/self.wall.fcE_psi)))))/ (self.wall.fb_prime_calc(cd)*(1-(axial_stress/self.wall.fcE_psi)))) self.stress_string = self.stress_string+"\nCombined Axial+Bending w/ Eccentricity:\n[fc/Fc]'^2 + (fb_lat + fc(6e/d)[1 + 0.234 (fc / FcE)])/ Fb' [ 1- (fc / FcE)] = {0:.3f} <= 1.0".format(ratio) self.results_text_box.insert(tk.END, self.stress_string) ##Calculation of Cp self.cp_string = '\n\n--Calculation of Cp--' self.cp_string=self.cp_string + '\nFc* = reference compression design value parallel to grain multiplied by all applicable adjusment factors except Cp\nFc* = Fc*Cd*Cm*Ct*Cf*Ci = {1:.2f}*{2:.2f}*{3:.2f}*{4:.2f}*{5:.2f}*{6:.2f} = {0:.2f} psi\nc = 0.8 - NDS 2005 3.7.1'.format(self.wall.fc_star_psi,self.wall.fc_psi,cd,self.wall.cm_fc,self.wall.ct_fc,self.wall.cf_fc,self.wall.ci_fc) self.cp_string=self.cp_string + self.wall.assumptions_ke + self.wall.assumptions_leb self.cp_string = self.cp_string + 'Ke * Le_d / d = {0:.3f} in < 50'.format(self.wall.height_in/d) self.cp_string = self.cp_string + '\nKe * Le_b / b = {0:.3f} in < 50'.format(self.wall.le_b/b) self.cp_string = self.cp_string + "\nFcE = 0.822 * Emin' / (max[Le_d/d,Le_b/b])^2 - NDS 2005 Section 3.7.1\nFcE = {0:.3f} psi".format(self.wall.fcE_psi) self.cp_string = self.cp_string + "\nCp = ([1 + (FcE / Fc*)] / 2c ) - sqrt[ [1 + (FcE / Fc*) / 2c]^2 - (FcE / Fc*) / c] = {0:.3f} - NDS 2005 Section 3.7.1".format(self.wall.cp) self.results_text_box.insert(tk.END, self.cp_string) ##Calculation of CL if self.com_lat_brace_yn.get() == 1: pass else: self.results_text_box.insert(tk.END, self.wall.cl_calc_text) ##write out assumption from wall creation - see wood_classes.py assumptions_string = self.wall.assumptions + self.wall.assumptions_c+self.wall.assumptions_cp self.results_text_box.insert(tk.END, assumptions_string) ##Fill in reduction factor table #Fb self.res_labels[17].configure(text='{0:.2f}'.format(fb)) self.res_nds_table_output[17] = '{0:.2f}'.format(fb) self.res_labels[18].configure(text='{0:.2f}'.format(cd)) self.res_nds_table_output[18] = '{0:.2f}'.format(cd) self.res_labels[19].configure(text='{0:.2f}'.format(self.wall.cm_fb)) self.res_nds_table_output[19] = '{0:.2f}'.format(self.wall.cm_fb) self.res_labels[20].configure(text='{0:.2f}'.format(self.wall.ct_fb)) self.res_nds_table_output[20] = '{0:.2f}'.format(self.wall.ct_fb) self.res_labels[21].configure(text='{0:.2f}'.format(self.wall.cl)) self.res_nds_table_output[21] = '{0:.2f}'.format(self.wall.cl) self.res_labels[22].configure(text='{0:.2f}'.format(self.wall.cf_fb)) self.res_nds_table_output[22] = '{0:.2f}'.format(self.wall.cf_fb) self.res_labels[23].configure(text='{0:.2f}'.format(self.wall.cfu)) self.res_nds_table_output[23] = '{0:.2f}'.format(self.wall.cfu) self.res_labels[24].configure(text='{0:.2f}'.format(self.wall.ci_fb)) self.res_nds_table_output[24] = '{0:.2f}'.format(self.wall.ci_fb) self.res_labels[25].configure(text='{0:.2f}'.format(self.wall.cr)) self.res_nds_table_output[25] = '{0:.2f}'.format(self.wall.cr) self.res_labels[29].configure(text='{0:.2f}'.format(cfrt[0])) self.res_nds_table_output[29] = '{0:.2f}'.format(cfrt[0]) self.res_labels[30].configure(text='{0:.2f}'.format(self.wall.fb_prime_calc(cd))) self.res_nds_table_output[30] = '{0:.2f}'.format(self.wall.fb_prime_calc(cd)) #Fv self.res_labels[33].configure(text='{0:.2f}'.format(fv)) self.res_nds_table_output[33] = '{0:.2f}'.format(fv) self.res_labels[34].configure(text='{0:.2f}'.format(cd)) self.res_nds_table_output[34] = '{0:.2f}'.format(cd) self.res_labels[35].configure(text='{0:.2f}'.format(self.wall.cm_fv)) self.res_nds_table_output[35] = '{0:.2f}'.format(self.wall.cm_fv) self.res_labels[36].configure(text='{0:.2f}'.format(self.wall.ct_fv)) self.res_nds_table_output[36] = '{0:.2f}'.format(self.wall.ct_fv) self.res_labels[40].configure(text='{0:.2f}'.format(self.wall.ci_fv)) self.res_nds_table_output[40] = '{0:.2f}'.format(self.wall.ci_fv) self.res_labels[45].configure(text='{0:.2f}'.format(cfrt[1])) self.res_nds_table_output[45] = '{0:.2f}'.format(cfrt[1]) self.res_labels[46].configure(text='{0:.2f}'.format(self.wall.fv_prime_psi_cd)) self.res_nds_table_output[46] = '{0:.2f}'.format(self.wall.fv_prime_psi_cd) #Fc self.res_labels[49].configure(text='{0:.2f}'.format(fc)) self.res_nds_table_output[49] = '{0:.2f}'.format(fc) self.res_labels[50].configure(text='{0:.2f}'.format(cd)) self.res_nds_table_output[50] = '{0:.2f}'.format(cd) self.res_labels[51].configure(text='{0:.2f}'.format(self.wall.cm_fc)) self.res_nds_table_output[51] = '{0:.2f}'.format(self.wall.cm_fc) self.res_labels[52].configure(text='{0:.2f}'.format(self.wall.ct_fc)) self.res_nds_table_output[52] = '{0:.2f}'.format(self.wall.ct_fc) self.res_labels[54].configure(text='{0:.2f}'.format(self.wall.cf_fc)) self.res_nds_table_output[54] = '{0:.2f}'.format(self.wall.cf_fc) self.res_labels[56].configure(text='{0:.2f}'.format(self.wall.ci_fc)) self.res_nds_table_output[56] = '{0:.2f}'.format(self.wall.ci_fc) self.res_labels[58].configure(text='{0:.3f}'.format(self.wall.cp)) self.res_nds_table_output[58] = '{0:.3f}'.format(self.wall.cp) self.res_labels[61].configure(text='{0:.2f}'.format(cfrt[2])) self.res_nds_table_output[61] = '{0:.2f}'.format(cfrt[2]) self.res_labels[62].configure(text='{0:.2f}'.format(self.wall.fc_prime_psi)) self.res_nds_table_output[62] = '{0:.2f}'.format(self.wall.fc_prime_psi) #fc_perp self.res_labels[65].configure(text='{0:.2f}'.format(fc_perp)) self.res_nds_table_output[65] = '{0:.2f}'.format(fc_perp) self.res_labels[67].configure(text='{0:.2f}'.format(self.wall.cm_fc_perp)) self.res_nds_table_output[67] = '{0:.2f}'.format(self.wall.cm_fc_perp) self.res_labels[68].configure(text='{0:.2f}'.format(self.wall.ct_fc_perp)) self.res_nds_table_output[68] = '{0:.2f}'.format(self.wall.ct_fc_perp) self.res_labels[72].configure(text='{0:.2f}'.format(self.wall.ci_fc_perp)) self.res_nds_table_output[72] = '{0:.2f}'.format(self.wall.ci_fc_perp) self.res_labels[76].configure(text='{0:.2f}'.format(self.wall.cb_fc_perp)) self.res_nds_table_output[76] = '{0:.2f}'.format(self.wall.cb_fc_perp) self.res_labels[77].configure(text='{0:.2f}'.format(cfrt[3])) self.res_nds_table_output[77] = '{0:.2f}'.format(cfrt[3]) self.res_labels[78].configure(text='{0:.2f}'.format(self.wall.fc_perp_pl_prime_psi)) self.res_nds_table_output[78] = '{0:.2f}'.format(self.wall.fc_perp_pl_prime_psi) #E self.res_labels[81].configure(text='{0:.2f}'.format(E)) self.res_nds_table_output[81] = '{0:.2f}'.format(E) self.res_labels[83].configure(text='{0:.2f}'.format(self.wall.cm_E)) self.res_nds_table_output[83] = '{0:.2f}'.format(self.wall.cm_E) self.res_labels[84].configure(text='{0:.2f}'.format(self.wall.ct_E)) self.res_nds_table_output[84] = '{0:.2f}'.format(self.wall.ct_E) self.res_labels[88].configure(text='{0:.2f}'.format(self.wall.ci_E)) self.res_nds_table_output[88] = '{0:.2f}'.format(self.wall.ci_E) self.res_labels[93].configure(text='{0:.2f}'.format(cfrt[4])) self.res_nds_table_output[93] = '{0:.2f}'.format(cfrt[4]) self.res_labels[94].configure(text='{0:.2f}'.format(self.wall.E_prime_psi)) self.res_nds_table_output[94] = '{0:.2f}'.format(self.wall.E_prime_psi) #Emin self.res_labels[97].configure(text='{0:.2f}'.format(Emin)) self.res_nds_table_output[97] = '{0:.2f}'.format(Emin) self.res_labels[99].configure(text='{0:.2f}'.format(self.wall.cm_E)) self.res_nds_table_output[99] = '{0:.2f}'.format(self.wall.cm_E) self.res_labels[100].configure(text='{0:.2f}'.format(self.wall.ct_E)) self.res_nds_table_output[100] = '{0:.2f}'.format(self.wall.ct_E) self.res_labels[104].configure(text='{0:.2f}'.format(self.wall.ci_E)) self.res_nds_table_output[104] = '{0:.2f}'.format(self.wall.ci_E) self.res_labels[107].configure(text='{0:.2f}'.format(self.wall.cT)) self.res_nds_table_output[107] = '{0:.2f}'.format(self.wall.cT) self.res_labels[109].configure(text='{0:.2f}'.format(cfrt[5])) self.res_nds_table_output[109] = '{0:.2f}'.format(cfrt[5]) self.res_labels[110].configure(text='{0:.2f}'.format(self.wall.Emin_prime_psi)) self.res_nds_table_output[110] = '{0:.2f}'.format(self.wall.Emin_prime_psi) self.b_build_chart.configure(state=tk.NORMAL) self.b_build_pm.configure(state=tk.NORMAL) self.b_output_res.configure(state=tk.NORMAL) self.b_output_pm.configure(state=tk.NORMAL) self.b_output_pp.configure(state=tk.NORMAL) self.b_save.configure(state=tk.NORMAL) #Fill consistant wall information in user laod calc tab #set wall height self.user_calc_wall_ht_ft.configure(text='{0:.3f}'.format(self.wall.height_in/12.0)) self.user_sw_height_ft.set(self.wall.height_in/12.0) tk.Label(self.user_res_bottom_frame, text = '* - indicates load greater than wall plate crushing w/o Cb - {0:.3f} lbs'.format(self.wall.crushing_limit_lbs_no_cb)).grid(column=1, row=15, columnspan=10) tk.Label(self.user_res_bottom_frame, text = '** - indicates load greater than wall plate crushing w/ Cb - {0:.3f} lbs'.format(self.wall.crushing_limit_lbs)).grid(column=1, row=16, columnspan=10) def generate_interaction_graph(self,*event): e_in = self.e_in #Refresh chart data for each Cd #Cd - NDS 2005 Table 2.3.2 #cd = [0.9,1.0,1.15,1.25,1.6,2.0] w,p,d = self.wall.wall_interaction_diagram_cd(0.9,e_in,0) self.line_cd009.set_data(w,p) self.line_delta_cd009.set_data(w,d) w,p,d = self.wall.wall_interaction_diagram_cd(1.0,e_in,0) self.line_cd100.set_data(w,p) self.line_delta_cd100.set_data(w,d) w,p,d = self.wall.wall_interaction_diagram_cd(1.15,e_in,0) self.line_cd115.set_data(w,p) self.line_delta_cd115.set_data(w,d) w,p,d = self.wall.wall_interaction_diagram_cd(1.25,e_in,0) self.line_cd125.set_data(w,p) self.line_delta_cd125.set_data(w,d) w,p,d = self.wall.wall_interaction_diagram_cd(1.6,e_in,0) self.line_cd160.set_data(w,p) self.line_delta_cd160.set_data(w,d) w,p,d = self.wall.wall_interaction_diagram_cd(2.0,e_in,0) self.line_cd200.set_data(w,p) self.line_delta_cd200.set_data(w,d) if (self.wall.crushing_limit_lbs/(self.wall.spacing_in/12.0)) > 1.2*max(p): self.line_pl_cb.set_data([0,0],[0,0]) self.line_pl_wo_cb.set_data([0,0],[0,0]) else: self.line_pl_cb.set_data([0,max(w)],[self.wall.crushing_limit_lbs/(self.wall.spacing_in/12.0),self.wall.crushing_limit_lbs/(self.wall.spacing_in/12.0)]) self.line_pl_wo_cb.set_data([0,max(w)],[self.wall.crushing_limit_lbs_no_cb/(self.wall.spacing_in/12.0),self.wall.crushing_limit_lbs_no_cb/(self.wall.spacing_in/12.0)]) self.line_delta_180.set_data([0,max(w)],[self.wall.height_in/180.0,self.wall.height_in/180.0]) self.line_delta_240.set_data([0,max(w)],[self.wall.height_in/240.0,self.wall.height_in/240.0]) self.line_delta_360.set_data([0,max(w)],[self.wall.height_in/360.0,self.wall.height_in/360.0]) self.line_delta_600.set_data([0,max(w)],[self.wall.height_in/600.0,self.wall.height_in/600.0]) self.ax1.set_xlim(0, max(w)+20) self.ax1.set_ylim(0, max(p)+200) self.ax2.set_ylim(0, max(d)+0.75) min_ecc = self.min_ecc_yn.get() if min_ecc == 1: e_string = ' at min d/6 = {0:.3f} in eccentricity '.format(self.e_in) else: e_string ='' self.ax1.set_ylabel('Axial (plf)'+e_string) self.ax1.set_title(self.title) self.canvas.draw() def generate_pm_graph(self,*event): e_in = self.e_in #Refresh chart data for each Cd #Cd - NDS 2005 Table 2.3.2 #cd = [0.9,1.0,1.15,1.25,1.6,2.0] w,p,d = self.wall.wall_pm_diagram_cd(0.9,e_in,0) self.line_cd009B.set_data(w,p) self.line_delta_cd009B.set_data(w,d) w,p,d = self.wall.wall_pm_diagram_cd(1.0,e_in,0) self.line_cd100B.set_data(w,p) self.line_delta_cd100B.set_data(w,d) w,p,d = self.wall.wall_pm_diagram_cd(1.15,e_in,0) self.line_cd115B.set_data(w,p) self.line_delta_cd115B.set_data(w,d) w,p,d = self.wall.wall_pm_diagram_cd(1.25,e_in,0) self.line_cd125B.set_data(w,p) self.line_delta_cd125B.set_data(w,d) w,p,d = self.wall.wall_pm_diagram_cd(1.6,e_in,0) self.line_cd160B.set_data(w,p) self.line_delta_cd160B.set_data(w,d) w,p,d = self.wall.wall_pm_diagram_cd(2.0,e_in,0) self.line_cd200B.set_data(w,p) self.line_delta_cd200B.set_data(w,d) if (self.wall.crushing_limit_lbs/(self.wall.spacing_in/12.0)) > 1.2*max(p): self.line_pl_cbB.set_data([0,0],[0,0]) self.line_pl_wo_cbB.set_data([0,0],[0,0]) else: self.line_pl_cbB.set_data([0,max(w)],[self.wall.crushing_limit_lbs/(self.wall.spacing_in/12.0),self.wall.crushing_limit_lbs/(self.wall.spacing_in/12.0)]) self.line_pl_wo_cbB.set_data([0,max(w)],[self.wall.crushing_limit_lbs_no_cb/(self.wall.spacing_in/12.0),self.wall.crushing_limit_lbs_no_cb/(self.wall.spacing_in/12.0)]) self.line_delta_180B.set_data([0,max(w)],[self.wall.height_in/180.0,self.wall.height_in/180.0]) self.line_delta_240B.set_data([0,max(w)],[self.wall.height_in/240.0,self.wall.height_in/240.0]) self.line_delta_360B.set_data([0,max(w)],[self.wall.height_in/360.0,self.wall.height_in/360.0]) self.line_delta_600B.set_data([0,max(w)],[self.wall.height_in/600.0,self.wall.height_in/600.0]) self.ax1B.set_xlim(0, max(w)+500) self.ax1B.set_ylim(0, max(p)+200) self.ax2B.set_ylim(0, max(d)+0.75) min_ecc = self.min_ecc_yn.get() if min_ecc == 1: e_string = ' at min d/6 = {0:.3f} in eccentricity '.format(self.e_in) else: e_string ='' self.ax1B.set_ylabel('Axial (plf)'+e_string) self.ax1B.set_title(self.title) self.canvasB.draw() w,p,d = self.wall.wall_pm_diagram_cd_stud(0.9,e_in) self.line_cd009D.set_data(w,p) self.line_delta_cd009D.set_data(w,d) w,p,d = self.wall.wall_pm_diagram_cd_stud(1.0,e_in) self.line_cd100D.set_data(w,p) self.line_delta_cd100D.set_data(w,d) w,p,d = self.wall.wall_pm_diagram_cd_stud(1.15,e_in) self.line_cd115D.set_data(w,p) self.line_delta_cd115D.set_data(w,d) w,p,d = self.wall.wall_pm_diagram_cd_stud(1.25,e_in) self.line_cd125D.set_data(w,p) self.line_delta_cd125D.set_data(w,d) w,p,d = self.wall.wall_pm_diagram_cd_stud(1.6,e_in) self.line_cd160D.set_data(w,p) self.line_delta_cd160D.set_data(w,d) w,p,d = self.wall.wall_pm_diagram_cd_stud(2.0,e_in) self.line_cd200D.set_data(w,p) self.line_delta_cd200D.set_data(w,d) if (self.wall.crushing_limit_lbs) > 1.2*max(p): self.line_pl_cbD.set_data([0,0],[0,0]) self.line_pl_wo_cbD.set_data([0,0],[0,0]) else: self.line_pl_cbD.set_data([0,max(w)],[self.wall.crushing_limit_lbs,self.wall.crushing_limit_lbs]) self.line_pl_wo_cbD.set_data([0,max(w)],[self.wall.crushing_limit_lbs_no_cb,self.wall.crushing_limit_lbs_no_cb]) self.line_delta_180D.set_data([0,max(w)],[self.wall.height_in/180.0,self.wall.height_in/180.0]) self.line_delta_240D.set_data([0,max(w)],[self.wall.height_in/240.0,self.wall.height_in/240.0]) self.line_delta_360D.set_data([0,max(w)],[self.wall.height_in/360.0,self.wall.height_in/360.0]) self.line_delta_600D.set_data([0,max(w)],[self.wall.height_in/600.0,self.wall.height_in/600.0]) self.ax1D.set_xlim(0, max(w)+500) self.ax1D.set_ylim(0, max(p)+200) self.ax2D.set_ylim(0, max(d)+0.75) min_ecc = self.min_ecc_yn.get() if min_ecc == 1: e_string = ' at min d/6 = {0:.3f} in eccentricity '.format(self.e_in) else: e_string ='' self.ax1D.set_ylabel('Axial (lbs)'+e_string) self.ax1D.set_title(self.title_pm_stud) self.canvasD.draw() def path_exists(self,path): res_folder_exist = os.path.isdir(path) if res_folder_exist is False: os.makedirs(path) else: pass return 'Directory created' def save_inputs(self,*event): self.run() ##Create a file containing user inputs to be read back in #all inputs are single values so write a single input per line string = '' #Gather inputs #geometry b = self.b_nom.get() string = string + '{0}\n'.format(b) d = self.d_nom.get() string = string + '{0}\n'.format(d) spacing = self.stud_spacing.get() string = string + '{0}\n'.format(spacing) h = self.wall_height.get() string = string + '{0}\n'.format(h) sub_pl = self.sub_plates.get() string = string + '{0}\n'.format(sub_pl) plates = self.num_plates.get() string = string + '{0}\n'.format(plates) #Reference Stud Values grade = self.grade.get() string = string + '{0}\n'.format(grade) #Fb fb = self.fb_psi.get() string = string + '{0}\n'.format(fb) #Fv fv = self.fv_psi.get() string = string + '{0}\n'.format(fv) #Fc fc = self.fc_psi.get() string = string + '{0}\n'.format(fc) #E E = self.E_psi.get() string = string + '{0}\n'.format(E) #Emin Emin = self.Emin_psi.get() string = string + '{0}\n'.format(Emin) #Fc_perp_pl fcperp = self.fc_perp_psi.get() string = string + '{0}\n'.format(fcperp) #FRT? frtyn = self.frt_yn.get() string = string + '{0}\n'.format(frtyn) frtfb = self.frt_fb.get() string = string + '{0}\n'.format(frtfb) frtfv = self.frt_fv.get() string = string + '{0}\n'.format(frtfv) frtfc = self.frt_fc.get() string = string + '{0}\n'.format(frtfc) frtfperp = self.frt_fc_perp.get() string = string + '{0}\n'.format(frtfperp) frtE = self.frt_E.get() string = string + '{0}\n'.format(frtE) frtEmin = self.frt_Emin.get() string = string + '{0}\n'.format(frtEmin) species = self.species .get() string = string + '{0}\n'.format(species) #Moisture % moist = self.moisture.get() string = string + '{0}\n'.format(moist) #Temp F temp= self.temp.get() string = string + '{0}\n'.format(temp) #Incised? inc = self.incised_yn.get() string = string + '{0}\n'.format(inc) p = self.pressure.get() string = string + '{0}\n'.format(p) cd = self.cd.get() string = string + '{0}\n'.format(cd) e = self.min_ecc_yn.get() string = string + '{0}\n'.format(e) label = '{0}x{1}_height-{2}_ft_pressure-{3}_psf_Cd-{4}'.format(b,d,h,p,cd) path = os.path.join(os.path.expanduser('~'),'Desktop','RESULTS','Wood_Walls', label) self.path_exists(path) name = label+'_inputs.wdwall' file = open(os.path.join(path,name),'w') file.write(string) file.close() def file_open(self): filename = tkFileDialog.askopenfilename() in_file = open(filename,'r') in_data = in_file.readlines() in_file.close() b = in_data[0].rstrip('\n') self.b_nom.set(b) d = in_data[1].rstrip('\n') self.d_nom.set(d) spacing = in_data[2].rstrip('\n') self.stud_spacing.set(spacing) h = in_data[3].rstrip('\n') self.wall_height.set(h) sub_pl = in_data[4].rstrip('\n') self.sub_plates.set(sub_pl) plates = in_data[5].rstrip('\n') self.num_plates.set(plates) #Reference Stud Values grade = in_data[6].rstrip('\n') self.grade.set(grade) #Fb fb = in_data[7].rstrip('\n') self.fb_psi.set(fb) #Fv fv = in_data[8].rstrip('\n') self.fv_psi.set(fv) #Fc fc = in_data[9].rstrip('\n') self.fc_psi.set(fc) #E E = in_data[10].rstrip('\n') self.E_psi.set(E) #Emin Emin = in_data[11].rstrip('\n') self.Emin_psi.set(Emin) #Fc_perp_pl fcperp = in_data[12].rstrip('\n') self.fc_perp_psi.set(fcperp) #FRT? frtyn = in_data[13].rstrip('\n') self.frt_yn.set(frtyn) frtfb = in_data[14].rstrip('\n') self.frt_fb.set(frtfb) frtfv = in_data[15].rstrip('\n') self.frt_fv.set(frtfv) frtfc = in_data[16].rstrip('\n') self.frt_fc.set(frtfc) frtfperp = in_data[17].rstrip('\n') self.frt_fc_perp.set(frtfperp) frtE = in_data[18].rstrip('\n') self.frt_E.set(frtE) frtEmin = in_data[19].rstrip('\n') self.frt_Emin.set(frtEmin) species = in_data[20].rstrip('\n') self.species.set(species) #Moisture % moist = in_data[21].rstrip('\n') self.moisture.set(moist) #Temp F temp= in_data[22].rstrip('\n') self.temp.set(temp) #Incised? inc = in_data[23].rstrip('\n') self.incised_yn.set(inc) p = in_data[24].rstrip('\n') self.pressure.set(p) cd = in_data[25].rstrip('\n') self.cd.set(cd) e = in_data[26].rstrip('\n') self.min_ecc_yn.set(e) self.run() def write_text_results_to_file(self,*event): #generate file name and confirm path exists if not create it b = self.b_nom.get() d = self.d_nom.get() h = self.wall_height.get() p = self.pressure.get() cd = self.cd.get() min_ecc = self.min_ecc_yn.get() if min_ecc == 1: e_string_file = '-Axial_Ecc_Included' else: e_string_file ='' label = '{0}x{1}_height-{2}_ft_pressure-{3}_psf_Cd-{4}'.format(b,d,h,p,cd) path = os.path.join(os.path.expanduser('~'),'Desktop','RESULTS','Wood_Walls', label) self.path_exists(path) name = label+e_string_file+'_results.txt' output = self.results_text_box.get(1.0,tk.END) #file = open(os.path.join(path,name),'w') #file.write(output) #file.close() name_nds_table = label+e_string_file+'_nds_load_factor_table.csv' string = '' for i in range(len(self.res_nds_table_output)): string = string + '{0},'.format(self.res_nds_table_output[i]) file = open(os.path.join(path,name_nds_table),'w') file.write(string) file.write('\n') file.write(output) file.close() def print_pm_graph_common(self,*event): b = self.b_actual d = self.d_actual h = self.wall_height.get() p = self.pressure.get() cd = self.cd.get() grade = self.grade.get() label = '{0}x{1}_height-{2}_ft_pressure-{3}_psf_Cd-{4}'.format(self.b_nom.get(),self.d_nom.get(),h,p,cd) path = os.path.join(os.path.expanduser('~'),'Desktop','RESULTS','Wood_Walls', label,'PvM_Charts') self.path_exists(path) #initialize plot pmfig, ax1C = plt.subplots(figsize=(17,11), dpi=600) ax1C.minorticks_on() ax1C.grid(b=True, which='major', color='k', linestyle='-', alpha=0.3) ax1C.grid(b=True, which='minor', color='g', linestyle='-', alpha=0.1) ax2C=ax1C.twinx() #Prebuild chart lines so data can be refreshed to cut down on render time #['0.9','1.0','1.15','1.25','1.6','2.0'] line_cd009C, = ax1C.plot([0,10],[10,0], label='Cd = 0.9') line_cd100C, = ax1C.plot([0,15],[15,0], label='Cd = 1.0') line_cd115C, = ax1C.plot([0,25],[25,0], label='Cd = 1.15') line_cd125C, = ax1C.plot([0,35],[35,0], label='Cd = 1.25') line_cd160C, = ax1C.plot([0,50],[50,0], label='Cd = 1.6') line_cd200C, = ax1C.plot([0,75],[75,0], label='Cd = 2.0') line_pl_cbC, = ax1C.plot([0,10],[3,3], label='PL Crushing') line_pl_wo_cbC, = ax1C.plot([0,10],[1.5,1.5], label='PL Crushing w/o Cb') line_delta_cd009C, = ax2C.plot([0,10],[0,13], label='D - Cd = 0.9') line_delta_cd100C, = ax2C.plot([0,15],[15,0], label='D - Cd = 1.0') line_delta_cd115C, = ax2C.plot([0,25],[25,0], label='D - Cd = 1.15') line_delta_cd125C, = ax2C.plot([0,35],[35,0], label='D - Cd = 1.25') line_delta_cd160C, = ax2C.plot([0,50],[50,0], label='D - Cd = 1.6') line_delta_cd200C, = ax2C.plot([0,75],[75,0], label='D - Cd = 2.0') self.line_delta_180C, = ax2C.plot([6,6],[0,13], label='H/180', linestyle=':') self.line_delta_240C, = ax2C.plot([4,4],[0,13], label='H/240', linestyle=':') self.line_delta_360C, = ax2C.plot([1,1],[0,13], label='H/360', linestyle=':') self.line_delta_600C, = ax2C.plot([1,1],[0,13], label='H/600', linestyle=':') legend_ax1C = ax1C.legend(loc=1, fontsize='x-small') legend_ax2C = ax2C.legend(loc=4, fontsize='x-small') min_ecc = self.min_ecc_yn.get() if min_ecc == 1: e_string = ' at min d/6 = {0:.3f} in eccentricity '.format(self.e_in) e_string_file = '-Axial_Ecc_Included' else: e_string ='' e_string_file ='' ax1C.set_ylabel('Axial (plf)'+e_string) ax1C.set_xlabel('Moment (in-lbs)') ax2C.set_ylabel('Mid Height Deflection (in)') spacings = [4,6,8,12,16,24] for s in spacings: file = '{0}x{1}_height-{2}_ft_Spacing_{3}_in-PvM_chart_11x17{4}.pdf'.format(self.b_nom.get(),self.d_nom.get(),h,s,e_string_file) title = '{0}x{1} ({2:.2f}x{3:.2f})- Height:{4} ft - Species: {7} - Grade: {5} - Spacing: {6} in'.format(self.b_nom.get(),self.d_nom.get(),self.b_actual,self.d_actual,h,grade,s, self.species.get()) e_in = self.e_in #Refresh chart data for each Cd #Cd - NDS 2005 Table 2.3.2 #cd = [0.9,1.0,1.15,1.25,1.6,2.0] w,p,d = self.wall.wall_pm_diagram_cd(0.9,e_in,s) line_cd009C.set_data(w,p) line_delta_cd009C.set_data(w,d) w,p,d = self.wall.wall_pm_diagram_cd(1.0,e_in,s) line_cd100C.set_data(w,p) line_delta_cd100C.set_data(w,d) w,p,d = self.wall.wall_pm_diagram_cd(1.15,e_in,s) line_cd115C.set_data(w,p) line_delta_cd115C.set_data(w,d) w,p,d = self.wall.wall_pm_diagram_cd(1.25,e_in,s) line_cd125C.set_data(w,p) line_delta_cd125C.set_data(w,d) w,p,d = self.wall.wall_pm_diagram_cd(1.6,e_in,s) line_cd160C.set_data(w,p) line_delta_cd160C.set_data(w,d) w,p,d = self.wall.wall_pm_diagram_cd(2.0,e_in,s) line_cd200C.set_data(w,p) line_delta_cd200C.set_data(w,d) if (self.wall.crushing_limit_lbs/(s/12.0)) > 1.2*max(p): line_pl_cbC.set_data([0,0],[0,0]) line_pl_wo_cbC.set_data([0,0],[0,0]) else: line_pl_cbC.set_data([0,max(w)],[self.wall.crushing_limit_lbs/(s/12.0),self.wall.crushing_limit_lbs/(s/12.0)]) line_pl_wo_cbC.set_data([0,max(w)],[self.wall.crushing_limit_lbs_no_cb/(s/12.0),self.wall.crushing_limit_lbs_no_cb/(s/12.0)]) self.line_delta_180C.set_data([0,max(w)],[self.wall.height_in/180.0,self.wall.height_in/180.0]) self.line_delta_240C.set_data([0,max(w)],[self.wall.height_in/240.0,self.wall.height_in/240.0]) self.line_delta_360C.set_data([0,max(w)],[self.wall.height_in/360.0,self.wall.height_in/360.0]) self.line_delta_600C.set_data([0,max(w)],[self.wall.height_in/600.0,self.wall.height_in/600.0]) ax1C.set_xlim(0, max(w)+500) ax1C.set_ylim(0, max(p)+200) ax2C.set_ylim(0, max(d)+0.75) ax1C.set_title(title) pmfig.savefig(os.path.join(path,file)) file = '{0}x{1}_height-{2}_ft-PvM_chart_per_Stud_11x17{3}.pdf'.format(self.b_nom.get(),self.d_nom.get(),h,e_string_file) title = '{0}x{1} ({2:.2f}x{3:.2f})- Height:{4} ft - Species: {6} - Grade: {5}'.format(self.b_nom.get(),self.d_nom.get(),self.b_actual,self.d_actual,h,grade, self.species.get()) e_in = self.e_in #Refresh chart data for each Cd #Cd - NDS 2005 Table 2.3.2 #cd = [0.9,1.0,1.15,1.25,1.6,2.0] w,p,d = self.wall.wall_pm_diagram_cd_stud(0.9,e_in) line_cd009C.set_data(w,p) line_delta_cd009C.set_data(w,d) w,p,d = self.wall.wall_pm_diagram_cd_stud(1.0,e_in) line_cd100C.set_data(w,p) line_delta_cd100C.set_data(w,d) w,p,d = self.wall.wall_pm_diagram_cd_stud(1.15,e_in) line_cd115C.set_data(w,p) line_delta_cd115C.set_data(w,d) w,p,d = self.wall.wall_pm_diagram_cd_stud(1.25,e_in) line_cd125C.set_data(w,p) line_delta_cd125C.set_data(w,d) w,p,d = self.wall.wall_pm_diagram_cd_stud(1.6,e_in) line_cd160C.set_data(w,p) line_delta_cd160C.set_data(w,d) w,p,d = self.wall.wall_pm_diagram_cd_stud(2.0,e_in) line_cd200C.set_data(w,p) line_delta_cd200C.set_data(w,d) if (self.wall.crushing_limit_lbs) > 1.2*max(p): line_pl_cbC.set_data([0,0],[0,0]) line_pl_wo_cbC.set_data([0,0],[0,0]) else: line_pl_cbC.set_data([0,max(w)],[self.wall.crushing_limit_lbs,self.wall.crushing_limit_lbs]) line_pl_wo_cbC.set_data([0,max(w)],[self.wall.crushing_limit_lbs_no_cb,self.wall.crushing_limit_lbs_no_cb]) self.line_delta_180C.set_data([0,max(w)],[self.wall.height_in/180.0,self.wall.height_in/180.0]) self.line_delta_240C.set_data([0,max(w)],[self.wall.height_in/240.0,self.wall.height_in/240.0]) self.line_delta_360C.set_data([0,max(w)],[self.wall.height_in/360.0,self.wall.height_in/360.0]) self.line_delta_600C.set_data([0,max(w)],[self.wall.height_in/600.0,self.wall.height_in/600.0]) ax1C.set_xlim(0, max(w)+500) ax1C.set_ylim(0, max(p)+200) ax2C.set_ylim(0, max(d)+0.75) ax1C.set_ylabel('Axial (lbs)'+e_string) ax1C.set_title(title) pmfig.savefig(os.path.join(path,file)) plt.close('all') def print_pp_graph_common(self,*event): b = self.b_actual d = self.d_actual h = self.wall_height.get() p = self.pressure.get() cd = self.cd.get() grade = self.grade.get() label = '{0}x{1}_height-{2}_ft_pressure-{3}_psf_Cd-{4}'.format(self.b_nom.get(),self.d_nom.get(),h,p,cd) path = os.path.join(os.path.expanduser('~'),'Desktop','RESULTS','Wood_Walls', label,'PvPressure_Charts') self.path_exists(path) #initialize plot pmfig, ax1C = plt.subplots(figsize=(17,11), dpi=600) ax1C.minorticks_on() ax1C.grid(b=True, which='major', color='k', linestyle='-', alpha=0.3) ax1C.grid(b=True, which='minor', color='g', linestyle='-', alpha=0.1) ax2C=ax1C.twinx() #Prebuild chart lines so data can be refreshed to cut down on render time #['0.9','1.0','1.15','1.25','1.6','2.0'] line_cd009C, = ax1C.plot([0,10],[10,0], label='Cd = 0.9') line_cd100C, = ax1C.plot([0,15],[15,0], label='Cd = 1.0') line_cd115C, = ax1C.plot([0,25],[25,0], label='Cd = 1.15') line_cd125C, = ax1C.plot([0,35],[35,0], label='Cd = 1.25') line_cd160C, = ax1C.plot([0,50],[50,0], label='Cd = 1.6') line_cd200C, = ax1C.plot([0,75],[75,0], label='Cd = 2.0') line_pl_cbC, = ax1C.plot([0,10],[3,3], label='PL Crushing') line_pl_wo_cbC, = ax1C.plot([0,10],[1.5,1.5], label='PL Crushing w/o Cb') line_delta_cd009C, = ax2C.plot([0,10],[0,13], label='D - Cd = 0.9') line_delta_cd100C, = ax2C.plot([0,15],[15,0], label='D - Cd = 1.0') line_delta_cd115C, = ax2C.plot([0,25],[25,0], label='D - Cd = 1.15') line_delta_cd125C, = ax2C.plot([0,35],[35,0], label='D - Cd = 1.25') line_delta_cd160C, = ax2C.plot([0,50],[50,0], label='D - Cd = 1.6') line_delta_cd200C, = ax2C.plot([0,75],[75,0], label='D - Cd = 2.0') self.line_delta_180C, = ax2C.plot([6,6],[0,13], label='H/180', linestyle=':') self.line_delta_240C, = ax2C.plot([4,4],[0,13], label='H/240', linestyle=':') self.line_delta_360C, = ax2C.plot([1,1],[0,13], label='H/360', linestyle=':') self.line_delta_600C, = ax2C.plot([1,1],[0,13], label='H/600', linestyle=':') legend_ax1C = ax1C.legend(loc=1, fontsize='x-small') legend_ax2C = ax2C.legend(loc=4, fontsize='x-small') min_ecc = self.min_ecc_yn.get() if min_ecc == 1: e_string = ' at min d/6 = {0:.3f} in eccentricity '.format(self.e_in) e_string_file = '-Axial_Ecc_Included' else: e_string ='' e_string_file ='' ax1C.set_ylabel('Axial (plf)'+e_string) ax1C.set_xlabel('Pressure (psf)') ax2C.set_ylabel('Mid Height Deflection (in)') spacings = [4,6,8,12,16,24] for s in spacings: file = '{0}x{1}_height-{2}_ft_Spacing_{3}_in-PvP_chart_11x17{4}.pdf'.format(self.b_nom.get(),self.d_nom.get(),h,s,e_string_file) title = '{0}x{1} ({2:.2f}x{3:.2f})- Height:{4} ft - Species: {7} - Grade: {5} - Spacing: {6} in'.format(self.b_nom.get(),self.d_nom.get(),self.b_actual,self.d_actual,h,grade,s, self.species.get()) e_in = self.e_in #Refresh chart data for each Cd #Cd - NDS 2005 Table 2.3.2 #cd = [0.9,1.0,1.15,1.25,1.6,2.0] w,p,d = self.wall.wall_interaction_diagram_cd(0.9,e_in,s) line_cd009C.set_data(w,p) line_delta_cd009C.set_data(w,d) w,p,d = self.wall.wall_interaction_diagram_cd(1.0,e_in,s) line_cd100C.set_data(w,p) line_delta_cd100C.set_data(w,d) w,p,d = self.wall.wall_interaction_diagram_cd(1.15,e_in,s) line_cd115C.set_data(w,p) line_delta_cd115C.set_data(w,d) w,p,d = self.wall.wall_interaction_diagram_cd(1.25,e_in,s) line_cd125C.set_data(w,p) line_delta_cd125C.set_data(w,d) w,p,d = self.wall.wall_interaction_diagram_cd(1.6,e_in,s) line_cd160C.set_data(w,p) line_delta_cd160C.set_data(w,d) w,p,d = self.wall.wall_interaction_diagram_cd(2.0,e_in,s) line_cd200C.set_data(w,p) line_delta_cd200C.set_data(w,d) if (self.wall.crushing_limit_lbs/(s/12.0)) > 1.2*max(p): line_pl_cbC.set_data([0,0],[0,0]) line_pl_wo_cbC.set_data([0,0],[0,0]) else: line_pl_cbC.set_data([0,max(w)],[self.wall.crushing_limit_lbs/(s/12.0),self.wall.crushing_limit_lbs/(s/12.0)]) line_pl_wo_cbC.set_data([0,max(w)],[self.wall.crushing_limit_lbs_no_cb/(s/12.0),self.wall.crushing_limit_lbs_no_cb/(s/12.0)]) self.line_delta_180C.set_data([0,max(w)],[self.wall.height_in/180.0,self.wall.height_in/180.0]) self.line_delta_240C.set_data([0,max(w)],[self.wall.height_in/240.0,self.wall.height_in/240.0]) self.line_delta_360C.set_data([0,max(w)],[self.wall.height_in/360.0,self.wall.height_in/360.0]) self.line_delta_600C.set_data([0,max(w)],[self.wall.height_in/600.0,self.wall.height_in/600.0]) ax1C.set_xlim(0, max(w)+20) ax1C.set_ylim(0, max(p)+200) ax2C.set_ylim(0, max(d)+0.75) ax1C.set_title(title) pmfig.savefig(os.path.join(path,file)) plt.close('all') def run_user_loads(self, *event): #Initialize the "No Good" Count ng_count = 0 #Get New user defined spacing from user load tab s_in = float(self.user_calc_spacing.get()) #Check that spacing is greater than the stud width if s_in<self.wall.b_in: tkMessageBox.showerror("ERROR!!","Spacing is less than wall stud width.") else: pass #Initialize the output strings - used to make exporting the results easier self.user_load_res_string_output = '' self.user_vert_load_string = '\nVertical Loads:\n' self.user_lat_load_string = 'Lateral Loads:\n' e = self.e_in loads_plf = [] loads_lbs = [] grav_delta = [] grav_shear = [] #Wall Self Weight to be added to DL self.user_vert_load_string = self.user_vert_load_string + 'Self Weight: ,{0}, psf x ,{1}, ft = '.format(self.user_sw.get(),self.user_sw_height_ft.get()) sw_plf = float(self.user_sw.get())*float(self.user_sw_height_ft.get()) self.user_sw_label.configure(text='ft = {0:.3f} plf'.format(sw_plf)) self.user_vert_load_string = self.user_vert_load_string + ',{0:.2f}, plf\n'.format(sw_plf) sw_lbs = sw_plf*(s_in/12.0) sw_delta = 0 sw_shear = 0 i=0 for load in self.user_vert_loads_psf: self.user_vert_load_string = self.user_vert_load_string + '{0} ,{1}, psf x ,{2}, ft = '.format(self.user_vert_load_labels[i],load.get(),self.user_vert_loads_trib[i].get()) load_psf = float(load.get()) load_trib = float(self.user_vert_loads_trib[i].get()) loads_plf.append(load_psf * load_trib) loads_lbs.append(loads_plf[i]*(s_in/12.0)) self.user_load_trib_plf_label[i].configure(text='ft = {0:.3f} plf @ e = {1:.3f} in'.format(loads_plf[i],e)) self.user_vert_load_string = self.user_vert_load_string + ',{0:.3f}, plf @ e = ,{1:.3f}, in\n'.format(loads_plf[i], e) grav_delta.append(((loads_lbs[i]*e)*self.wall.height_in**2)/(16.0*self.wall.E_prime_psi*self.wall.I_in4)) grav_shear.append((loads_lbs[i]*e) / self.wall.height_in) i+=1 loads_lbs.append(0) grav_delta.append(0) grav_shear.append(0) loads_lbs[0] = loads_lbs[0] + sw_lbs grav_delta[0] = grav_delta[0] + sw_delta grav_shear[0] = grav_shear[0] + sw_shear lat_plf = [] lat_inlbs = [] lat_delta = [] lat_shear = [] i=0 for lat_load in self.user_lat_loads_psf: lat_load_psf = float(lat_load.get()) lat_plf.append(lat_load_psf*(s_in/12.0)) self.user_lat_load_string = self.user_lat_load_string + '{0} ,{1}, psf x ,{2:.2f}, in x 1/12 ft/in = ,{3:.2f}, plf\n'.format(self.user_lat_load_labels[i],lat_load.get(),s_in,lat_plf[i]) lat_inlbs.append(((lat_plf[i]*((self.wall.height_in)/12.0)**2)/8.0)*12.0) lat_delta.append((1728*5*lat_plf[i]*(self.wall.height_in/12.0)**4)/(384*self.wall.E_prime_psi*self.wall.I_in4)) lat_shear.append((((lat_plf[i]*(self.wall.height_in))/12.0)/2.0)) i+=1 i=0 p_plot = [] m_plot = [] d_plot = [] ratio_text = '' for combo in self.load_combos: self.user_load_res_string_output = self.user_load_res_string_output + '{0},{1},'.format(combo[0],combo[1]) fc_prime = self.wall.fc_prime_calc(combo[1]) fb_prime = self.wall.fb_prime_calc(combo[1]) fv_prime = self.wall.fv_prime_psi_cd p = 0 m = 0 v = 0 delta = 0 for c in range(2,8): p = p + (loads_lbs[c-2]*combo[c]) delta = delta + (grav_delta[c-2]*combo[c]) v = v + (grav_shear[c-2]*combo[c]) if c == 3: m = m + (lat_inlbs[0]*combo[c]) delta = delta + (lat_delta[0]*combo[c]) v = v + (lat_shear[0]*combo[c]) elif c == 7: m = m + (lat_inlbs[1]*combo[c]) delta = delta + (lat_delta[1]*combo[c]) v = v + (lat_shear[1]*combo[c]) else: m = m delta = delta v = v fc = p / self.wall.area_in2 fb = m / self.wall.s_in3 fv = (3.0 * v) / (2.0*self.wall.b_in*self.wall.d_in) if delta == 0: delta_ratio = 0 else: delta_ratio = self.wall.height_in/delta if e == 0: if m==0: ratio = fc/fc_prime ratio_text = " (fc/Fc')" elif p==0: ratio = fb/fb_prime ratio_text = " (fb/Fb')" else: if fc/self.wall.fcE_psi > 1.0: ratio = 100 ratio_text = " (fc > FcE)" else: ratio = (fc/fc_prime)**2 + (fb / (fb_prime*(1-(fc/self.wall.fcE_psi)))) ratio_text = " (3.9-3)" ratio_v = fv / fv_prime ratio = max(ratio,ratio_v) if ratio == ratio_v: ratio_text = " (fv/Fv')" else: ratio_text = ratio_text else: if fc/self.wall.fcE_psi > 1.0: ratio = 100 ratio_text = " (fc > FcE)" else: ratio = (fc/fc_prime)**2 + ((fb+(fc*(6*e/self.wall.d_in)*(1+(0.234*(fc/self.wall.fcE_psi)))))/ (fb_prime*(1-(fc/self.wall.fcE_psi)))) ratio_text = " (15.4-1)" ratio_v = fv / fv_prime ratio = max(ratio,ratio_v) if ratio == ratio_v: ratio_text = " (fv/Fv')" else: ratio_text = ratio_text if ratio > 1.0 or s_in<self.wall.b_in: user_status = 'NG' ng_count = ng_count +1 else: user_status = 'OK' ng_count = ng_count if p > self.wall.crushing_limit_lbs: self.user_p_res_labels[i].configure(text='{0:.2f}**'.format(p)) self.user_load_res_string_output = self.user_load_res_string_output + '{0:.2f}**,'.format(p) elif p > self.wall.crushing_limit_lbs_no_cb: self.user_p_res_labels[i].configure(text='{0:.2f}*'.format(p)) self.user_load_res_string_output = self.user_load_res_string_output + '{0:.2f}*,'.format(p) else: self.user_p_res_labels[i].configure(text='{0:.2f}'.format(p)) self.user_load_res_string_output = self.user_load_res_string_output + '{0:.2f},'.format(p) self.user_fc_res_labels[i].configure(text='{0:.3f}'.format(fc)) self.user_load_res_string_output = self.user_load_res_string_output + '{0:.3f},'.format(fc) self.user_kel_res_labels[i].configure(text='{0:.2f}'.format(self.wall.height_in/self.wall.d_in)) self.user_load_res_string_output = self.user_load_res_string_output + '{0:.2f},'.format(self.wall.height_in/self.wall.d_in) self.user_FcE_res_labels[i].configure(text='{0:.2f}'.format(self.wall.fcE_psi)) self.user_load_res_string_output = self.user_load_res_string_output + '{0:.2f},'.format(self.wall.fcE_psi) self.user_c_labels[i].configure(text='{0:.1f}'.format(self.wall.c_cp)) self.user_load_res_string_output = self.user_load_res_string_output + '{0:.1f},'.format(self.wall.c_cp) self.user_cp_labels[i].configure(text='{0:.3f}'.format(self.wall.cp)) self.user_load_res_string_output = self.user_load_res_string_output + '{0:.3f},'.format(self.wall.cp) self.user_fcprime_res_labels[i].configure(text='{0:.2f}'.format(fc_prime)) self.user_load_res_string_output = self.user_load_res_string_output + '{0:.2f},'.format(fc_prime) self.user_fc_fc_res_labels[i].configure(text='{0:.3f}'.format(fc/fc_prime)) self.user_load_res_string_output = self.user_load_res_string_output + '{0:.3f},'.format(fc/fc_prime) self.user_m_res_labels[i].configure(text='{0:.2f}'.format(m)) self.user_load_res_string_output = self.user_load_res_string_output + '{0:.2f},'.format(m) self.user_fb_res_labels[i].configure(text='{0:.3f}'.format(fb)) self.user_load_res_string_output = self.user_load_res_string_output + '{0:.3f},'.format(fb) self.user_fbprime_res_labels[i].configure(text='{0:.2f}'.format(fb_prime)) self.user_load_res_string_output = self.user_load_res_string_output + '{0:.2f},'.format(fb_prime) self.user_fb_fb_res_labels[i].configure(text='{0:.3f}'.format(fb/fb_prime)) self.user_load_res_string_output = self.user_load_res_string_output + '{0:.3f},'.format(fb/fb_prime) self.user_v_res_labels[i].configure(text='{0:.2f}'.format(v)) self.user_load_res_string_output = self.user_load_res_string_output + '{0:.2f},'.format(v) self.user_fv_res_labels[i].configure(text='{0:.2f}'.format(fv)) self.user_load_res_string_output = self.user_load_res_string_output + '{0:.2f},'.format(fv) self.user_fvprime_res_labels[i].configure(text='{0:.2f}'.format(fv_prime)) self.user_load_res_string_output = self.user_load_res_string_output + '{0:.2f},'.format(fv_prime) self.user_fv_fv_res_labels[i].configure(text='{0:.3f}'.format(fv/fv_prime)) self.user_load_res_string_output = self.user_load_res_string_output + '{0:.3f},'.format(fv/fv_prime) self.user_ratio_res_labels[i].configure(text='{0:.3f}{1}'.format(ratio,ratio_text)) self.user_load_res_string_output = self.user_load_res_string_output + '{0:.3f}{1},'.format(ratio,ratio_text) self.user_deltaratio_res_labels[i].configure(text='{1:.3f} in (H/{0:.1f})'.format(delta_ratio,delta)) self.user_load_res_string_output = self.user_load_res_string_output +'{1:.3f} in (H/{0:.1f}),'.format(delta_ratio,delta) if user_status == 'OK': self.user_status_res_labels[i].configure(text='{0}'.format(user_status),background='green') else: self.user_status_res_labels[i].configure(text='{0}'.format(user_status),background='red') self.user_load_res_string_output = self.user_load_res_string_output + '{0}\n'.format(user_status) p_plot.append(p) m_plot.append(m) d_plot.append(delta) i+=1 self.user_pmD.set_data(m_plot,p_plot) self.user_mdD.set_data(m_plot,d_plot) self.canvasD.draw() if ng_count > 0: return 1 else: return 0 def solve_user_loads(self, *event): #optimize spacing a=0 b=24 #upper bound limit on spacing for Cr=1.15 c=0 loop_max = 500 tol = 0.0001 loop = 0 self.user_calc_spacing.set(b) check = self.run_user_loads() if check == 0: self.user_calc_spacing.set(b) self.run_user_loads() else: while loop<loop_max: c = (a+b)/2.0 self.user_calc_spacing.set(c) check = self.run_user_loads() if check == 0 : a = c else: b = c if (b-a)/2.0 <= tol: loop = loop_max c = math.floor(c*4)/4 self.user_calc_spacing.set(c) self.run_user_loads() elif c<self.wall.b_in: loop = loop_max self.user_calc_spacing.set(0) self.run_user_loads() else: loop+=1 def export_user_load_results(self,*event): #Run the user loads so export results are always current self.run_user_loads() #Get New user defined spacing from user load tab s_in = float(self.user_calc_spacing.get()) #generate file name and confirm path exists if not create it b = self.b_nom.get() d = self.d_nom.get() h = self.wall_height.get() p = self.pressure.get() cd = self.cd.get() grade = self.grade.get() min_ecc = self.min_ecc_yn.get() if min_ecc == 1: e_string_file = '-Axial_Ecc_Included' else: e_string_file ='' label = '{0}x{1}_height-{2}_ft_pressure-{3}_psf_Cd-{4}'.format(b,d,h,p,cd) path = os.path.join(os.path.expanduser('~'),'Desktop','RESULTS','Wood_Walls', label) self.path_exists(path) name = label+e_string_file+'_user_load_results.csv' chart = label+e_string_file+'_user_load_results_nomograph.jpg' self.FigD.savefig(os.path.join(path,chart)) title = 'Nominal: ,{0},x,{1}, Height:,{4}, ft, Species:, {6} ,Grade:, {5}\nActual: ,{2:.2f}, in x,{3:.2f}, in\n'.format(self.b_nom.get(),self.d_nom.get(),self.b_actual,self.d_actual,h,grade, self.species.get()) file = open(os.path.join(path,name),'w') file.write('User Load Results - IBC 2012 - ASD\n') file.write(title) file.write('Design Stud Spacing: ,{0:.3f}, in\n'.format(s_in)) file.write(self.user_vert_load_string+'\n') file.write(self.user_lat_load_string+'\n') file.write("Combo:,Cd,P (lbs), fc (psi),Ke Le_d/d,FcE (psi),c,Cp,Fc' (psi),fc/Fc',M_lat (in-lbs),fb_lat (psi),Fb' (psi),fb/Fb',V (lbs),fv (psi),Fv' (psi),fv/Fv',Ratio,D (H/--),Status\n") file.write(self.user_load_res_string_output) file.write('* - indicates load greater than wall plate crushing w/o Cb - {0:.3f} lbs\n'.format(self.wall.crushing_limit_lbs_no_cb)) file.write('** - indicates load greater than wall plate crushing w/ Cb - {0:.3f} lbs\n'.format(self.wall.crushing_limit_lbs)) file.write('\n'+self.wall.assumptions) file.close() def main(): root = tk.Tk() root.title("Wood Stud Wall - 2-4x Studs - North American Species (Not Southern Pine) - V0.9 BETA") Master_window(root) root.minsize(1024,700) root.mainloop() if __name__ == '__main__': main()