diff --git a/documentation/Usage.ipynb b/documentation/Usage.ipynb index c489dd4..88bfe45 100644 --- a/documentation/Usage.ipynb +++ b/documentation/Usage.ipynb @@ -13,14 +13,17 @@ "metadata": {}, "outputs": [], "source": [ - "from ak_sap import debug, Sap2000Wrapper\n", + "from ak_sap import Sap2000Wrapper, debug\n", + "\n", "debug(status=False)\n", "\n", - "#Initialize\n", - "sap = Sap2000Wrapper(attach_to_exist=True) #Attach to existing opened model\n", - "sap = Sap2000Wrapper(attach_to_exist=False) #Create new blank model from latest SAP2000\n", + "# Initialize\n", + "sap = Sap2000Wrapper(attach_to_exist=True) # Attach to existing opened model\n", + "sap = Sap2000Wrapper(\n", + " attach_to_exist=False\n", + ") # Create new blank model from latest SAP2000\n", "## Create blank model from a custom version of SAP2000\n", - "sap = Sap2000Wrapper(attach_to_exist=False, program_path=r'Path\\to\\SAP2000.exe')" + "sap = Sap2000Wrapper(attach_to_exist=False, program_path=r\"Path\\to\\SAP2000.exe\")" ] }, { @@ -36,14 +39,14 @@ "metadata": {}, "outputs": [], "source": [ - "sap.hide() #Hide the SAP2000 window\n", - "sap.unhide() #Unhides SAP2000 window\n", - "sap.ishidden #Check if window is hidden\n", - "sap.version #Returns SAP2000 version number\n", - "sap.api_version #Returns Sap0API version number\n", - "sap.exit(save=False) #Exit the application\n", + "sap.hide() # Hide the SAP2000 window\n", + "sap.unhide() # Unhides SAP2000 window\n", + "sap.ishidden # Check if window is hidden\n", + "sap.version # Returns SAP2000 version number\n", + "sap.api_version # Returns Sap0API version number\n", + "sap.exit(save=False) # Exit the application\n", "\n", - "sap.save(r'\\Path\\to\\save\\file.sdb')" + "sap.save(r\"\\Path\\to\\save\\file.sdb\")" ] }, { @@ -68,25 +71,25 @@ "metadata": {}, "outputs": [], "source": [ - "sap.Model.units #Returns current model units\n", - "sap.Model.units_database #Returns Internal Database units\n", - "sap.Model.set_units(value='N_m_C') #Changes the present units of model\n", + "sap.Model.units # Returns current model units\n", + "sap.Model.units_database # Returns Internal Database units\n", + "sap.Model.set_units(value=\"N_m_C\") # Changes the present units of model\n", "\n", - "sap.Model.merge_tol #retrieves the value of the program auto merge tolerance\n", - "sap.Model.set_merge_tol(0.05) #sets the program auto merge tolerance\n", + "sap.Model.merge_tol # retrieves the value of the program auto merge tolerance\n", + "sap.Model.set_merge_tol(0.05) # sets the program auto merge tolerance\n", "\n", - "sap.Model.filepath #Returns filepath of current file\n", + "sap.Model.filepath # Returns filepath of current file\n", "\n", - "sap.Model.is_locked #Returns if the model is locked\n", - "sap.Model.lock() #Locks the model\n", - "sap.Model.unlock() #Unlocks the model\n", + "sap.Model.is_locked # Returns if the model is locked\n", + "sap.Model.lock() # Locks the model\n", + "sap.Model.unlock() # Unlocks the model\n", "\n", - "sap.Model.project_info #Returns a dict of Project Info\n", + "sap.Model.project_info # Returns a dict of Project Info\n", "##Set project info, use `.project_info` to see available keys\n", - "sap.Model.set_project_info({'Design Code': 'BCBC 2018'})\n", + "sap.Model.set_project_info({\"Design Code\": \"BCBC 2018\"})\n", "\n", - "sap.Model.logs #Retrieve user comments and logs\n", - "sap.Model.set_logs('Add this comment') #Adds user comments/logs" + "sap.Model.logs # Retrieve user comments and logs\n", + "sap.Model.set_logs(\"Add this comment\") # Adds user comments/logs" ] }, { @@ -105,14 +108,15 @@ "outputs": [], "source": [ "object = sap.Object\n", - "object.move_selected(dx=0.5, dy=0, dz=1.0) #Move selected object\n", - "object.copy(dx=0.5, dy=0, dz=0, num=10)#copy selected object\n", + "object.move_selected(dx=0.5, dy=0, dz=1.0) # Move selected object\n", + "object.copy(dx=0.5, dy=0, dz=0, num=10) # copy selected object\n", "\n", - "#Mirror and create object\n", + "# Mirror and create object\n", "from ak_sap import Coord\n", + "\n", "pt1 = Coord(x=10, y=20, z=0)\n", "p2 = Coord(x=10, y=30, z=0)\n", - "object.mirror(plane='Z', coord1=pt1, coord2=pt2) #Mirror replicate selected obj." + "object.mirror(plane=\"Z\", coord1=pt1, coord2=pt2) # Mirror replicate selected obj." ] }, { @@ -131,30 +135,25 @@ "outputs": [], "source": [ "points = sap.Object.Point\n", - "len(points) #list number of points in model\n", - "points.add_by_coord((1,2,3)) #Add point to model\n", - "points.is_selected(name='1') #Check if point is selected\n", - "points.selected() #Yields selected points\n", - "points.all() #Lists all defined points\n", - "points.rename(old_name='1', new_name='1_1') #Rename point\n", - "points.check_obj_legal(name='1') #Asserts point's existance\n", - "points.delete(name='1') #Delete point\n", - "\n", - "#Manipilate\n", - "points.deselect_all() #Deselect all points\n", - "points.select(name='1') #Select a single point\n", - "points.align(axis='Z', ordinate = 100) #Align selected points\n", - "points.deselect(name='1') #Deselect a single point\n", + "len(points) # list number of points in model\n", + "points.add_by_coord((1, 2, 3)) # Add point to model\n", + "points.is_selected(name=\"1\") # Check if point is selected\n", + "points.selected() # Yields selected points\n", + "points.all() # Lists all defined points\n", + "points.rename(old_name=\"1\", new_name=\"1_1\") # Rename point\n", + "points.check_obj_legal(name=\"1\") # Asserts point's existance\n", + "points.delete(name=\"1\") # Delete point\n", + "\n", + "# Manipilate\n", + "points.deselect_all() # Deselect all points\n", + "points.select(name=\"1\") # Select a single point\n", + "points.align(axis=\"Z\", ordinate=100) # Align selected points\n", + "points.deselect(name=\"1\") # Deselect a single point\n", "\n", "# Extrude point to frame\n", - "points.extrude(\n", - " point_name='3',\n", - " property_name='FSec1',\n", - " dx=0, dy=144, dz=0,\n", - " num_frames=3\n", - ")\n", - "points.merge(tolerance=2) #Merge points that are within tol\n", - "points.change_coord(name='1', x=0, y=0, z=0)#Change point coordinate" + "points.extrude(point_name=\"3\", property_name=\"FSec1\", dx=0, dy=144, dz=0, num_frames=3)\n", + "points.merge(tolerance=2) # Merge points that are within tol\n", + "points.change_coord(name=\"1\", x=0, y=0, z=0) # Change point coordinate" ] }, { @@ -173,36 +172,39 @@ "outputs": [], "source": [ "frames = sap.Object.Frame\n", - "len(frames) #list number of frames in model\n", - "frames.is_selected(name='1') #Check if frame is selected\n", - "frames.selected() #Yields selected frames\n", - "frames.all() #Lists all defined frames\n", - "frames.rename(old_name='1', new_name='1_1') #Rename frame\n", - "frames.check_obj_legal(name='1') #Asserts frame's existance\n", - "frames.get_section(name='1') #Get the assigned Section name\n", - "frames.get_points(name='1') #Get points connected to frame\n", - "\n", - "#Manipulation\n", - "frames.delete(name='1') #Delete frame\n", - "frames.divide_by_distance(name='1',\n", - " dist=0.5,Iend=True) #Divide frame by distance\n", - "frames.divide_by_intersection(name='2') #Divide at selected intersections\n", - "frames.divide_by_ratio(name='3',ratio=0.3)#Divide at selected ratio\n", - "frames.join('2','3') #Join Colinear frames\n", - "frames.change_points(name='1', point1='1', point2='3') #Change connected points of frame\n", + "len(frames) # list number of frames in model\n", + "frames.is_selected(name=\"1\") # Check if frame is selected\n", + "frames.selected() # Yields selected frames\n", + "frames.all() # Lists all defined frames\n", + "frames.rename(old_name=\"1\", new_name=\"1_1\") # Rename frame\n", + "frames.check_obj_legal(name=\"1\") # Asserts frame's existance\n", + "frames.get_section(name=\"1\") # Get the assigned Section name\n", + "frames.get_points(name=\"1\") # Get points connected to frame\n", + "\n", + "# Manipulation\n", + "frames.delete(name=\"1\") # Delete frame\n", + "frames.divide_by_distance(name=\"1\", dist=0.5, Iend=True) # Divide frame by distance\n", + "frames.divide_by_intersection(name=\"2\") # Divide at selected intersections\n", + "frames.divide_by_ratio(name=\"3\", ratio=0.3) # Divide at selected ratio\n", + "frames.join(\"2\", \"3\") # Join Colinear frames\n", + "frames.change_points(\n", + " name=\"1\", point1=\"1\", point2=\"3\"\n", + ") # Change connected points of frame\n", "\n", "# Extrude frames to area\n", "frames.extrude(\n", - " frame_name='8',\n", - " property_name='Default',\n", - " dx=0, dy=144, dz=0,\n", + " frame_name=\"8\",\n", + " property_name=\"Default\",\n", + " dx=0,\n", + " dy=144,\n", + " dz=0,\n", " num_areas=3,\n", - " del_frame=True\n", + " del_frame=True,\n", ")\n", "\n", "# Get frame properties\n", - "frames.Prop.rename(old_name=\"FSEC1\", new_name=\"MySection\") #Rename frame property\n", - "frames.Prop.total() #Total # of defined frame properties" + "frames.Prop.rename(old_name=\"FSEC1\", new_name=\"MySection\") # Rename frame property\n", + "frames.Prop.total() # Total # of defined frame properties" ] }, { @@ -221,15 +223,19 @@ "outputs": [], "source": [ "tables = sap.Table\n", - "tables.list_available() #Lists available database tables\n", - "tables.list_all() #Lists all database tables\n", - "tables.get_table_fields('Analysis Options') #Get table Field Info\n", - "tables.get(TableKey='Load Case Definitions', dataframe=False) #Get Table data in `list[dict]` format\n", - "df = tables.get('Material Properties 01 - General') #Get Table data in pandas dataframe\n", + "tables.list_available() # Lists available database tables\n", + "tables.list_all() # Lists all database tables\n", + "tables.get_table_fields(\"Analysis Options\") # Get table Field Info\n", + "tables.get(\n", + " TableKey=\"Load Case Definitions\", dataframe=False\n", + ") # Get Table data in `list[dict]` format\n", + "df = tables.get(\n", + " \"Material Properties 01 - General\"\n", + ") # Get Table data in pandas dataframe\n", "\n", "# Update Table\n", - "df.iloc[0,0] = 'New Value'\n", - "tables.update(TableKey='Material Properties 01 - General', data=df, apply=True)" + "df.iloc[0, 0] = \"New Value\"\n", + "tables.update(TableKey=\"Material Properties 01 - General\", data=df, apply=True)" ] }, { @@ -298,20 +304,21 @@ "outputs": [], "source": [ "pattern = sap.Load.Pattern\n", - "len(pattern) # List the number of load patterns defined\n", - "pattern.list_all() #List defined load patterns\n", - "pattern.rename('Dead', 'Live') #Rename previously defined pattern\n", - "pattern.delete(name='Dead') #Delete a load pattern\n", + "len(pattern) # List the number of load patterns defined\n", + "pattern.list_all() # List defined load patterns\n", + "pattern.rename(\"Dead\", \"Live\") # Rename previously defined pattern\n", + "pattern.delete(name=\"Dead\") # Delete a load pattern\n", "\n", - "pattern.get_selfwt_multiplier('DEAD') #Get defined self weight multiplier\n", - "pattern.set_selfwt_multiplier('DEAD', 1.15) #Set self weight multiplier\n", + "pattern.get_selfwt_multiplier(\"DEAD\") # Get defined self weight multiplier\n", + "pattern.set_selfwt_multiplier(\"DEAD\", 1.15) # Set self weight multiplier\n", "\n", - "pattern.get_loadtype('DEAD') #Get the defined load type\n", - "pattern.set_loadtype('DEAD', pattern_type='LIVE') #Set the defined load type\n", + "pattern.get_loadtype(\"DEAD\") # Get the defined load type\n", + "pattern.set_loadtype(\"DEAD\", pattern_type=\"LIVE\") # Set the defined load type\n", "\n", - "#Add a Live load case with name \"Custom Live\", a 1.15x self weight multiplier and also generate an accompanying load case\n", - "pattern.add(name='Custom Live', pattern_type='LIVE', \n", - " selfwt_multiplier=1.15, add_case=True)" + "# Add a Live load case with name \"Custom Live\", a 1.15x self weight multiplier and also generate an accompanying load case\n", + "pattern.add(\n", + " name=\"Custom Live\", pattern_type=\"LIVE\", selfwt_multiplier=1.15, add_case=True\n", + ")" ] }, { @@ -328,12 +335,14 @@ "outputs": [], "source": [ "cases = sap.Load.Case\n", - "len(cases) #returns total # of defined cases\n", - "cases.total(casetype='MODAL') #Get # of modal load cases\n", - "cases.list_all() #List all load cases\n", - "cases.rename('DEAD','WATER') #Rename existing load case\n", - "cases.case_info(name='DEAD') #Get the Case type information\n", - "cases.set_type(name='DEAD', casetype='LINEAR_STATIC') #Change the case type of existing load case" + "len(cases) # returns total # of defined cases\n", + "cases.total(casetype=\"MODAL\") # Get # of modal load cases\n", + "cases.list_all() # List all load cases\n", + "cases.rename(\"DEAD\", \"WATER\") # Rename existing load case\n", + "cases.case_info(name=\"DEAD\") # Get the Case type information\n", + "cases.set_type(\n", + " name=\"DEAD\", casetype=\"LINEAR_STATIC\"\n", + ") # Change the case type of existing load case" ] }, { @@ -359,25 +368,27 @@ "outputs": [], "source": [ "eigen = sap.Load.Modal.Eigen\n", - "eigen.set_case(case_name=\"LCASE1\") #Set a Eigen Modal case\n", + "eigen.set_case(case_name=\"LCASE1\") # Set a Eigen Modal case\n", "\n", - "eigen.set_initial_case(case_name='LCASE1', initial_case='DEAD') #Set initial stiffness case\n", - "eigen.get_initial_case(case_name=\"LCASE1\") #Get the Initial Case\n", + "eigen.set_initial_case(\n", + " case_name=\"LCASE1\", initial_case=\"DEAD\"\n", + ") # Set initial stiffness case\n", + "eigen.get_initial_case(case_name=\"LCASE1\") # Get the Initial Case\n", "\n", - "eigen.get_loads(case_name='LCASE1') #Get the load data\n", + "eigen.get_loads(case_name=\"LCASE1\") # Get the load data\n", "\n", - "#Set Eigen parameters\n", + "# Set Eigen parameters\n", "eigen.set_parameters(\n", - " case_name='LCASE1',\n", - " EigenShiftFreq=0.05, #cyc/s\n", - " EigenCutOff=0.0001, #cyc/s\n", + " case_name=\"LCASE1\",\n", + " EigenShiftFreq=0.05, # cyc/s\n", + " EigenCutOff=0.0001, # cyc/s\n", " EigenTolerance=0.00000001,\n", - " AllowAutoFreqShift=True\n", + " AllowAutoFreqShift=True,\n", ")\n", - "eigen.get_parameters(case_name='LCASE1') #Get Parameters\n", + "eigen.get_parameters(case_name=\"LCASE1\") # Get Parameters\n", "\n", - "eigen.set_number_modes(case_name='LCASE1', max=10, min=5) #set number of modes\n", - "eigen.get_number_modes(case_name='LCASE1') #get number of modes" + "eigen.set_number_modes(case_name=\"LCASE1\", max=10, min=5) # set number of modes\n", + "eigen.get_number_modes(case_name=\"LCASE1\") # get number of modes" ] }, { @@ -394,15 +405,17 @@ "outputs": [], "source": [ "ritz = sap.Load.Modal.Ritz\n", - "ritz.set_case(case_name=\"LCASE1\") #Set a Eigen Modal case\n", + "ritz.set_case(case_name=\"LCASE1\") # Set a Eigen Modal case\n", "\n", - "ritz.set_initial_case(case_name='LCASE1', initial_case='DEAD') #Set initial stiffness case\n", - "ritz.get_initial_case(case_name=\"LCASE1\") #Get the Initial Case\n", + "ritz.set_initial_case(\n", + " case_name=\"LCASE1\", initial_case=\"DEAD\"\n", + ") # Set initial stiffness case\n", + "ritz.get_initial_case(case_name=\"LCASE1\") # Get the Initial Case\n", "\n", - "ritz.get_loads(case_name='LCASE1') #Get the load data\n", + "ritz.get_loads(case_name=\"LCASE1\") # Get the load data\n", "\n", - "ritz.set_number_modes(case_name='LCASE1', max=10, min=5) #set number of modes\n", - "ritz.get_number_modes(case_name='LCASE1') #get number of modes" + "ritz.set_number_modes(case_name=\"LCASE1\", max=10, min=5) # set number of modes\n", + "ritz.get_number_modes(case_name=\"LCASE1\") # get number of modes" ] }, { @@ -419,20 +432,17 @@ "outputs": [], "source": [ "analyze = sap.Analyze\n", - "analyze.create_model() #Create analysis model\n", - "analyze.run() #Runs the analysis\n", - "analyze.case_status() #retrieves the status for all load cases.\n", - "analyze.get_run_flag() #retrieves the run flags for all cases\n", - "analyze.set_run_flag(case='MODAL', status=True) # Set case to run\n", - "analyze.get_solver() #Get solver info\n", - "\n", - "#Set solver options\n", + "analyze.create_model() # Create analysis model\n", + "analyze.run() # Runs the analysis\n", + "analyze.case_status() # retrieves the status for all load cases.\n", + "analyze.get_run_flag() # retrieves the run flags for all cases\n", + "analyze.set_run_flag(case=\"MODAL\", status=True) # Set case to run\n", + "analyze.get_solver() # Get solver info\n", + "\n", + "# Set solver options\n", "analyze.set_solver(\n", - " SolverType='Standard',\n", - " SolverProcessType='Auto',\n", - " NumberParallelRuns=0,\n", - " StiffCase=''\n", - ") " + " SolverType=\"Standard\", SolverProcessType=\"Auto\", NumberParallelRuns=0, StiffCase=\"\"\n", + ")" ] }, { @@ -453,21 +463,27 @@ "results = sap.Results\n", "\n", "setup = sap.Results.Setup\n", - "setup.clear_casecombo() #Deselect all Case&Combo for results\n", - "setup.select_case(casename='DEAD') #sets an load case selected for output flag.\n", - "setup.is_selected_case(casename='DEAD') #checks if an load case is selected for output.\n", - "setup.select_combo(comboname='DEAD') #sets an load combo selected for output flag.\n", - "setup.is_selected_combo(comboname='COMB1') #checks if an load combo is selected for output.\n", - "setup.set_rxn_loc_get(x=0.5, y=0.5, z=5) #sets coordinates of the locn at which the base reactions are reported. \n", - "setup.base_rxn_loc_get() #retrieves coordinates of the locn at which the base reactions are reported.\n", - "\n", - "results.joint_reactions(jointname='1') #Get Joint reactions as list of dict\n", - "results.joint_displacements(jointname='1') #Get Joint displacements as list of dict\n", - "results.joint_accelerations(jointname='1') #Get joint accelerations\n", - "results.joint_velocities(jointname='1') #Get joint velocities\n", - "\n", - "results.delete('MODAL') #Delete results of `MODAL` case\n", - "results.delete('All') #Delete results of all cases" + "setup.clear_casecombo() # Deselect all Case&Combo for results\n", + "setup.select_case(casename=\"DEAD\") # sets an load case selected for output flag.\n", + "setup.is_selected_case(\n", + " casename=\"DEAD\"\n", + ") # checks if an load case is selected for output.\n", + "setup.select_combo(comboname=\"DEAD\") # sets an load combo selected for output flag.\n", + "setup.is_selected_combo(\n", + " comboname=\"COMB1\"\n", + ") # checks if an load combo is selected for output.\n", + "setup.set_rxn_loc_get(\n", + " x=0.5, y=0.5, z=5\n", + ") # sets coordinates of the locn at which the base reactions are reported.\n", + "setup.base_rxn_loc_get() # retrieves coordinates of the locn at which the base reactions are reported.\n", + "\n", + "results.joint_reactions(jointname=\"1\") # Get Joint reactions as list of dict\n", + "results.joint_displacements(jointname=\"1\") # Get Joint displacements as list of dict\n", + "results.joint_accelerations(jointname=\"1\") # Get joint accelerations\n", + "results.joint_velocities(jointname=\"1\") # Get joint velocities\n", + "\n", + "results.delete(\"MODAL\") # Delete results of `MODAL` case\n", + "results.delete(\"All\") # Delete results of all cases" ] }, { @@ -484,14 +500,16 @@ "outputs": [], "source": [ "material = sap.Material\n", - "material.rename(old=\"4000Psi\", new=\"MatConc\") #Rename existing material\n", - "material.total() #Total # of defined material properties\n", - "material.delete(name='4000Psi') #Delete existing material property\n", - "material.list_all() #List all defined Material Properties\n", - "material.get_props(name='4000Psi') #Returns basic material property data\n", - "material.add(name='Steel', material_type='Steel') #Initialze Material Property\n", - "material.set_isotropic(name='Steel', E=29500, poisson=0.25, thermal_coeff=6e-06) #Set isotropic material properties\n", - "material.set_density(name='Steel', mass_per_vol=0.00029) #set density" + "material.rename(old=\"4000Psi\", new=\"MatConc\") # Rename existing material\n", + "material.total() # Total # of defined material properties\n", + "material.delete(name=\"4000Psi\") # Delete existing material property\n", + "material.list_all() # List all defined Material Properties\n", + "material.get_props(name=\"4000Psi\") # Returns basic material property data\n", + "material.add(name=\"Steel\", material_type=\"Steel\") # Initialze Material Property\n", + "material.set_isotropic(\n", + " name=\"Steel\", E=29500, poisson=0.25, thermal_coeff=6e-06\n", + ") # Set isotropic material properties\n", + "material.set_density(name=\"Steel\", mass_per_vol=0.00029) # set density" ] }, { @@ -508,12 +526,12 @@ "outputs": [], "source": [ "rebar = sap.Material.Rebar\n", - "rebar.rename(old='R1', new='MyRebar') #Rename rebar\n", - "rebar.total() #Total # of defined rebar properties\n", - "rebar.delete(name='R1') #Delete existing rebar property\n", - "rebar.list_all() #List all defined rebar Properties\n", - "rebar.set_prop(name='MyRebar2', area=1.05, dia=1.0) #Define a rebar property\n", - "rebar.get_prop(name='MyRebar2') #Get rebar property" + "rebar.rename(old=\"R1\", new=\"MyRebar\") # Rename rebar\n", + "rebar.total() # Total # of defined rebar properties\n", + "rebar.delete(name=\"R1\") # Delete existing rebar property\n", + "rebar.list_all() # List all defined rebar Properties\n", + "rebar.set_prop(name=\"MyRebar2\", area=1.05, dia=1.0) # Define a rebar property\n", + "rebar.get_prop(name=\"MyRebar2\") # Get rebar property" ] } ], diff --git a/pages/2_Tables.py b/pages/2_Tables.py index 7f7e103..ff6ed75 100644 --- a/pages/2_Tables.py +++ b/pages/2_Tables.py @@ -3,19 +3,19 @@ from ak_sap import Sap2000Wrapper from ak_sap.gui.streamlit import st_initialize -st.write('## Tables') +st.write("## Tables") st_initialize() -if not st.session_state.get('attached'): - st.warning('[Attach to existing](/) SAP model first to use this tab') +if not st.session_state.get("attached"): + st.warning("[Attach to existing](/) SAP model first to use this tab") st.stop() -sap:Sap2000Wrapper = st.session_state['SAP'] +sap: Sap2000Wrapper = st.session_state["SAP"] st.divider() -with st.expander('Tables Tables'): - _all = st.checkbox('Show All') +with st.expander("Tables Tables"): + _all = st.checkbox("Show All") if _all: st.table(sap.Table.list_all()) else: st.table(sap.Table.list_available()) -st.divider() \ No newline at end of file +st.divider() diff --git a/pages/Export/hilti_export.py b/pages/Export/hilti_export.py index 4c44890..68cb259 100644 --- a/pages/Export/hilti_export.py +++ b/pages/Export/hilti_export.py @@ -1,74 +1,90 @@ -from hilti_profis import PE -import streamlit as st - -from datetime import datetime import os import tempfile +from datetime import datetime + +import streamlit as st +from hilti_profis import PE from ak_sap import Sap2000Wrapper + def main(): - sap:Sap2000Wrapper = st.session_state['SAP'] + sap: Sap2000Wrapper = st.session_state["SAP"] _steps = """ Steps to follow: 1. Run the Analysis on SAP2000. 2. Select the frame and attached support for export in the 3D model. 3. Click the `Extract Values` button below. """ - st.info(_steps, icon='ℹ️') - - if st.session_state.get('_hilti_values_extracted') is None: - st.session_state['_hilti_values_extracted'] = False - + st.info(_steps, icon="ℹ️") + + if st.session_state.get("_hilti_values_extracted") is None: + st.session_state["_hilti_values_extracted"] = False + def _hilti_extract_values(): try: - st.session_state['_hilti_values_extracted'] = sap.Object.Point.selected().__next__() + st.session_state["_hilti_values_extracted"] = ( + sap.Object.Point.selected().__next__() + ) except StopIteration: - st.session_state['_hilti_values_extracted'] = None - st.warning('Make sure the node is selected.') - - st.button('Extract Values', on_click=_hilti_extract_values) - + st.session_state["_hilti_values_extracted"] = None + st.warning("Make sure the node is selected.") + + st.button("Extract Values", on_click=_hilti_extract_values) + @st.cache_data def load_hilti_class(basefile): return PE(basefile=basefile) - - if st.session_state['_hilti_values_extracted']: + + if st.session_state["_hilti_values_extracted"]: try: - selected_section = sap.Object.Frame.get_section(frame_name=sap.Object.Frame.selected().__next__()) + selected_section = sap.Object.Frame.get_section( + frame_name=sap.Object.Frame.selected().__next__() + ) except StopIteration: selected_section = None st.divider() - st.markdown('##### Selections') + st.markdown("##### Selections") _lcases = sap.Load.Case.list_all() _lcombos = sap.Load.Combo.list_all() - + col1, col2, col3 = st.columns(3) - cases = col1.multiselect(label='Load Cases for Export', default=_lcases, options=_lcases) - combos = col2.multiselect(label='Load Combos for Export', default=_lcombos, options=_lcombos) - #col3.write(f'##### Selected Section: \n###### {selected_section}') - col3.table(data = {'Selected Section':selected_section, 'Selected Node #':st.session_state['_hilti_values_extracted']}) - - col1, col2 = st.columns([3,1]) + cases = col1.multiselect( + label="Load Cases for Export", default=_lcases, options=_lcases + ) + combos = col2.multiselect( + label="Load Combos for Export", default=_lcombos, options=_lcombos + ) + # col3.write(f'##### Selected Section: \n###### {selected_section}') + col3.table( + data={ + "Selected Section": selected_section, + "Selected Node #": st.session_state["_hilti_values_extracted"], + } + ) + + col1, col2 = st.columns([3, 1]) uploaded_file = col2.file_uploader( - label = 'Upload a base `.pe` file (Optional)', + label="Upload a base `.pe` file (Optional)", accept_multiple_files=False, - help='You can optionally provide a `.pe` file as reference. All other design values will be imported from supplied file', - key = 'pe_basefile', - type='pe' + help="You can optionally provide a `.pe` file as reference. All other design values will be imported from supplied file", + key="pe_basefile", + type="pe", ) - + col1, col2, col3 = col1.columns(3) - _axis = [1,2,3] - x_axis = col2.selectbox(label='X-axis', options=_axis, index=0) - y_axis = col3.selectbox(label='Y-axis', options=_axis, index=1) - z_axis = col1.selectbox(label='Z-axis', options=_axis, index=2) + _axis = [1, 2, 3] + x_axis = col2.selectbox(label="X-axis", options=_axis, index=0) + y_axis = col3.selectbox(label="Y-axis", options=_axis, index=1) + z_axis = col1.selectbox(label="Z-axis", options=_axis, index=2) def generate_pe() -> str: - sap:Sap2000Wrapper = st.session_state['SAP'] + sap: Sap2000Wrapper = st.session_state["SAP"] if not x_axis != y_axis != z_axis: - st.error('^ Make sure X, Y, Z axis are mutually exclusive from each other') + st.error( + "^ Make sure X, Y, Z axis are mutually exclusive from each other" + ) if uploaded_file is not None: basefile = os.path.join(tempfile.mkdtemp(), uploaded_file.name) with open(basefile, "wb") as f: @@ -76,22 +92,24 @@ def generate_pe() -> str: else: basefile = None anchor = load_hilti_class(basefile=basefile) - + sap.Results.Setup.clear_casecombo() - + for case in cases: sap.Results.Setup.select_case(casename=case) - + for combo in combos: sap.Results.Setup.select_combo(comboname=combo) - + _current_units = sap.Model.units sap.Model.set_units(value="N_mm_C") - - #Delete Existing Load Combinations - anchor.Model.Loads.Combos.data['LoadCombinationEntity'] = None - - for rxn in sap.Results.joint_reactions(jointname=st.session_state['_hilti_values_extracted']): + + # Delete Existing Load Combinations + anchor.Model.Loads.Combos.data["LoadCombinationEntity"] = None + + for rxn in sap.Results.joint_reactions( + jointname=st.session_state["_hilti_values_extracted"] + ): anchor.Model.Loads.Combos.add( Fx=-rxn[f"F{x_axis}"], Fy=-rxn[f"F{y_axis}"], @@ -99,25 +117,25 @@ def generate_pe() -> str: Mx=-rxn[f"M{x_axis}"], My=-rxn[f"M{y_axis}"], Mz=-rxn[f"M{z_axis}"], - LoadType='Seismic', - Comment=rxn["LoadCase"] + LoadType="Seismic", + Comment=rxn["LoadCase"], ) sap.Model.set_units(value=_current_units) - + anchor.Model.apply() - _xml=anchor.xml_content() + _xml = anchor.xml_content() assert isinstance(_xml, str) - return anchor.xml_content() # type: ignore - + return anchor.xml_content() # type: ignore + st.divider() - + # Todo # Defer the `generate_pe` function run until the button is clicked. # Currently on [streamlit roadmap](https://roadmap.streamlit.app) for May-July ("Deferred data load for st.download_button") st.download_button( - label='Export `.pe` file', + label="Export `.pe` file", data=generate_pe(), - file_name=f"{sap.Model.filepath.stem}-{st.session_state['_hilti_values_extracted']}{'-'+selected_section if selected_section else ''}-AK-{datetime.now():%m%d_%H%M}.pe", - type='primary', - mime = 'text/plain' + file_name=f"{sap.Model.filepath.stem}-{st.session_state['_hilti_values_extracted']}{'-' + selected_section if selected_section else ''}-AK-{datetime.now():%m%d_%H%M}.pe", + type="primary", + mime="text/plain", ) diff --git a/pyproject.toml b/pyproject.toml index 35b99b8..b4bfea3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,15 +1,11 @@ -[build-system] -requires = ["flit_core >=3.2,<4"] -build-backend = "flit_core.buildapi" - [project] name = "ak_sap" +version = "0.0.1" requires-python = ">=3.12.0" authors = [{name = "Arun Kishore", email = "pypi@rpakishore.co.in"}] readme = "README.md" license = {file = "LICENSE"} classifiers = ["License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)"] -dynamic = ["version", "description"] dependencies = [ "comtypes>=1.4.8", "forallpeople>=2.7.1", @@ -31,6 +27,10 @@ update-doc="ak_sap.cli.update_doc:app" [tool.uv] default-groups = ["gui"] +package = true + +[tool.setuptools.dynamic] +description = {file = "README.md"} [dependency-groups] cli = [ @@ -41,6 +41,7 @@ dev = [ "ipykernel>=6.29.5", "ipywidgets>=8.1.5", "line-profiler>=4.2.0", + "ruff>=0.9.1", ] gui = [ "streamlit>=1.40.1", diff --git a/scripts/code_coverage.py b/scripts/code_coverage.py index 3374599..7410590 100644 --- a/scripts/code_coverage.py +++ b/scripts/code_coverage.py @@ -1,23 +1,34 @@ +import subprocess import tempfile -from pathlib import Path import webbrowser -import subprocess -import shutil +from pathlib import Path # Run Pytest Coverage Report code_coverage_path = Path(tempfile.gettempdir()) / "code_coverage_report" -cmd = [ - "uv", - "run", - "--group", - "test", - "pytest", - "--cov=ak_sap", - f"--cov-report=html:{code_coverage_path}", -] -print(" ".join(cmd)) -subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).wait() +def run_cmd(cmd: list[str]): + print(" ".join(cmd)) + subprocess.Popen( + cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE + ).wait() + + +run_cmd(cmd=["uv", "run", "ruff", "format"]) +run_cmd(cmd=["uv", "run", "ruff", "check", "--select", "I", "-e", "--fix"]) +run_cmd(cmd=["uv", "run", "ruff", "check", "--fix", ">&1"]) + +run_cmd( + cmd=[ + "uv", + "run", + "--group", + "test", + "pytest", + "--cov=template_python", + f"--cov-report=html:{code_coverage_path}", + ] +) +webbrowser.open(f"file://{code_coverage_path}/index.html") -webbrowser.open(f"file://{code_coverage_path}/index.html") \ No newline at end of file +run_cmd(cmd=["uv", "run", "--group", "test", "pytest"]) diff --git a/src/ak_sap/Analyze/main.py b/src/ak_sap/Analyze/main.py index 27af68e..7caaa29 100644 --- a/src/ak_sap/Analyze/main.py +++ b/src/ak_sap/Analyze/main.py @@ -1,6 +1,6 @@ from typing import Literal -from ak_sap.utils import MasterClass, log +from ak_sap.utils import MasterClass from ak_sap.utils.decorators import smooth_sap_do diff --git a/src/ak_sap/Database/tables.py b/src/ak_sap/Database/tables.py index c3deb09..e3a5f5d 100644 --- a/src/ak_sap/Database/tables.py +++ b/src/ak_sap/Database/tables.py @@ -197,9 +197,9 @@ def _array_to_pandas(headers: tuple, array: tuple) -> pd.DataFrame: """Given the table headers as tuple and table data as a single tuple; Returns table as a dataframe.""" num_fields = len(headers) - assert ( - len(array) % num_fields == 0 - ), f"Array length ({len(array)}) is not divisible by header length ({num_fields})" + assert len(array) % num_fields == 0, ( + f"Array length ({len(array)}) is not divisible by header length ({num_fields})" + ) df_data: dict[str, list] = {header: [] for header in headers} for array_idx, value in enumerate(array): @@ -212,9 +212,9 @@ def _array_to_list_of_dicts(headers: tuple, array: tuple) -> list[dict[str, Any] """Given the table headers as tuple and table data as a single tuple; Returns table as a list of dictionaries.""" num_fields = len(headers) - assert ( - len(array) % num_fields == 0 - ), f"Array length ({len(array)}) is not divisible by header length ({num_fields})" + assert len(array) % num_fields == 0, ( + f"Array length ({len(array)}) is not divisible by header length ({num_fields})" + ) list_of_dicts = [] for i in range(len(array) // num_fields): diff --git a/src/ak_sap/Loads/LoadCases.py b/src/ak_sap/Loads/LoadCases.py index f773f5b..76f661e 100644 --- a/src/ak_sap/Loads/LoadCases.py +++ b/src/ak_sap/Loads/LoadCases.py @@ -1,6 +1,6 @@ import typing -from ak_sap.utils import MasterClass, log +from ak_sap.utils import MasterClass from ak_sap.utils.decorators import smooth_sap_do from .constants import LoadCaseType, LoadPatternType @@ -33,9 +33,9 @@ def total(self, casetype: LoadCaseType | None = None): @smooth_sap_do def rename(self, old_name: str, new_name: str): """changes the name of an existing load case.""" - assert ( - old_name in self.list_all() - ), f'"{old_name}" is not in list of defined load cases {self.list_all()}' + assert old_name in self.list_all(), ( + f'"{old_name}" is not in list of defined load cases {self.list_all()}' + ) return self.__LoadCases.ChangeName(old_name, new_name) @smooth_sap_do @@ -46,9 +46,9 @@ def list_all(self) -> tuple[str]: @smooth_sap_do def delete(self, name: str): - assert ( - name in self.list_all() - ), f'"{name}" is not in list of defined load cases {self.list_all()}' + assert name in self.list_all(), ( + f'"{name}" is not in list of defined load cases {self.list_all()}' + ) return self.__LoadCases.Delete(name) @smooth_sap_do @@ -73,8 +73,8 @@ def case_info(self, name: str) -> dict: @smooth_sap_do def set_type(self, name: str, casetype: LoadCaseType): - assert ( - name in self.list_all() - ), f'"{name}" is not in list of defined load cases {self.list_all()}' + assert name in self.list_all(), ( + f'"{name}" is not in list of defined load cases {self.list_all()}' + ) _value = typing.get_args(LoadCaseType).index(casetype) + 1 return self.__LoadCases.SetDesignType(name, 1, _value) diff --git a/src/ak_sap/Loads/LoadCombos.py b/src/ak_sap/Loads/LoadCombos.py index c209465..b069271 100644 --- a/src/ak_sap/Loads/LoadCombos.py +++ b/src/ak_sap/Loads/LoadCombos.py @@ -1,4 +1,4 @@ -from ak_sap.utils import MasterClass, log +from ak_sap.utils import MasterClass from ak_sap.utils.decorators import smooth_sap_do diff --git a/src/ak_sap/Material/Materials/rebar.py b/src/ak_sap/Material/Materials/rebar.py index 35e561f..c4d7b75 100644 --- a/src/ak_sap/Material/Materials/rebar.py +++ b/src/ak_sap/Material/Materials/rebar.py @@ -1,4 +1,4 @@ -from ak_sap.utils import MasterClass, log +from ak_sap.utils import MasterClass from ak_sap.utils.decorators import smooth_sap_do diff --git a/src/ak_sap/Material/material.py b/src/ak_sap/Material/material.py index b074914..14f29d6 100644 --- a/src/ak_sap/Material/material.py +++ b/src/ak_sap/Material/material.py @@ -1,6 +1,6 @@ import typing -from ak_sap.utils import MasterClass, log +from ak_sap.utils import MasterClass from ak_sap.utils.decorators import smooth_sap_do from .constants import MaterialTypesStr, SymmetryTypeStr diff --git a/src/ak_sap/Object/frame.py b/src/ak_sap/Object/frame.py index 2debb99..ae6c76d 100644 --- a/src/ak_sap/Object/frame.py +++ b/src/ak_sap/Object/frame.py @@ -1,4 +1,3 @@ -from ak_sap.utils import log from ak_sap.utils.decorators import smooth_sap_do from .helper import MasterObj diff --git a/src/ak_sap/Object/helper.py b/src/ak_sap/Object/helper.py index d409cd9..2e33c3b 100644 --- a/src/ak_sap/Object/helper.py +++ b/src/ak_sap/Object/helper.py @@ -55,9 +55,9 @@ def rename(self, old_name: str, new_name: str): def check_obj_legal(self, name: str): """Confirms specified element exists in the model""" - assert ( - name in self.all() - ), f"`{name}` not found in the current list of elements: {self.all()}" + assert name in self.all(), ( + f"`{name}` not found in the current list of elements: {self.all()}" + ) @smooth_sap_do def delete(self, name: str): diff --git a/src/ak_sap/Object/point.py b/src/ak_sap/Object/point.py index 8e03116..bcd43f1 100644 --- a/src/ak_sap/Object/point.py +++ b/src/ak_sap/Object/point.py @@ -1,6 +1,5 @@ from typing import Literal -from ak_sap.utils import log from ak_sap.utils.decorators import smooth_sap_do from .helper import MasterObj diff --git a/src/ak_sap/Results/Setup.py b/src/ak_sap/Results/Setup.py index 58c92e9..71de38b 100644 --- a/src/ak_sap/Results/Setup.py +++ b/src/ak_sap/Results/Setup.py @@ -1,4 +1,4 @@ -from ak_sap.utils import MasterClass, log +from ak_sap.utils import MasterClass from ak_sap.utils.decorators import smooth_sap_do diff --git a/src/ak_sap/Results/main.py b/src/ak_sap/Results/main.py index 91bee3c..5481492 100644 --- a/src/ak_sap/Results/main.py +++ b/src/ak_sap/Results/main.py @@ -1,6 +1,6 @@ from typing import Literal -from ak_sap.utils import MasterClass, log +from ak_sap.utils import MasterClass from ak_sap.utils.decorators import smooth_sap_do from .Setup import ResultsSetup @@ -20,7 +20,9 @@ def delete(self, casename: str | Literal["All"]) -> bool: Args: casename (str | Literal['All']): name of an existing load case that is to have its results deleted. """ - return self.mySapObject.SapModel.Analyze.DeleteResykts(casename, casename.casefold() == "all") # type: ignore + return self.mySapObject.SapModel.Analyze.DeleteResykts( + casename, casename.casefold() == "all" + ) # type: ignore @smooth_sap_do def joint_reactions(self, jointname: str) -> list[dict]: diff --git a/src/ak_sap/Select/main.py b/src/ak_sap/Select/main.py index bda0379..7a79587 100644 --- a/src/ak_sap/Select/main.py +++ b/src/ak_sap/Select/main.py @@ -1,6 +1,6 @@ from typing import Literal -from ak_sap.utils import MasterClass, log +from ak_sap.utils import MasterClass from ak_sap.utils.decorators import smooth_sap_do diff --git a/src/ak_sap/__init__.py b/src/ak_sap/__init__.py index db7d590..904fbe3 100644 --- a/src/ak_sap/__init__.py +++ b/src/ak_sap/__init__.py @@ -1,6 +1,3 @@ -"Python wrapper for SAP2000 API" -__version__ = "0.0.4" - from ak_sap.misc import Coord from ak_sap.utils.logger import log from ak_sap.wrapper import Sap2000Wrapper diff --git a/src/ak_sap/cli/cli_app.py b/src/ak_sap/cli/cli_app.py index 4f1155c..a9f7956 100644 --- a/src/ak_sap/cli/cli_app.py +++ b/src/ak_sap/cli/cli_app.py @@ -1,6 +1,3 @@ -from pathlib import Path -from typing import Optional - import typer from rich import print diff --git a/src/ak_sap/cli/update_doc.py b/src/ak_sap/cli/update_doc.py index ffffdd7..5569a5d 100644 --- a/src/ak_sap/cli/update_doc.py +++ b/src/ak_sap/cli/update_doc.py @@ -1,6 +1,5 @@ import json from pathlib import Path -from typing import Optional import typer diff --git a/src/ak_sap/gui/streamlit/config.py b/src/ak_sap/gui/streamlit/config.py index 6e67f6a..62a226e 100644 --- a/src/ak_sap/gui/streamlit/config.py +++ b/src/ak_sap/gui/streamlit/config.py @@ -1,5 +1,4 @@ import streamlit as st - from ak_sap import Sap2000Wrapper, debug, log DEFAULT_SESSION_STATES = {"attached": False, "debug_mode": False, "SAP": None} diff --git a/src/ak_sap/utils/__init__.py b/src/ak_sap/utils/__init__.py index 08dd1fb..11b59bc 100644 --- a/src/ak_sap/utils/__init__.py +++ b/src/ak_sap/utils/__init__.py @@ -1,20 +1,23 @@ from .logger import log + class MasterClass: def __init__(self, mySapObject) -> None: self.mySapObject = mySapObject self.SapModel = self.mySapObject.SapModel - print(f'`{self.__class__.__name__}` instance initialized.') - + print(f"`{self.__class__.__name__}` instance initialized.") + def __str__(self) -> str: - return f'Instance of `Loads.Modal.{self.__class__.__name__}`. Holds collection of functions' - + return f"Instance of `Loads.Modal.{self.__class__.__name__}`. Holds collection of functions" + def __repr__(self) -> str: return self.__str__() - + def __del__(self) -> None: try: self.mySapObject = None self.SapModel = None except Exception as e: - log.warning(msg=f'Exception faced when deleting {self.__class__.__name__}\n{e}') \ No newline at end of file + log.warning( + msg=f"Exception faced when deleting {self.__class__.__name__}\n{e}" + ) diff --git a/src/ak_sap/utils/logger.py b/src/ak_sap/utils/logger.py index 27092ac..d2a7f1d 100644 --- a/src/ak_sap/utils/logger.py +++ b/src/ak_sap/utils/logger.py @@ -17,7 +17,7 @@ def __init__(self): self.logger.addHandler(streamhandler) log_dir: Path = Path(__file__).parent.parent.parent / "logs" log_dir.mkdir(exist_ok=True) - logfile = log_dir / f'{user}{time.strftime("-%Y-%b")}.log' + logfile = log_dir / f"{user}{time.strftime('-%Y-%b')}.log" self.logfile = logfile filehandler = logging.FileHandler(logfile, encoding="utf-8") filehandler.setFormatter(formatter) diff --git a/src/tests/Database/test_tables.py b/src/tests/Database/test_tables.py index d24869d..7fd360c 100644 --- a/src/tests/Database/test_tables.py +++ b/src/tests/Database/test_tables.py @@ -60,7 +60,6 @@ def test_array_to_list_of_dicts_invalid_length(): class TestFlattenDataFrame(unittest.TestCase): - def test_flatten_empty_dataframe(self): df = pd.DataFrame() result = flatten_dataframe(df) diff --git a/src/tests/utils/test_decorators.py b/src/tests/utils/test_decorators.py index d2fe697..a77476e 100644 --- a/src/tests/utils/test_decorators.py +++ b/src/tests/utils/test_decorators.py @@ -2,7 +2,6 @@ def test_smooth_sap_do(): - @smooth_sap_do def return_failed_list(): return [1, 2, 3, 1]