midas-civil 0.1.4__py3-none-any.whl → 0.1.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of midas-civil might be problematic. Click here for more details.

midas_civil/_node.py CHANGED
@@ -12,7 +12,10 @@ def dist_tol(a,b):
12
12
  def cell(point,size=1): #SIZE OF GRID
13
13
  return (int(point.X//size),int(point.Y//size),int(point.Z//size))
14
14
 
15
- #-- NEW SYSTEM
15
+
16
+ # -------- FUNCTIONS ARE DEFINED BELOW TO RECOGNISE NODE CLASS ----------------
17
+
18
+
16
19
 
17
20
  #5 Class to create nodes
18
21
  class Node:
@@ -48,9 +51,9 @@ class Node:
48
51
  node_count = max(Node.ids)+1
49
52
 
50
53
 
51
- self.X = x
52
- self.Y = y
53
- self.Z = z
54
+ self.X = round(x,6)
55
+ self.Y = round(y,6)
56
+ self.Z = round(z,6)
54
57
 
55
58
  if id == 0 : self.ID = node_count
56
59
  if id != 0 : self.ID = id
@@ -94,7 +97,9 @@ class Node:
94
97
  Node.ids.append(self.ID)
95
98
  Node.Grid[cell_loc].append(self)
96
99
 
97
- _add_node_2_stGroup(self.ID,group)
100
+ if group !="":
101
+ _add_node_2_stGroup(self.ID,group)
102
+
98
103
 
99
104
 
100
105
 
@@ -159,6 +164,16 @@ class Node:
159
164
 
160
165
 
161
166
 
167
+ # ---- GET NODE OBJECT FROM ID ----------
168
+
169
+ def nodeByID(nodeID:int) -> Node:
170
+ ''' Return Node object with the input ID '''
171
+ for node in Node.nodes:
172
+ if node.ID == nodeID:
173
+ return node
174
+
175
+ print(f'There is no node with ID {nodeID}')
176
+ return None
162
177
 
163
178
 
164
179
 
midas_civil/_result.py CHANGED
@@ -111,7 +111,7 @@ class LoadCombination:
111
111
  @classmethod
112
112
  def create(cls, classification = "All"):
113
113
  if len(LoadCombination.data) == 0:
114
- print("No Load Combinations defined! Define the load combination using the 'LoadCombination' class before creating these in the model.")
114
+ # print("No Load Combinations defined! Define the load combination using the 'LoadCombination' class before creating these in the model.")
115
115
  return
116
116
  if classification not in LoadCombination.valid:
117
117
  print(f'"{classification}" is not a valid input. It is changed to "General".')
@@ -142,13 +142,13 @@ class LoadCombination:
142
142
 
143
143
  @classmethod
144
144
  def delete(cls, classification = "All", ids = []):
145
- json = LoadCombination.call_json(classification)
145
+ json = LoadCombination.json(classification)
146
146
  a = ""
147
147
  for i in range(len(ids)):
148
148
  a += str(ids[i]) + ","
149
149
  a = "/" + a[:-1]
150
150
  if json == {}:
151
- print("No load combinations are defined to delete. Def")
151
+ print("No load combinations are defined to delete.")
152
152
  for i in list(json.keys()):
153
153
  MidasAPI("DELETE",LoadCombination.com_map.get(i) + a)
154
154
  #---------------------------------------------------------------------------------------------------------------
@@ -2,6 +2,7 @@ import polars as pl
2
2
  import json
3
3
  import xlsxwriter
4
4
  from ._mapi import *
5
+ from ._model import *
5
6
  # js_file = open('JSON_Excel Parsing\\test.json','r')
6
7
 
7
8
  # print(js_file)
@@ -125,7 +126,7 @@ class Result :
125
126
 
126
127
  # ---------- User defined TABLE (Dynamic Report Table) ------------------------------
127
128
  @staticmethod
128
- def UserDefinedTable(tableName:str, summary=0):
129
+ def UserDefinedTable(tableName:str, summary=0, force_unit='KN',len_unit='M'):
129
130
  js_dat = {
130
131
  "Argument": {
131
132
  "TABLE_NAME": tableName,
@@ -135,11 +136,11 @@ class Result :
135
136
  }
136
137
  }
137
138
  }
138
-
139
+ Model.units(force=force_unit,length=len_unit)
139
140
  ss_json = MidasAPI("POST","/post/TABLE",js_dat)
140
141
  return _JSToDF_UserDefined(tableName,ss_json,summary)
141
142
 
142
- # ---------- Result TABLE ------------------------------
143
+ # ---------- LIST ALL USER DEFINED TABLE ------------------------------
143
144
  @staticmethod
144
145
  def UserDefinedTables_print():
145
146
  ''' Print all the User defined table names '''
@@ -158,18 +159,17 @@ class Result :
158
159
 
159
160
  # ---------- Result TABLE ------------------------------
160
161
  @staticmethod
161
- def ResultTable(tabletype:str,elements:list=[],loadcase:list=[],cs_stage=[],force_unit='kN',len_unit='m'):
162
+ def ResultTable(tabletype:str,keys=[],loadcase:list=[],cs_stage=[],force_unit='KN',len_unit='M'):
162
163
  '''
163
164
  TableType : REACTIONG | REACTIONL | DISPLACEMENTG | DISPLACEMENTL | TRUSSFORCE | TRUSSSTRESS
165
+ Keys : List{int} -> Element/ Node IDs | str -> Structure Group Name
166
+ Loadcase : Loadcase name followed by type. eg. DeadLoad(ST)
164
167
  '''
168
+
165
169
  js_dat = {
166
170
  "Argument": {
167
171
  "TABLE_NAME": "SS_Table",
168
172
  "TABLE_TYPE": tabletype,
169
- "UNIT": {
170
- "FORCE": force_unit,
171
- "DIST": len_unit
172
- },
173
173
  "STYLES": {
174
174
  "FORMAT": "Fixed",
175
175
  "PLACE": 12
@@ -185,9 +185,17 @@ class Result :
185
185
  js_dat["Argument"]['STAGE_STEP'] = cs_stage
186
186
 
187
187
 
188
- if elements!=[]: js_dat["Argument"]['NODE_ELEMS'] = {"KEYS": elements}
188
+ if isinstance(keys,list):
189
+ if keys!=[]:
190
+ js_dat["Argument"]['NODE_ELEMS'] = {"KEYS": keys}
191
+ elif isinstance(keys,str):
192
+ js_dat["Argument"]['NODE_ELEMS'] = {"STRUCTURE_GROUP_NAME": keys}
193
+
194
+
189
195
  if loadcase!=[]: js_dat["Argument"]['LOAD_CASE_NAMES'] = loadcase
190
196
 
197
+
198
+ Model.units(force=force_unit,length=len_unit)
191
199
  ss_json = MidasAPI("POST","/post/table",js_dat)
192
200
  return _JSToDF_ResTable(ss_json)
193
201
 
midas_civil/_section.py CHANGED
@@ -732,8 +732,142 @@ class Section:
732
732
  _SectionADD(self)
733
733
 
734
734
 
735
+ #=======================================================Tapered Group===========================================
735
736
 
736
-
737
+ class TaperedGroup:
738
+
739
+ data = []
740
+
741
+ def __init__(self, name, elem_list, z_var, y_var, z_exp=None, z_from=None, z_dist=None,
742
+ y_exp=None, y_from=None, y_dist=None, id=""):
743
+ """
744
+ Args:
745
+ name (str): Tapered Group Name (Required).
746
+ elem_list (list): List of element numbers (Required).
747
+ z_var (str): Section shape variation for Z-axis: "LINEAR" or "POLY" (Required).
748
+ y_var (str): Section shape variation for Y-axis: "LINEAR" or "POLY" (Required).
749
+ z_exp (float, optional): Z-axis exponent. Required if z_var is "POLY".
750
+ z_from (str, optional): Z-axis symmetric plane ("i" or "j"). Defaults to "i" for "POLY".
751
+ z_dist (float, optional): Z-axis symmetric plane distance. Defaults to 0 for "POLY".
752
+ y_exp (float, optional): Y-axis exponent. Required if y_var is "POLY".
753
+ y_from (str, optional): Y-axis symmetric plane ("i" or "j"). Defaults to "i" for "POLY".
754
+ y_dist (float, optional): Y-axis symmetric plane distance. Defaults to 0 for "POLY".
755
+ id (str, optional): ID for the tapered group. Auto-generated if not provided.
737
756
 
738
-
739
-
757
+ Example:
758
+ Section.TapperGroup("Linear", [1, 2, 3], "LINEAR", "LINEAR")
759
+ Section.TapperGroup("ZPoly", [4, 5], "POLY", "LINEAR", z_exp=2.5)
760
+ """
761
+ self.NAME = name
762
+ self.ELEM_LIST = elem_list
763
+ self.Z_VAR = z_var
764
+ self.Y_VAR = y_var
765
+
766
+ # Z-axis parameters (only for POLY)
767
+ if z_var == "POLY":
768
+ if z_exp is None:
769
+ raise ValueError("z_exp is required when z_var is 'POLY'")
770
+ self.Z_EXP = z_exp
771
+ self.Z_FROM = z_from if z_from is not None else "i"
772
+ self.Z_DIST = z_dist if z_dist is not None else 0
773
+ else:
774
+ self.Z_EXP = None
775
+ self.Z_FROM = None
776
+ self.Z_DIST = None
777
+
778
+ # Y-axis parameters (only for POLY)
779
+ if y_var == "POLY":
780
+ if y_exp is None:
781
+ raise ValueError("y_exp is required when y_var is 'POLY'")
782
+ self.Y_EXP = y_exp
783
+ self.Y_FROM = y_from if y_from is not None else "i"
784
+ self.Y_DIST = y_dist if y_dist is not None else 0
785
+ else:
786
+ self.Y_EXP = None
787
+ self.Y_FROM = None
788
+ self.Y_DIST = None
789
+
790
+ if id == "":
791
+ id = len(Section.TaperedGroup.data) + 1
792
+ self.ID = id
793
+
794
+ Section.TaperedGroup.data.append(self)
795
+
796
+ @classmethod
797
+ def json(cls):
798
+ json_data = {"Assign": {}}
799
+ for i in cls.data:
800
+ # Base data that's always included
801
+ tapper_data = {
802
+ "NAME": i.NAME,
803
+ "ELEMLIST": i.ELEM_LIST,
804
+ "ZVAR": i.Z_VAR,
805
+ "YVAR": i.Y_VAR
806
+ }
807
+
808
+ # Add Z-axis polynomial parameters only if Z_VAR is "POLY"
809
+ if i.Z_VAR == "POLY":
810
+ tapper_data["ZEXP"] = i.Z_EXP
811
+ tapper_data["ZFROM"] = i.Z_FROM
812
+ tapper_data["ZDIST"] = i.Z_DIST
813
+
814
+ # Add Y-axis polynomial parameters only if Y_VAR is "POLY"
815
+ if i.Y_VAR == "POLY":
816
+ tapper_data["YEXP"] = i.Y_EXP
817
+ tapper_data["YFROM"] = i.Y_FROM
818
+ tapper_data["YDIST"] = i.Y_DIST
819
+
820
+ json_data["Assign"][str(i.ID)] = tapper_data
821
+
822
+ return json_data
823
+
824
+ @classmethod
825
+ def create(cls):
826
+ MidasAPI("PUT", "/db/tsgr", cls.json())
827
+
828
+ @classmethod
829
+ def get(cls):
830
+ return MidasAPI("GET", "/db/tsgr")
831
+
832
+ @classmethod
833
+ def delete(cls):
834
+ cls.data = []
835
+ return MidasAPI("DELETE", "/db/tsgr")
836
+
837
+ @classmethod
838
+ def sync(cls):
839
+ cls.data = []
840
+ response = cls.get()
841
+
842
+ if response and response != {'message': ''}:
843
+ tsgr_data = response.get('TSGR', {})
844
+ # Iterate through the dictionary of tapered groups from the API response
845
+ for tsgr_id, item_data in tsgr_data.items():
846
+ # Extract base parameters
847
+ name = item_data.get('NAME')
848
+ elem_list = item_data.get('ELEMLIST')
849
+ z_var = item_data.get('ZVAR')
850
+ y_var = item_data.get('YVAR')
851
+
852
+ # Extract optional parameters based on variation type
853
+ z_exp = item_data.get('ZEXP') if z_var == "POLY" else None
854
+ z_from = item_data.get('ZFROM') if z_var == "POLY" else None
855
+ z_dist = item_data.get('ZDIST') if z_var == "POLY" else None
856
+
857
+ y_exp = item_data.get('YEXP') if y_var == "POLY" else None
858
+ y_from = item_data.get('YFROM') if y_var == "POLY" else None
859
+ y_dist = item_data.get('YDIST') if y_var == "POLY" else None
860
+
861
+ Section.TaperedGroup(
862
+ name=name,
863
+ elem_list=elem_list,
864
+ z_var=z_var,
865
+ y_var=y_var,
866
+ z_exp=z_exp,
867
+ z_from=z_from,
868
+ z_dist=z_dist,
869
+ y_exp=y_exp,
870
+ y_from=y_from,
871
+ y_dist=y_dist,
872
+ id=tsgr_id
873
+ )
@@ -0,0 +1,160 @@
1
+ from ._mapi import *
2
+
3
+ class Settlement:
4
+
5
+ @classmethod
6
+ def create(cls):
7
+ """Creates Settlement Load in MIDAS Civil NX"""
8
+ if cls.Group.data != []: cls.Group.create()
9
+ if cls.Case.data != []: cls.Case.create()
10
+
11
+ @classmethod
12
+ def delete(cls):
13
+ """Deletes Settlement load from MIDAS Civil NX and Python"""
14
+ cls.Group.delete()
15
+ cls.Case.delete()
16
+
17
+ @classmethod
18
+ def sync(cls):
19
+ """Sync Settlement load from MIDAS Civil NX to Python"""
20
+ cls.Group.sync()
21
+ cls.Case.sync()
22
+
23
+ class Group:
24
+ """
25
+ Parameters:
26
+ name: Settlement group name (string)
27
+ displacement: Settlement displacement value (number)
28
+ node_list: List of node IDs to include in the group (array of integers)
29
+ id: Group ID (optional, auto-generated if not provided)
30
+
31
+ Examples:
32
+ ```python
33
+ Settlement.Group("SG1", 0.025, [100, 101])
34
+ Settlement.Group("SG2", 0.015, [102, 103])
35
+ ```
36
+ """
37
+ data = []
38
+
39
+ def __init__(self, name, displacement, node_list, id=""):
40
+ self.NAME = name
41
+ self.SETTLE = displacement
42
+ self.ITEMS = node_list
43
+ if id == "": id = len(Settlement.Group.data) + 1
44
+ self.ID = id
45
+
46
+ Settlement.Group.data.append(self)
47
+
48
+ @classmethod
49
+ def json(cls):
50
+ json = {"Assign": {}}
51
+ for i in cls.data:
52
+ json["Assign"][str(i.ID)] = {
53
+ "NAME": i.NAME,
54
+ "SETTLE": i.SETTLE,
55
+ "ITEMS": i.ITEMS
56
+ }
57
+ return json
58
+
59
+ @staticmethod
60
+ def create():
61
+ MidasAPI("PUT", "/db/smpt", Settlement.Group.json())
62
+
63
+ @staticmethod
64
+ def get():
65
+ return MidasAPI("GET", "/db/smpt")
66
+
67
+ @classmethod
68
+ def delete(cls):
69
+ cls.data = []
70
+ return MidasAPI("DELETE", "/db/smpt")
71
+
72
+ @classmethod
73
+ def sync(cls):
74
+ cls.data = []
75
+ a = cls.get()
76
+ if a != {'message': ''}:
77
+ for i in a['SMPT'].keys():
78
+ Settlement.Group(
79
+ a['SMPT'][i]['NAME'],
80
+ a['SMPT'][i]['SETTLE'],
81
+ a['SMPT'][i]['ITEMS'],
82
+ int(i)
83
+ )
84
+
85
+
86
+ class Case:
87
+ """
88
+
89
+ Parameters:
90
+ name: Settlement load case name (string)
91
+ settlement_groups: List of settlement group names to include (array of strings, default [])
92
+ factor: Settlement scale factor (number, default 1.0)
93
+ min_groups: Minimum number of settlement groups (integer, default 1)
94
+ max_groups: Maximum number of settlement groups (integer, default 1)
95
+ desc: Description of the settlement case (string, default "")
96
+ id: Case ID (optional, auto-generated if not provided)
97
+
98
+ Examples:
99
+ ```python
100
+ Settlement.Case("SMLC1", ["SG1"], 1.2, 1, 1, "Foundation Settlement Case")
101
+ Settlement.Case("SMLC2", ["SG1", "SG2"], 1.0, 1, 2, "Combined Settlement")
102
+ ```
103
+ """
104
+ data = []
105
+
106
+ def __init__(self, name, settlement_groups=[],factor=1.0, min_groups=1, max_groups=1, desc="", id=""):
107
+ self.NAME = name
108
+ self.DESC = desc
109
+ self.FACTOR = factor
110
+ self.MIN = min_groups
111
+ self.MAX = max_groups
112
+ self.ST_GROUPS = settlement_groups
113
+ if id == "": id = len(Settlement.Case.data) + 1
114
+ self.ID = id
115
+
116
+ Settlement.Case.data.append(self)
117
+
118
+ @classmethod
119
+ def json(cls):
120
+ json = {"Assign": {}}
121
+ for i in cls.data:
122
+ json["Assign"][str(i.ID)] = {
123
+ "NAME": i.NAME,
124
+ "DESC": i.DESC,
125
+ "FACTOR": i.FACTOR,
126
+ "MIN": i.MIN,
127
+ "MAX": i.MAX,
128
+ "ST_GROUPS": i.ST_GROUPS
129
+ }
130
+ return json
131
+
132
+ @staticmethod
133
+ def create():
134
+ MidasAPI("PUT", "/db/smlc", Settlement.Case.json())
135
+
136
+ @staticmethod
137
+ def get():
138
+ return MidasAPI("GET", "/db/smlc")
139
+
140
+ @classmethod
141
+ def delete(cls):
142
+ cls.data = []
143
+ return MidasAPI("DELETE", "/db/smlc")
144
+
145
+ @classmethod
146
+ def sync(cls):
147
+ cls.data = []
148
+ a = cls.get()
149
+ if a != {'message': ''}:
150
+ for i in a['SMLC'].keys():
151
+ Settlement.Case(
152
+ a['SMLC'][i]['NAME'],
153
+ a['SMLC'][i]['DESC'],
154
+ a['SMLC'][i]['FACTOR'],
155
+ a['SMLC'][i]['MIN'],
156
+ a['SMLC'][i]['MAX'],
157
+ a['SMLC'][i]['ST_GROUPS'],
158
+ int(i)
159
+ )
160
+