midas-civil 1.4.1__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.
Files changed (40) hide show
  1. midas_civil/_BoundaryChangeAssignment.py +278 -0
  2. midas_civil/__init__.py +51 -0
  3. midas_civil/_analysiscontrol.py +585 -0
  4. midas_civil/_boundary.py +888 -0
  5. midas_civil/_construction.py +1004 -0
  6. midas_civil/_element.py +1346 -0
  7. midas_civil/_group.py +337 -0
  8. midas_civil/_load.py +967 -0
  9. midas_civil/_loadcomb.py +159 -0
  10. midas_civil/_mapi.py +249 -0
  11. midas_civil/_material.py +1692 -0
  12. midas_civil/_model.py +522 -0
  13. midas_civil/_movingload.py +1479 -0
  14. midas_civil/_node.py +532 -0
  15. midas_civil/_result_table.py +929 -0
  16. midas_civil/_result_test.py +5455 -0
  17. midas_civil/_section/_TapdbSecSS.py +175 -0
  18. midas_civil/_section/__init__.py +413 -0
  19. midas_civil/_section/_compositeSS.py +283 -0
  20. midas_civil/_section/_dbSecSS.py +164 -0
  21. midas_civil/_section/_offsetSS.py +53 -0
  22. midas_civil/_section/_pscSS copy.py +455 -0
  23. midas_civil/_section/_pscSS.py +822 -0
  24. midas_civil/_section/_tapPSC12CellSS.py +565 -0
  25. midas_civil/_section/_unSupp.py +58 -0
  26. midas_civil/_settlement.py +161 -0
  27. midas_civil/_temperature.py +677 -0
  28. midas_civil/_tendon.py +1016 -0
  29. midas_civil/_thickness.py +147 -0
  30. midas_civil/_utils.py +529 -0
  31. midas_civil/_utilsFunc/__init__.py +0 -0
  32. midas_civil/_utilsFunc/_line2plate.py +636 -0
  33. midas_civil/_view.py +891 -0
  34. midas_civil/_view_trial.py +430 -0
  35. midas_civil/_visualise.py +347 -0
  36. midas_civil-1.4.1.dist-info/METADATA +74 -0
  37. midas_civil-1.4.1.dist-info/RECORD +40 -0
  38. midas_civil-1.4.1.dist-info/WHEEL +5 -0
  39. midas_civil-1.4.1.dist-info/licenses/LICENSE +21 -0
  40. midas_civil-1.4.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,159 @@
