FEM-Design 0.0.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.
@@ -0,0 +1,445 @@
1
+ import os
2
+ import xml.etree.ElementTree as ET
3
+ from enum import Enum, auto
4
+ from abc import ABC, abstractmethod
5
+
6
+ from .analysis import Analysis, Design
7
+
8
+ import uuid
9
+ import pathlib
10
+
11
+ class User(Enum):
12
+ """Enum class to represent the different modules in FEM-Design
13
+ """
14
+ STRUCT = auto()
15
+ LOADS = auto()
16
+ MESH = auto()
17
+ RESMODE = auto()
18
+ FOUNDATIONDESIGN = auto()
19
+ RCDESIGN = auto()
20
+ STEELDESIGN = auto()
21
+ TIMBERDESIGN = auto()
22
+ MASONRYDESIGN = auto()
23
+ COMPOSITEDESIGN = auto()
24
+ PERFORMANCEBASEDDESIGN = auto()
25
+
26
+
27
+ class DesignModule(Enum):
28
+ """Enum class to represent the different design modules in FEM-Design
29
+ """
30
+ RCDESIGN = auto()
31
+ STEELDESIGN = auto()
32
+ TIMBERDESIGN = auto()
33
+ MASONRYDESIGN = auto()
34
+ COMPOSITEDESIGN = auto()
35
+
36
+ def to_user(self) -> User:
37
+ """Convert the DesignModule to a User object
38
+
39
+ Returns:
40
+ User: User object corresponding to the DesignModule
41
+ """
42
+ mapping = {
43
+ DesignModule.RCDESIGN: User.RCDESIGN,
44
+ DesignModule.STEELDESIGN: User.STEELDESIGN,
45
+ DesignModule.TIMBERDESIGN: User.TIMBERDESIGN,
46
+ DesignModule.MASONRYDESIGN: User.MASONRYDESIGN,
47
+ DesignModule.COMPOSITEDESIGN: User.COMPOSITEDESIGN
48
+ }
49
+ return mapping[self]
50
+
51
+
52
+ class Command(ABC):
53
+ """Abstract class to represent a command in a FEM-Design script file
54
+ """
55
+ @abstractmethod
56
+ def to_xml_element(self) -> ET.Element:
57
+ pass
58
+
59
+
60
+ class CmdUser(Command):
61
+ """CmdUser class to represent the fdscript 'cmduser' command
62
+ """
63
+ def __init__(self, module : User):
64
+ self.module = module
65
+
66
+ def to_xml_element(self) -> ET.Element:
67
+ """convert the CmdUser object to an xml element
68
+
69
+ Returns:
70
+ ET.Element: xml element representing the CmdUser object
71
+ """
72
+ cmd_user = ET.Element("cmduser")
73
+ cmd_user.attrib = {"command": f"; CXL $MODULE {self.module.name}"}
74
+
75
+ return cmd_user
76
+
77
+ @classmethod
78
+ def ResMode(cls) -> Command:
79
+ """Create a CmdUser object for the ResMode module
80
+
81
+ Returns:
82
+ Command: CmdUser object for the ResMode module
83
+ """
84
+ return cls(User.RESMODE)
85
+
86
+ @classmethod
87
+ def Load(cls) -> Command:
88
+ """Create a CmdUser object for the Load module
89
+
90
+ Returns:
91
+ Command: CmdUser object for the Load module
92
+ """
93
+ return cls(User.LOADS)
94
+
95
+ @classmethod
96
+ def Mesh(cls) -> Command:
97
+ """Create a CmdUser object for the Mesh module
98
+
99
+ Returns:
100
+ Command: CmdUser object for the Mesh module
101
+ """
102
+ return cls(User.MESH)
103
+
104
+ @classmethod
105
+ def FoundationDesign(cls) -> Command:
106
+ """Create a CmdUser object for the FoundationDesign module
107
+
108
+ Returns:
109
+ Command: CmdUser object for the FoundationDesign module
110
+ """
111
+ return cls(User.FOUNDATIONDESIGN)
112
+
113
+ @classmethod
114
+ def RCDesign(cls) -> Command:
115
+ """Create a CmdUser object for the RCDesign module
116
+
117
+ Returns:
118
+ Command: CmdUser object for the RCDesign module
119
+ """
120
+ return cls(User.RCDESIGN)
121
+
122
+ @classmethod
123
+ def SteelDesign(cls) -> Command:
124
+ """Create a CmdUser object for the SteelDesign module
125
+
126
+ Returns:
127
+ Command: CmdUser object for the SteelDesign module
128
+ """
129
+ return cls(User.STEELDESIGN)
130
+
131
+ @classmethod
132
+ def TimberDesign(cls)-> Command:
133
+ """Create a CmdUser object for the TimberDesign module
134
+
135
+ Returns:
136
+ Command: CmdUser object for the TimberDesign module
137
+ """
138
+ return cls(User.TIMBERDESIGN)
139
+
140
+ @classmethod
141
+ def MasonryDesign(cls) -> Command:
142
+ """Create a CmdUser object for the MasonryDesign module
143
+
144
+ Returns:
145
+ Command: CmdUser object for the MasonryDesign module
146
+ """
147
+ return cls(User.MASONRYDESIGN)
148
+
149
+ @classmethod
150
+ def CompositeDesign(cls) -> Command:
151
+ """Create a CmdUser object for the CompositeDesign module
152
+
153
+ Returns:
154
+ Command: CmdUser object for the CompositeDesign module
155
+ """
156
+ return cls(User.COMPOSITEDESIGN)
157
+
158
+ @classmethod
159
+ def PerformanceBasedDesign(cls) -> Command:
160
+ """Create a CmdUser object for the PerformanceBasedDesign module
161
+
162
+ Returns:
163
+ Command: CmdUser object for the PerformanceBasedDesign module
164
+ """
165
+ return cls(User.PERFORMANCEBASEDDESIGN)
166
+
167
+ @classmethod
168
+ def _fromDesignModule(cls, module : DesignModule) -> Command:
169
+ """Create a CmdUser object from a DesignModule
170
+
171
+ Args:
172
+ module (DesignModule): DesignModule to create the CmdUser object from
173
+
174
+ Returns:
175
+ Command: CmdUser object for the specified DesignModule
176
+ """
177
+ if module == DesignModule.RCDESIGN:
178
+ return cls.RCDesign()
179
+ if module == DesignModule.STEELDESIGN:
180
+ return cls.SteelDesign()
181
+ if module == DesignModule.TIMBERDESIGN:
182
+ return cls.TimberDesign()
183
+ if module == DesignModule.MASONRYDESIGN:
184
+ return cls.MasonryDesign()
185
+ if module == DesignModule.COMPOSITEDESIGN:
186
+ return cls.CompositeDesign()
187
+
188
+
189
+ class CmdOpen(Command):
190
+ """CmdOpen class to represent the fdscript 'cmdopen' command
191
+ """
192
+ def __init__(self, file_name : str):
193
+ """Constructor for the CmdOpen class
194
+
195
+ Args:
196
+ file_name (str): path to the file to open
197
+ """
198
+ self.file_name = os.path.abspath(file_name)
199
+
200
+ def to_xml_element(self) -> ET.Element:
201
+ cmd_open = ET.Element("cmdopen")
202
+
203
+ file_name_elem = ET.SubElement(cmd_open, "filename")
204
+ file_name_elem.text = self.file_name
205
+
206
+ attributes = {"command": "; CXL CS2SHELL OPEN"}
207
+ cmd_open.attrib = attributes
208
+
209
+ return cmd_open
210
+
211
+
212
+ class CmdCalculation(Command):
213
+ """CmdCalculation class to represent the fdscript 'cmdcalculation' command
214
+ """
215
+ def __init__(self, analysis : Analysis, design : Design = None):
216
+ """Constructor for the CmdCalculation class
217
+
218
+ Args:
219
+ analysis (Analysis): Analysis object to be included in the calculation
220
+ design (Design, optional): Design object to be included in the calculation.
221
+ """
222
+ self.analysis = analysis
223
+ self.design = design
224
+
225
+
226
+ def to_xml_element(self) -> ET.Element:
227
+ """Convert the CmdCalculation object to an xml element
228
+
229
+ Returns:
230
+ ET.Element: xml element representing the CmdCalculation object
231
+ """
232
+ cmd_calculation = ET.Element("cmdcalculation")
233
+
234
+ attributes = { "command": "; CXL $MODULE CALC"}
235
+ cmd_calculation.attrib = attributes
236
+
237
+ if self.analysis:
238
+ cmd_calculation.append(self.analysis.to_xml_element())
239
+ if self.design:
240
+ cmd_calculation.append(self.design.to_xml_element())
241
+
242
+ return cmd_calculation
243
+
244
+
245
+ class CmdSave(Command):
246
+ """CmdSave class to represent the fdscript 'cmdsave' command
247
+ """
248
+ def __init__(self, file_name : str):
249
+ """Constructor for the CmdSave class
250
+
251
+ Args:
252
+ file_name (str): path to the file to save
253
+ """
254
+
255
+ if not file_name.endswith(".str") and not file_name.endswith(".struxml"):
256
+ raise ValueError("file_name must have suffix .str or .struxml")
257
+
258
+ if not os.path.exists(os.path.dirname(os.path.abspath(file_name))):
259
+ os.makedirs(os.path.dirname(os.path.abspath(file_name)))
260
+
261
+ self.file_name = os.path.abspath(file_name)
262
+
263
+ def to_xml_element(self) -> ET.Element:
264
+ """Convert the CmdSave object to an xml element
265
+
266
+ Returns:
267
+ ET.Element: xml element representing the CmdSave object
268
+ """
269
+ cmd_save = ET.Element("cmdsave")
270
+
271
+ file_name_elem = ET.SubElement(cmd_save, "filename")
272
+ file_name_elem.text = self.file_name
273
+
274
+ attributes = {"command": "; CXL CS2SHELL SAVE"}
275
+ cmd_save.attrib = attributes
276
+
277
+ return cmd_save
278
+
279
+
280
+ class CmdEndSession(Command):
281
+ """CmdEndSession class to represent the fdscript 'cmdendsession' command
282
+ """
283
+ def __init__(self):
284
+ """"""
285
+ pass
286
+
287
+ def to_xml_element(self) -> ET.Element:
288
+ """convert the CmdEndSession object to an xml element
289
+
290
+ Returns:
291
+ ET.Element: xml element representing the CmdEndSession object
292
+ """
293
+ cmd_end_session = ET.Element("cmdendsession")
294
+ return cmd_end_session
295
+
296
+
297
+ class CmdProjDescr(Command):
298
+ """class to represent the fdscript cmdprojdescr command
299
+ """
300
+ def __init__(self, project : str, description : str, designer : str, signature : str, comment : str, items : dict = None, read : bool = False, reset : bool = False):
301
+ """Constructor for the CmdProjDescr class
302
+
303
+ Args:
304
+ project (str): project name
305
+ description (str): description
306
+ designer (str): designer
307
+ signature (str): signature
308
+ comment (str): comment
309
+ items (dict, optional): define key-value user data. Defaults to None.
310
+ read (bool, optional): read the project settings. Value will be store in the clipboard. Defaults to False.
311
+ reset (bool, optional): reset the project settings. Defaults to False.
312
+ """
313
+ self.project = project
314
+ self.description = description
315
+ self.designer = designer
316
+ self.signature = signature
317
+ self.comment = comment
318
+ self.items = items
319
+ self.read = read
320
+ self.reset = reset
321
+
322
+ def to_xml_element(self) -> ET.Element:
323
+ """Convert the CmdProjDescr object to an xml element
324
+
325
+ Returns:
326
+ ET.Element: xml element representing the CmdProjDescr object
327
+ """
328
+ cmd_proj_descr = ET.Element("cmdprojdescr")
329
+
330
+ attributes = {
331
+ "command": "$ MODULECOM PROJDESCR",
332
+ "szProject": self.project,
333
+ "szDescription": self.description,
334
+ "szDesigner": self.designer,
335
+ "szSignature": self.signature,
336
+ "szComment": self.comment,
337
+ "read": str(int(self.read)),
338
+ "reset": str(int(self.reset))
339
+ }
340
+
341
+ ## join two dictionaries
342
+ cmd_proj_descr.attrib = attributes
343
+
344
+ if self.items:
345
+ for key, value in self.items.items():
346
+ item = ET.SubElement(cmd_proj_descr, "item")
347
+ item.attrib = {"id": key, "txt": value}
348
+
349
+ return cmd_proj_descr
350
+
351
+
352
+ class CmdSaveDocx(Command):
353
+ """class to represent the fdscript cmdsavedocx command
354
+ """
355
+ def __init__(self, file_name : str):
356
+ """Constructor for the CmdSaveDocx class
357
+
358
+ Args:
359
+ file_name (str): path to the file to save
360
+ """
361
+ if not file_name.endswith(".docx"):
362
+ raise ValueError("file_name must have suffix .docx")
363
+
364
+ if not os.path.exists(os.path.dirname(os.path.abspath(file_name))):
365
+ os.makedirs(os.path.dirname(os.path.abspath(file_name)))
366
+
367
+ self.file_name = os.path.abspath(file_name)
368
+
369
+ def to_xml_element(self) -> ET.Element:
370
+ """Convert the CmdSaveDocx object to an xml element
371
+
372
+ Returns:
373
+ ET.Element: xml element representing the CmdSaveDocx object
374
+ """
375
+ cmd_save_docx = ET.Element("cmdsavedocx")
376
+
377
+ file_name_elem = ET.SubElement(cmd_save_docx, "filename")
378
+ file_name_elem.text = self.file_name
379
+
380
+ attributes = {"command": "$ DOC SAVEDOCX"}
381
+ cmd_save_docx.attrib = attributes
382
+
383
+ return cmd_save_docx
384
+
385
+
386
+
387
+
388
+ class CmdListGen:
389
+ """Class to represent the fdscript 'cmdlistgen' command
390
+ """
391
+ def __init__(self, bscfile : str, outfile : str = None, guids : list[uuid.UUID] = None, regional : bool = True, fillcells : bool = True, headers : bool = True):
392
+ """Constructor for the CmdListGen class
393
+
394
+ Args:
395
+ bscfile (str): path to the bsc file
396
+ outfile (str, optional): path to the output file. Defaults to None.
397
+ guids (list[uuid.UUID], optional): list of element part guids to include in the output. Defaults to None.
398
+ regional (bool, optional):
399
+ fillcells (bool, optional):
400
+ headers (bool, optional):
401
+ """
402
+ if not bscfile.endswith(".bsc"):
403
+ raise ValueError("bscfile must have suffix .bsc")
404
+
405
+ if outfile and not outfile.endswith(".csv"):
406
+ raise ValueError("outfile must have suffix .csv")
407
+
408
+ if not outfile:
409
+ outfile = pathlib.Path(self.bscfile).with_suffix(".csv")
410
+
411
+ if not os.path.exists(os.path.dirname(os.path.abspath(outfile))):
412
+ os.makedirs(os.path.dirname(os.path.abspath(outfile)))
413
+
414
+ self.bscfile = os.path.abspath(bscfile)
415
+ self.outfile = os.path.abspath(outfile)
416
+ self.regional = regional
417
+ self.fillcells = fillcells
418
+ self.headers = headers
419
+ self.guids = guids
420
+
421
+ def to_xml_element(self) -> ET.Element:
422
+ """convert the CmdListGen object to an xml element
423
+
424
+ Returns:
425
+ ET.Element: xml element representing the CmdListGen object
426
+ """
427
+ cmd_listgen = ET.Element("cmdlistgen")
428
+
429
+ attributes = {
430
+ "command": "$ MODULECOM LISTGEN",
431
+ "bscfile": self.bscfile,
432
+ "outfile": self.outfile,
433
+ "regional": str(int(self.regional)),
434
+ "fillcells": str(int(self.fillcells)),
435
+ "headers": str(int(self.headers)),
436
+ }
437
+
438
+ cmd_listgen.attrib = attributes
439
+
440
+ if self.guids:
441
+ for guid in self.guids:
442
+ guid_elem = ET.SubElement(cmd_listgen, "GUID")
443
+ guid_elem.text = str(guid)
444
+
445
+ return cmd_listgen
@@ -0,0 +1,87 @@
1
+ ## create a template for a class in python
2
+ import os
3
+ import xml.etree.ElementTree as ET
4
+ from .command import Command
5
+
6
+ class FdscriptHeader:
7
+ """
8
+ Class to represent the header of a FEM-Design script file
9
+ """
10
+ def __init__(self, log_file : str, title : str = "FEM-Design API", version : int = 2400, module : str = "SFRAME"):
11
+ self.title = title
12
+ self.version = str(version)
13
+ self.module = module
14
+ self.logfile = os.path.abspath(log_file)
15
+
16
+
17
+ def to_xml_element(self) -> ET.Element:
18
+ """Convert the FdscriptHeader object to an xml element
19
+
20
+ Returns:
21
+ ET.Element: xml element representing the FdscriptHeader object
22
+ """
23
+ fdscript_header = ET.Element("fdscriptheader")
24
+
25
+ title_elem = ET.SubElement(fdscript_header, "title")
26
+ title_elem.text = self.title
27
+
28
+ version_elem = ET.SubElement(fdscript_header, "version")
29
+ version_elem.text = self.version
30
+
31
+ module_elem = ET.SubElement(fdscript_header, "module")
32
+ module_elem.text = self.module
33
+
34
+ logfile_elem = ET.SubElement(fdscript_header, "logfile")
35
+ logfile_elem.text = self.logfile
36
+
37
+
38
+ return fdscript_header
39
+
40
+
41
+ class Fdscript:
42
+ """
43
+ Class to represent a FEM-Design script file
44
+ """
45
+ attributes = {
46
+ "xmlns:xsi" : "http://www.w3.org/2001/XMLSchema-instance",
47
+ "xsi:noNamespaceSchemaLocation" : "fdscript.xsd"
48
+ }
49
+
50
+ def __init__(self, log_file : str, commands : list[Command] ):
51
+ self.fdscriptheader = FdscriptHeader(log_file)
52
+ self.commands = commands
53
+
54
+ def add_command(self, command : Command):
55
+ """Add a command to the Fdscript object
56
+
57
+ Args:
58
+ command (Command): Command object to add to the Fdscript object
59
+ """
60
+ self.commands.append(command)
61
+
62
+ def to_xml_element(self) -> ET.Element:
63
+ """Convert the Fdscript object to an xml element
64
+
65
+ Returns:
66
+ ET.Element: xml element representing the Fdscript object
67
+ """
68
+ fdscript = ET.Element("fdscript")
69
+ fdscript.attrib = self.attributes
70
+
71
+ fdscript.append(self.fdscriptheader.to_xml_element())
72
+
73
+ for command in self.commands:
74
+ fdscript.append(command.to_xml_element())
75
+
76
+ return fdscript
77
+
78
+ def serialise_to_file(self, file_name : str):
79
+ """Serialise the Fdscript object to a file
80
+
81
+ Args:
82
+ file_name (str): file name to save the fdscript to
83
+ """
84
+ fdscript = self.to_xml_element()
85
+
86
+ tree = ET.ElementTree(fdscript)
87
+ tree.write(file_name, encoding="utf-8")