1
+ from ._mapi import MidasAPI
2
+ # from ._model import *
3
+
4
+
5
+ #28 Class to generate load combinations
6
+ class LoadCombination:
7
+ data = []
8
+ valid = ["General", "Steel", "Concrete", "SRC", "Composite Steel Girder", "Seismic", "All"]
9
+ com_map = {
10
+ "General": "/db/LCOM-GEN",
11
+ "Steel": "/db/LCOM-STEEL",
12
+ "Concrete": "/db/LCOM-CONC",
13
+ "SRC": "/db/LCOM-SRC",
14
+ "Composite Steel Girder": "/db/LCOM-STLCOMP",
15
+ "Seismic": "/db/LCOM-SEISMIC"
16
+ }
17
+ def __init__(self, name, case, classification = "General", active = "ACTIVE", typ = "Add", id:int = None, desc = ""):
18
+ """Name, List of tuple of load cases & factors, classification, active, type. \n
19
+ Sample: LoadCombination('LCB1', [('Dead Load(CS)',1.5), ('Temperature(ST)',0.9)], 'General', 'Active', 'Add')"""
20
+ if id == None: id =0
21
+ if not isinstance(case, list):
22
+ print("case should be a list that contains tuple of load cases & factors.\nEg: [('Load1(ST)', 1.5), ('Load2(ST)',0.9)]")
23
+ return
24
+ for i in case:
25
+ if not isinstance(i, tuple):
26
+ print(f"{i} is not a tuple. case should be a list that contains tuple of load cases & factors.\nEg: [('Load1(ST)', 1.5), ('Load2(ST)',0.9)]")
27
+ return
28
+ if not isinstance(i[0], str):
29
+ print(f"{i[0]} is not a string. case should be a list that contains tuple of load cases & factors.\nEg: [('Load1(ST)', 1.5), ('Load2(ST)',0.9)]")
30
+ return
31
+ if i[0][-1] != ")":
32
+ print(f"Load case type is not mentioned for {i[0]}. case should be a list that contains tuple of load cases & factors.\nEg: [('Load1(ST)', 1.5), ('Load2(ST)',0.9)]")
33
+ return
34
+ if not isinstance(i[1],(int, float)):
35
+ print(f"{i[1]} is not a number. case should be a list that contains tuple of load cases & factors.\nEg: [('Load1(ST)', 1.5), ('Load2(ST)',0.9)]")
36
+ return
37
+
38
+ if classification not in LoadCombination.valid[:-1]:
39
+ print(f'"{classification}" is not a valid input. It is changed to "General".')
40
+ classification = "General"
41
+
42
+ if classification in ["General", "Seismic"]:
43
+ if active not in ["ACTIVE", "INACTIVE"]: active = "ACTIVE"
44
+ if classification in ["Steel", "Concrete", "SRC", "Composite Steel Girder"]:
45
+ if active not in ["STRENGTH", "SERVICE", "INACTIVE"]: active = "STRENGTH"
46
+
47
+ typ_map = {"Add": 0, "Envelope": 1, "ABS": 2, "SRSS": 3, 0:0, 1:1, 2:2, 3:3}
48
+ if typ not in list(typ_map.keys()): typ = "Add"
49
+ if classification not in ["General", "Seismic"] and typ_map.get(typ) == 2: typ = "Add"
50
+
51
+ if id == 0 and len(LoadCombination.data) == 0:
52
+ id = 1
53
+ elif id == 0 and len(LoadCombination.data) != 0:
54
+ id = max([i.ID for i in LoadCombination.data]) + 1
55
+ elif id != 0 and id in [i.ID for i in LoadCombination.data]:
56
+ if classification in [i.CLS for i in LoadCombination.data if i.ID == id]:
57
+ print(f"ID {id} is already defined. Existing combination would be replaced.")
58
+
59
+
60
+ combo = []
61
+ valid_anl = ["ST", "CS", "MV", "SM", "RS", "TH", "CB", "CBC", "CBS", "CBR", "CBSC", "CBSM"] #Need to figure out for all combination types
62
+ for i in case:
63
+ a = i[0].rsplit('(', 1)[1].rstrip(')')
64
+ if a in valid_anl:
65
+ combo.append({
66
+ "ANAL": a,
67
+ "LCNAME":i[0].rsplit('(', 1)[0],
68
+ "FACTOR": i[1]
69
+ })
70
+ self.NAME = name
71
+ self.CASE = combo
72
+ self.CLS = classification
73
+ self.ACT = active
74
+ self.TYPE = typ_map.get(typ)
75
+ self.ID = id
76
+ self.DESC = desc
77
+ LoadCombination.data.append(self)
78
+
79
+ @classmethod
80
+ def json(cls, classification = "All"):
81
+ if len(LoadCombination.data) == 0:
82
+ print("No Load Combinations defined! Define the load combination using the 'LoadCombination' class before making json file.")
83
+ return
84
+ if classification not in LoadCombination.valid:
85
+ print(f'"{classification}" is not a valid input. It is changed to "General".')
86
+ classification = "General"
87
+ json = {k:{'Assign':{}} for k in LoadCombination.valid[:-1]}
88
+ for i in LoadCombination.data:
89
+ if i.CLS == classification or classification == "All":
90
+ json[i.CLS]['Assign'][i.ID] = {
91
+ "NAME": i.NAME,
92
+ "ACTIVE": i.ACT,
93
+ "iTYPE": i.TYPE,
94
+ "DESC": i.DESC,
95
+ "vCOMB":i.CASE
96
+ }
97
+ json = {k:v for k,v in json.items() if v != {'Assign':{}}}
98
+ return json
99
+
100
+ @classmethod
101
+ def get(cls, classification = "All"):
102
+ if classification not in LoadCombination.valid:
103
+ print(f'"{classification}" is not a valid input. It is changed to "General".')
104
+ classification = "General"
105
+ combos = {k:{} for k in LoadCombination.valid[:-1]}
106
+ for i in LoadCombination.valid[:-1]:
107
+ if classification == i or classification == "All":
108
+ combos[i] = MidasAPI("GET",LoadCombination.com_map.get(i))
109
+ json = {k:v for k,v in combos.items() if v != {'message':''}}
110
+ return json
111
+
112
+ @classmethod
113
+ def create(cls, classification = "All"):
114
+ if len(LoadCombination.data) == 0:
115
+ # print("No Load Combinations defined! Define the load combination using the 'LoadCombination' class before creating these in the model.")
116
+ return
117
+ if classification not in LoadCombination.valid:
118
+ print(f'"{classification}" is not a valid input. It is changed to "General".')
119
+ classification = "General"
120
+ json = LoadCombination.json(classification)
121
+ for i in LoadCombination.valid[:-1]:
122
+ if classification == i or classification == "All":
123
+ if i in list(json.keys()):
124
+ a = list(json[i]['Assign'].keys())
125
+ b=""
126
+ for j in range(len(a)):
127
+ b += str(a[j]) + ","
128
+ if b != "": b = "/" + b[:-1]
129
+ MidasAPI("DELETE", LoadCombination.com_map.get(i) + b) #Delete existing combination if any
130
+ MidasAPI("PUT", LoadCombination.com_map.get(i), json[i]) #Create new combination
131
+
132
+ @classmethod
133
+ def sync(cls, classification = "All"):
134
+ json = LoadCombination.get(classification)
135
+ if json != {}:
136
+ keys = list(json.keys())
137
+ for i in keys:
138
+ for k,v in json[i][LoadCombination.com_map.get(i)[4:]].items():
139
+ c = []
140
+ for j in range(len(v['vCOMB'])):
141
+ c.append((v['vCOMB'][j]['LCNAME'] + "("+ v['vCOMB'][j]['ANAL'] + ")", v['vCOMB'][j]['FACTOR']))
142
+ LoadCombination(v['NAME'], c, i, v['ACTIVE'], v['iTYPE'], int(k), v['DESC'])
143
+
144
+ @classmethod
145
+ def delete(cls, classification = "All", ids = []):
146
+ json = LoadCombination.json(classification)
147
+ a = ""
148
+ for i in range(len(ids)):
149
+ a += str(ids[i]) + ","
150
+ a = "/" + a[:-1]
151
+ if json == {}:
152
+ print("No load combinations are defined to delete.")
153
+ for i in list(json.keys()):
154
+ MidasAPI("DELETE",LoadCombination.com_map.get(i) + a)
155
+
156
+ @classmethod
157
+ def clear(cls):
158
+ cls.data = []
159
+ #---------------------------------------------------------------------------------------------------------------
midas_civil/_mapi.py ADDED
@@ -0,0 +1,249 @@
1
+ import requests
2
+ import sys
3
+ from colorama import Fore, Style
4
+ try:import winreg
5
+ except: pass
6
+ import time
7
+ from tqdm import tqdm
8
+ # import polars as pl
9
+
10
+
11
+
12
+ def Midas_help():
13
+ """MIDAS Documnetation : https://midas-rnd.github.io/midasapi-python """
14
+ print('\n╭────────────────────────────────────────────────────────────────────────────────────╮')
15
+ print("│ HELP MANUAL : https://midas-rnd.github.io/midasapi-python/ │")
16
+ print('╰────────────────────────────────────────────────────────────────────────────────────╯\n')
17
+
18
+
19
+
20
+ class NX:
21
+ version_check = True # CHANGE IT TO FALSE TO SKIP VERSION CHECK OF LIBRARY
22
+ user_print = True
23
+ debug_request = False
24
+ debug_requestJSON = False
25
+ debug_response = False
26
+ onlyNode = False
27
+ visualiser = False
28
+
29
+ def saveJSON(jsonData,fileLocation = "jsData.json"):
30
+ import json
31
+ with open(fileLocation, "w", encoding="utf-8") as f:
32
+ json.dump(jsonData, f, indent=4, ensure_ascii=False)
33
+
34
+
35
+ class MAPI_COUNTRY:
36
+
37
+ country = "US"
38
+
39
+ def __init__(self,country:str="US"):
40
+ ''' Define Civil NX country to automatically set Base URL and MAPI Key from registry.
41
+ ```
42
+ MAPI_COUNTRY('US') # For english version
43
+ MAPI_COUNTRY('KR') # For Korean version
44
+ MAPI_COUNTRY('CH') # For Chinese version
45
+ ```
46
+ '''
47
+ if country.lower() in ['us','ch','kr','jp']:
48
+ MAPI_COUNTRY.country = country.upper()
49
+ else:
50
+ MAPI_COUNTRY.country = 'US'
51
+
52
+ MAPI_BASEURL.setURLfromRegistry()
53
+ MAPI_KEY.get_key() # Intial Key from registry
54
+
55
+
56
+ class MAPI_BASEURL:
57
+ baseURL = "https://moa-engineers.midasit.com:443/civil"
58
+ server_loc = "Global"
59
+
60
+ def __init__(self, baseURL:str = "https://moa-engineers.midasit.com:443/civil"):
61
+ ''' Define the Base URL for API connection.
62
+ ```
63
+ MAPI_BASEURL('https://moa-engineers.midasit.com:443/civil')
64
+ ```
65
+ '''
66
+ MAPI_BASEURL.baseURL = baseURL
67
+
68
+ @classmethod
69
+ def get_url(cls):
70
+ return MAPI_BASEURL.baseURL
71
+
72
+ @classmethod
73
+ def setURLfromRegistry(cls):
74
+ try:
75
+ key_path = f"Software\\MIDAS\\CVLwNX_{MAPI_COUNTRY.country}\\CONNECTION"
76
+ registry_key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, key_path, 0, winreg.KEY_READ)
77
+ url_reg = winreg.QueryValueEx(registry_key, "URI")
78
+ url_reg_key = url_reg[0]
79
+
80
+ port_reg = winreg.QueryValueEx(registry_key, "PORT")
81
+ port_reg_key = port_reg[0]
82
+
83
+ url_comb = f'https://{url_reg_key}:{port_reg_key}/civil'
84
+
85
+ tqdm.write(f' 🌐 BASE URL is taken from Registry entry. >> {url_comb}')
86
+ MAPI_BASEURL(url_comb)
87
+ except:
88
+ tqdm.write(" 🌐 BASE URL is not defined. Click on Apps > API Settings to copy the BASE URL Key.\nDefine it using MAPI_BASEURL('https://moa-engineers.midasit.com:443/civil')")
89
+ sys.exit(0)
90
+
91
+ @staticmethod
92
+ def autoURL():
93
+ base_urls = [
94
+ "https://moa-engineers-in.midasit.com:443/civil",
95
+ "https://moa-engineers-kr.midasit.com:443/civil",
96
+ "https://moa-engineers-gb.midasit.com:443/civil",
97
+ "https://moa-engineers-us.midasit.com:443/civil",
98
+ "https://moa-engineers.midasit.cn:443/civil"
99
+ ]
100
+ serv_locations = ["INDIA","KOREA","EUROPE","USA","CHINA"]
101
+ mapi_key = MAPI_KEY.get_key()
102
+ chk = 0
103
+ for i,base_url in enumerate(base_urls):
104
+ url = base_url + "/config/ver"
105
+ headers = {
106
+ "Content-Type": "application/json",
107
+ "MAPI-Key": mapi_key
108
+ }
109
+ response = requests.get(url=url, headers=headers)
110
+ if response.status_code == 200:
111
+ MAPI_BASEURL(base_url)
112
+ MAPI_BASEURL.server_loc = serv_locations[i]
113
+ chk=1
114
+ break
115
+ if chk==0:
116
+ tqdm.write(f" 🌐 Kindly manually enter the BASE URL. \nRefer to https://moa.midasit.com/services to find the correct URL.")
117
+ sys.exit(0)
118
+
119
+ class MAPI_KEY:
120
+ """MAPI key from Civil NX.\n\nEg: MAPI_Key("eadsfjaks568wqehhf.ajkgj345qfhh")"""
121
+ data = ""
122
+ count = 1
123
+
124
+ def __init__(self, mapi_key:str):
125
+ MAPI_KEY.data = mapi_key
126
+
127
+ @classmethod
128
+ def get_key(cls):
129
+ if MAPI_KEY.data == "":
130
+ try:
131
+ key_path = f"Software\\MIDAS\\CVLwNX_{MAPI_COUNTRY.country}\\CONNECTION"
132
+ registry_key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, key_path, 0, winreg.KEY_READ)
133
+ value = winreg.QueryValueEx(registry_key, "Key")
134
+ my_key = value[0]
135
+ MAPI_KEY(my_key)
136
+ tqdm.write(f' šŸ”‘ MAPI-KEY is taken from Registry entry. >> {my_key[:35]}...')
137
+ except:
138
+ tqdm.write(f"šŸ”‘ MAPI KEY is not defined. Click on Apps > API Settings to copy the MAPI Key.\n Define it using MAPI_KEY('xxxx')")
139
+ sys.exit(0)
140
+ else:
141
+ my_key = MAPI_KEY.data
142
+
143
+ return my_key
144
+ #---------------------------------------------------------------------------------------------------------------
145
+
146
+ #2 midas API link code:
147
+ def MidasAPI(method:str, command:str, body:dict={})->dict:
148
+ """Sends HTTP Request to MIDAS Civil NX
149
+ Parameters:
150
+ Method: "PUT" , "POST" , "GET" or "DELETE"
151
+ Command: eg. "/db/NODE"
152
+ Body: {{"Assign":{{1{{'X':0, 'Y':0, 'Z':0}}}}}}
153
+ Examples:
154
+ ```python
155
+ # Create a node
156
+ MidasAPI("PUT","/db/NODE",{{"Assign":{{"1":{{'X':0, 'Y':0, 'Z':0}}}}}})"""
157
+
158
+ base_url = MAPI_BASEURL.baseURL
159
+ mapi_key = MAPI_KEY.get_key()
160
+
161
+ url = base_url + command
162
+ headers = {
163
+ "Content-Type": "application/json",
164
+ "MAPI-Key": mapi_key
165
+ }
166
+
167
+ if MAPI_KEY.count == 1:
168
+ MAPI_KEY.count =0
169
+ if NX.user_print:
170
+ _checkUSER()
171
+
172
+
173
+
174
+
175
+ start_time = time.perf_counter()
176
+
177
+
178
+ if method == "POST":
179
+ response = requests.post(url=url, headers=headers, json=body)
180
+ elif method == "PUT":
181
+ response = requests.put(url=url, headers=headers, json=body)
182
+ elif method == "GET":
183
+ response = requests.get(url=url, headers=headers)
184
+ elif method == "DELETE":
185
+ response = requests.delete(url=url, headers=headers)
186
+
187
+ end_time = time.perf_counter()
188
+ elapsed_time = end_time - start_time
189
+
190
+ if NX.debug_request:
191
+ tqdm.write(Fore.RED+f">> METHOD : {method} | URL : {command} | STATUS : {response.status_code} | TIME : {elapsed_time:.4f} sec "+Style.RESET_ALL)
192
+ if NX.debug_requestJSON:
193
+ tqdm.write(Fore.CYAN+">> "+str(body)+Style.RESET_ALL)
194
+ if NX.debug_response:
195
+ tqdm.write(Fore.GREEN+"<< "+str(response.json())+Style.RESET_ALL)
196
+
197
+ if MAPI_KEY.count == 0:
198
+ MAPI_KEY.count = -1
199
+ if response.status_code == 404:
200
+ print(Fore.RED +'\n╭─ šŸ’€ ─────────────────────────────────────────────────────────────────────────────╮')
201
+ print(f"│ Civil NX model is not connected. Click on 'Apps > Connect' in Civil NX. │")
202
+ print(f"│ Make sure the MAPI Key in python code is matching with the MAPI key in Civil NX. │")
203
+ print('╰────────────────────────────────────────────────────────────────────────────────────╯\n'+Style.RESET_ALL)
204
+ sys.exit(0)
205
+
206
+
207
+
208
+ return response.json()
209
+
210
+
211
+ #--------------------------------------------------------------------
212
+
213
+ def _getUNIT():
214
+ return MidasAPI('GET','/db/UNIT',{})['UNIT']['1']
215
+
216
+ def _setUNIT(unitJS):
217
+ js = {
218
+ "Assign" : {
219
+ "1" : unitJS
220
+ }
221
+ }
222
+ MidasAPI('PUT','/db/UNIT',js)
223
+
224
+
225
+ def _checkUSER():
226
+ try:
227
+ resp = MidasAPI('GET','/config/ver',{})['VER']
228
+
229
+ # print(f"{' '*15}Connected to {resp['NAME']}")
230
+ # print(f"{' '*15}USER : {resp['USER']} COMPANY : {resp['COMPANY']}")
231
+
232
+ ln1 = f"Connected to {resp['NAME']} SERVER : {MAPI_BASEURL.server_loc}"
233
+ ln2 = f"USER : {resp['USER']} COMPANY : {resp['COMPANY']}"
234
+
235
+ lg_ln1 = 66-len(ln1)
236
+ lg_ln2 = 70-len(ln2)
237
+
238
+ line1 = f"│{' '*12} {ln1} {' '*lg_ln1} 🟢 │"
239
+ line2 = f"│{' '*12} {ln2} {' '*lg_ln2}│"
240
+ tqdm.write(Fore.GREEN+'\n╭─ šŸ”” ──────────────────────────────────────────────────────────────────────────────╮')
241
+ tqdm.write(line1)
242
+ tqdm.write(line2)
243
+ tqdm.write('╰────────────────────────────────────────────────────────────────────────────────────╯\n'+Style.RESET_ALL)
244
+
245
+
246
+ # print('─'*86)
247
+
248
+ except:
249
+ pass