sensotwin.defect_placement.configuration

  1from collections import defaultdict, Counter
  2from .. import read_vtt, write_vtt
  3from ..store_connection import LocalStoreConnection, FusekiConnection, StoreConnection
  4from pyiron_base import HasHDF
  5import numpy as np
  6import pandas as pd
  7from abc import ABC, abstractmethod
  8
  9class InputDefect(ABC):
 10    """Base class for all defect types, only used to search for available defect types via __subclasses__.
 11    
 12    Attributes:
 13        type_id: every subclass must have unique integer id, creating an uninterruped serial starting from 1 to total number of subclasses
 14    """
 15    type_id = 0
 16    _id = None
 17    @abstractmethod
 18    def __init__(self):
 19        pass
 20
 21    @abstractmethod
 22    def generate_display_label(self):
 23        pass
 24
 25    @abstractmethod
 26    def generate_ontology_label(self, set_id, iter_id):
 27        pass
 28
 29    @abstractmethod
 30    def generate_store_insert_stub(self):
 31        pass
 32
 33    @staticmethod
 34    @abstractmethod
 35    def get_all_entries_from_store(conn):
 36        pass
 37
 38    def get_cell_id(self) -> int:
 39        """Return cell position of defect."""
 40        return self._cell_id
 41
 42    def get_layer_id(self) -> int:
 43        """Return layer position of defect."""
 44        return self._layer_id
 45
 46    @staticmethod
 47    def get_id_from_ontology_iri(label) -> int:
 48        """Extract defect id from full ontology instance iri."""
 49        return int(label.split("_")[-1])
 50
 51    @staticmethod
 52    def get_set_id_from_ontology_iri(label) -> int:
 53        """Extract input set id from full ontology instance iri."""
 54        return int(label.split("_")[-2])
 55
 56
 57class PlyWavinessDefect(InputDefect):
 58    """Ply waviness defect.
 59
 60    Attributes:
 61        type_id: Integer unique among all subclasses of InputDefect belonging to one specific defect input set
 62        display_name: Human readable name of defect type for legends
 63        display_color: tuple of RGB color values scaled from 0 to 1
 64    """
 65    data = None
 66    type_id = 1
 67    display_name = "Ply Waviness"
 68    display_color = (200 / 256, 200 / 256, 0 / 256)
 69
 70    def __init__(self, cell_id: int=None, layer_id: int=None, orientation: float=None, length: float=None, amplitude: float=None):
 71        """Initialize object.
 72
 73        Args:
 74            cell_id: integer cell id from 3D mesh of wind turbine
 75            layer_id: integer layer id from 3D mesh of wind turbine
 76            orientation: orientation of waviness in °
 77            length: length of waviness in m
 78            amplitude: amplitude of waviness in m
 79        """
 80        self._cell_id = cell_id
 81        self._layer_id = layer_id
 82        self._orientation = orientation
 83        self._length = length
 84        self._amplitude = amplitude
 85
 86    def generate_display_label(self):
 87        """Return string display for object in list displays."""
 88        return "{}, O: {}°, L: {}m, A: {}m".format(self.display_name, self._orientation, self._length, self._amplitude)
 89
 90    def generate_ontology_label(self, set_id: int, iter_id: int) -> str:
 91        """Generate ontology instance iri from object.
 92
 93        Args:
 94            set_id: id of input set this defect belongs to
 95            iter_id: unique id of defect within this specific input set
 96
 97        Returns:
 98            relative iri of ontology instance
 99        """
100        return "__PlyWavinessDefect_{set_id}_{iter_id}".format(set_id=set_id, iter_id=iter_id)
101
102    def generate_store_insert_stub(self, uniq_id: str) -> str:
103        """Generate SPARQL stub for inserting this object in a multi INSERT query.
104
105        Args:
106            uniq_id: unique string identifier with a combination of input set and defect ids
107
108        Returns:
109            SPARQL insert statement without INSERT, PREFIXES or WHERE clause
110        """
111        return """
112            senso:__PlyWavinessDefect_{uniq_id} a senso:PlyWavinessDefect ;
113                senso:defectOrientation {orientation} ;
114                senso:defectLength {length} ;
115                senso:defectAmplitude {amplitude} ;
116                senso:hasCellNumber {cell_id} ;
117                senso:hasLayerNumber {layer_id} .
118        """.format(uniq_id=uniq_id, cell_id=self._cell_id, layer_id=self._layer_id, orientation=self._orientation, length=self._length, amplitude=self._amplitude)
119
120    @staticmethod
121    def get_all_entries_from_store(conn: StoreConnection) -> dict:
122        """Get all instances of PlyWavinessDefect from store connection passed during initialization.
123
124        Args:
125            conn: Any subclass instance of StoreConnection
126        Returns:
127            dict of int -> PlyWavinessDefect
128        """
129        query = """
130            SELECT ?x ?cell_number ?layer_number ?orientation ?length ?amplitude
131            WHERE {
132                ?x a senso:PlyWavinessDefect .
133                ?x senso:defectOrientation ?orientation .
134                ?x senso:defectLength ?length .
135                ?x senso:defectAmplitude ?amplitude .
136                ?x senso:hasCellNumber ?cell_number .
137                ?x senso:hasLayerNumber ?layer_number .
138            }
139            """
140        result = {}
141        for x in conn.get_data(query):
142            result[x[0]] = PlyWavinessDefect(cell_id=int(x[1]), layer_id=int(x[2]), orientation=float(x[3]), length=float(x[4]), amplitude=float(x[5]))
143        return result
144
145    def to_simulation_input_dict(self) -> dict:
146        """Return dict representation of object intended for input into process simulation."""
147        return {
148            "type": self.display_name,
149            "cell_id": self._cell_id,
150            "layer_id": self._layer_id,
151            "absolute_local_ply_orientation": self._orientation,
152            "amplitude": self._amplitude,
153            "length": self._length
154        }
155
156    def __str__(self):
157        return "{} (Type ID {}) in cell {}, layer {}, data TBA".format(self.display_name, self.type_id, self._cell_id, self._layer_id)
158
159    def __repr__(self):
160        return "PlyWavinessDefect(cell_id={cell_id}, layer_id={layer_id}, orientation={orientation}, length={length}, amplitude={amplitude})".format(
161            cell_id = self._cell_id,
162            layer_id = self._layer_id,
163            orientation = self._orientation,
164            length = self._length,
165            amplitude = self._amplitude)
166
167
168class PlyMisorientationDefect(InputDefect):
169    """Defect for different fibre angle in layer than intended.
170
171    Attributes:
172        type_id: Integer unique among all subclasses of InputDefect belonging to one specific defect input set
173        display_name: Human readable name of defect type for legends
174        display_color: tuple of RGB color values scaled from 0 to 1
175    """
176    data = None
177    type_id = 2
178    display_name = "Ply Misorientation"
179    display_color = (12 / 256, 238 / 256, 246 / 256)
180
181    def __init__(self, cell_id: int=None, layer_id: int=None, angle: float=None):
182        """Initialize object.
183
184        Args:
185            cell_id: integer cell id from 3D mesh of wind turbine
186            layer_id: integer layer id from 3D mesh of wind turbine
187            angle: relative deviation from intended angle in °
188        """
189        self._cell_id = cell_id
190        self._layer_id = layer_id
191        self._angle = angle
192
193    def generate_display_label(self) -> str:
194        """Return string display for object in list displays."""
195        return "{}, Offset: {}°".format(self.display_name, self._angle)
196
197    def generate_ontology_label(self, set_id: int, iter_id: int) -> str:
198        """Generate ontology instance iri from object.
199
200        Args:
201            set_id: id of input set this defect belongs to
202            iter_id: unique id of defect within this specific input set
203
204        Returns:
205            relative iri of ontology instance
206        """
207        return "__PlyMisorientationDefect_{set_id}_{iter_id}".format(set_id=set_id, iter_id=iter_id)
208
209    def generate_store_insert_stub(self, uniq_id: str) -> str:
210        """Generate SPARQL stub for inserting this object in a multi INSERT query.
211
212        Args:
213            uniq_id: unique string identifier with a combination of input set and defect ids
214
215        Returns:
216            SPARQL insert statement without INSERT, PREFIXES or WHERE clause
217        """
218        return """
219            senso:__PlyMisorientationDefect_{uniq_id} a senso:PlyMisorientationDefect ;
220                co:value {angle} ;
221                senso:hasCellNumber {cell_id} ;
222                senso:hasLayerNumber {layer_id} .
223        """.format(uniq_id=uniq_id, cell_id=self._cell_id, layer_id=self._layer_id, angle=self._angle)
224
225    @staticmethod
226    def get_all_entries_from_store(conn: StoreConnection) -> dict:
227        """Get all instances of PlyMisorientationDefect from store connection passed during initialization.
228
229        Args:
230            conn: Any subclass instance of StoreConnection
231        Returns:
232            dict of int -> PlyMisorientationDefect
233        """
234        query = """
235            SELECT ?x ?angle ?cell_number ?layer_number
236            WHERE {
237                ?x a senso:PlyMisorientationDefect .
238                ?x co:value ?angle .
239                ?x senso:hasCellNumber ?cell_number .
240                ?x senso:hasLayerNumber ?layer_number .
241            }
242            """
243        result = {}
244        for x in conn.get_data(query):
245            result[x[0]] = PlyMisorientationDefect(cell_id=int(x[2]), layer_id=int(x[3]), angle=float(x[1]))
246        return result
247
248    def to_simulation_input_dict(self) -> dict:
249        """Return dict representation of object intended for input into process simulation."""
250        return {
251            "type": self.display_name,
252            "cell_id": self._cell_id,
253            "layer_id": self._layer_id,
254            "local_angular_deviation": self._angle
255        }
256
257    def __str__(self):
258        return "{} (Type ID {}) in cell {}, layer {}, data TBA".format(self.display_name, self.type_id, self._cell_id, self._layer_id)
259
260    def __repr__(self):
261        return "PlyMisorientationDefect(cell_id={cell_id}, layer_id={layer_id}, angle={angle})".format(cell_id = self._cell_id, layer_id = self._layer_id, angle = self._angle)
262
263
264class MissingPlyDefect(InputDefect):
265    """Defect for an entire layer missing.
266
267    Attributes:
268        type_id: Integer unique among all subclasses of InputDefect belonging to one specific defect input set
269        display_name: Human readable name of defect type for legends
270        display_color: tuple of RGB color values scaled from 0 to 1
271    """
272    data = None
273    type_id = 3
274    display_name = "Missing Ply"
275    display_color = (25 / 256, 248 / 256, 5 / 256)
276
277    def __init__(self, cell_id: int=None, layer_id: int=None):
278        """Initialize object.
279
280        Args:
281            cell_id: integer cell id from 3D mesh of wind turbine
282            layer_id: integer layer id from 3D mesh of wind turbine
283        """
284        self._cell_id = cell_id
285        self._layer_id = layer_id
286
287    def generate_display_label(self) -> str:
288        """Return string display for object in list displays."""
289        return "{}, Ply missing".format(self.display_name)
290
291    def generate_ontology_label(self, set_id, iter_id):
292        """Generate ontology instance iri from object.
293
294        Args:
295            set_id: id of input set this defect belongs to
296            iter_id: unique id of defect within this specific input set
297
298        Returns:
299            relative iri of ontology instance
300        """
301        return "__MissingPlyDefect_{set_id}_{iter_id}".format(set_id=set_id, iter_id=iter_id)
302
303    def generate_store_insert_stub(self, uniq_id: str) -> str:
304        """Generate SPARQL stub for inserting this object in a multi INSERT query.
305
306        Args:
307            uniq_id: unique string identifier with a combination of input set and defect ids
308
309        Returns:
310            SPARQL insert statement without INSERT, PREFIXES or WHERE clause
311        """
312        return """
313            senso:__MissingPlyDefect_{uniq_id} a senso:MissingPlyDefect ;
314                senso:hasCellNumber {cell_id} ;
315                senso:hasLayerNumber {layer_id} .
316        """.format(uniq_id=uniq_id, cell_id=self._cell_id, layer_id=self._layer_id)
317
318    @staticmethod
319    def get_all_entries_from_store(conn: StoreConnection) -> dict:
320        """Get all instances of MissingPlyDefect from store connection passed during initialization.
321
322        Args:
323            conn: Any subclass instance of StoreConnection
324        Returns:
325            dict of int -> MissingPlyDefect
326        """
327        query = """
328            SELECT ?x ?cell_number ?layer_number
329            WHERE {
330                ?x a senso:MissingPlyDefect .
331                ?x senso:hasCellNumber ?cell_number .
332                ?x senso:hasLayerNumber ?layer_number .
333            }
334            """
335        result = {}
336        for x in conn.get_data(query):
337            result[x[0]] = MissingPlyDefect(cell_id=int(x[1]), layer_id=int(x[2]))
338        return result
339
340    def to_simulation_input_dict(self) -> dict:
341        """Return dict representation of object intended for input into process simulation."""
342        return {
343            "type": self.display_name,
344            "cell_id": self._cell_id,
345            "layer_id": self._layer_id,
346        }
347
348    def __str__(self):
349        return "{} (Type ID {}) in cell {}, layer {}, data TBA".format(self.display_name, self.type_id, self._cell_id, self._layer_id)
350
351    def __repr__(self):
352        return "MissingPlyDefect(cell_id={cell_id}, layer_id={layer_id})".format(cell_id = self._cell_id, layer_id = self._layer_id)
353
354
355class VaryingThicknessDefect(InputDefect):
356    """Defect for a different layer thickness than intended.
357
358    Attributes:
359        type_id: Integer unique among all subclasses of InputDefect belonging to one specific defect input set
360        display_name: Human readable name of defect type for legends
361        display_color: tuple of RGB color values scaled from 0 to 1
362    """
363    data = None
364    type_id = 4
365    display_name = "Varying Thickness"
366    display_color = (255 / 256, 130 / 256, 3 / 256)
367
368    def __init__(self, cell_id: int=None, layer_id: int=None, fvc: float=None):
369        self._cell_id = cell_id
370        self._layer_id = layer_id
371        self._fvc = fvc
372
373    def generate_display_label(self) -> str:
374        """Return string display for object in list displays."""
375        return "{}, {}% FVC".format(self.display_name, self._fvc)
376
377    def generate_ontology_label(self, set_id: int, iter_id: int) -> str:
378        """Generate ontology instance iri from object.
379
380        Args:
381            set_id: id of input set this defect belongs to
382            iter_id: unique id of defect within this specific input set
383
384        Returns:
385            relative iri of ontology instance
386        """
387        return "__VaryingThicknessDefect__{set_id}_{iter_id}".format(set_id=set_id, iter_id=iter_id)
388
389    def generate_store_insert_stub(self, uniq_id: str) -> str:
390        """Generate SPARQL stub for inserting this object in a multi INSERT query.
391
392        Args:
393            uniq_id: unique string identifier with a combination of input set and defect ids
394
395        Returns:
396            SPARQL insert statement without INSERT, PREFIXES or WHERE clause
397        """
398        return """
399            senso:__VaryingThicknessDefect_{uniq_id} a senso:VaryingThicknessDefect ;
400                co:value {fvc} ;
401                senso:hasCellNumber {cell_id} ;
402                senso:hasLayerNumber {layer_id} .
403        """.format(uniq_id=uniq_id, cell_id=self._cell_id, layer_id=self._layer_id, fvc=self._fvc)
404
405    @staticmethod
406    def get_all_entries_from_store(conn: StoreConnection) -> dict:
407        """Get all instances of VaryingThicknessDefect from store connection passed during initialization.
408
409        Args:
410            conn: Any subclass instance of StoreConnection
411        Returns:
412            dict of int -> VaryingThicknessDefect
413        """
414        query = """
415            SELECT ?x ?fvc ?cell_number ?layer_number
416            WHERE {
417                ?x a senso:VaryingThicknessDefect .
418                ?x co:value ?fvc .
419                ?x senso:hasCellNumber ?cell_number .
420                ?x senso:hasLayerNumber ?layer_number .
421            }
422            """
423        result = {}
424        for x in conn.get_data(query):
425            result[x[0]] = VaryingThicknessDefect(cell_id=int(x[2]), layer_id=int(x[3]), fvc=float(x[1]))
426        return result
427
428    def to_simulation_input_dict(self) -> dict:
429        """Return dict representation of object intended for input into process simulation."""
430        return {
431            "type": self.display_name,
432            "cell_id": self._cell_id,
433            "layer_id": self._layer_id,
434            "fvc": self._fvc
435        }
436
437    def __str__(self):
438        return "{} (Type ID {}) in cell {}, layer {}, data TBA".format(self.display_name, self.type_id, self._cell_id, self._layer_id)
439
440    def __repr__(self):
441        return "VaryingThicknessDefect(cell_id={cell_id}, layer_id={layer_id}, fvc={fvc})".format(cell_id = self._cell_id, layer_id = self._layer_id, fvc = self._fvc)
442
443
444class DefectInputDataSet(HasHDF):
445    """Input data set for future simulation containing placed defects.
446
447    Contains all info for a single simulation concerning deviations from the standard 3D model
448    Information is sorted according to cell id of the 3D model first and then layer information of
449    composite material markup second, individual defects are instances of an InputDefect subclass; 
450    implements pyiron HasHDF interface for automatic HDF5 serialization during job execution for storage
451    """
452    def __init__(self, uniq_id: int=None, defects: list=None, conn: StoreConnection=None):
453        """Initialize empty internal data storage object"""
454        self._defect_data = {}
455        self._id = uniq_id
456        self._store_connection = conn
457        if defects:
458            for defect in defects:
459                self.add_defect_to_cell(defect.get_cell_id(), defect.get_layer_id(), defect)
460
461    def get_id(self):
462        """Return id of input data set, can be None if object not saved to data storage yet"""
463        return self._id
464    
465    def get_defects_of_cell(self, cell_id: int) -> dict:
466        """Return all defects for specified cell
467
468        Args:
469            cell_id: unique cell id of associated 3D model
470
471        Returns:
472            dict of layer id to defect dicts (defect id => defect object) 
473        """
474        if cell_id not in self._defect_data:
475            return {}
476        else:
477            return self._defect_data[cell_id]
478
479    def add_defect_to_cell(self, cell_id: int, layer_id: int, defect: InputDefect):
480        """Add 1 defect,overwriting any existing defect of this specific InputDefect subclass.
481
482        Args:
483            cell_id: unique cell id of associated 3D model
484            layer_id: id of layer in material of defect
485            defect: child class of InputDefect containing defect data
486        """
487        if cell_id not in self._defect_data:
488            self._defect_data[cell_id] = {}
489        if layer_id not in self._defect_data[cell_id]:
490            self._defect_data[cell_id][layer_id] = {}
491        self._defect_data[cell_id][layer_id][defect.type_id] = defect
492
493    def clear_defects_of_cell(self, cell_id: int):
494        """Remove all defects of specific cell"""
495        if cell_id in self._defect_data:
496            self._defect_data.pop(cell_id)
497
498    def generate_input_file(self):
499        print("generate the calculix input file i guess")
500
501    def generate_defect_display_summary(self) -> dict:
502        """Generate summary containing ids of all cells with defects and list of contained defect types, disregarding layer information.
503
504        Returns:
505            dictionary containing list of cells of with defects and list of defect types per cell
506        """
507        summary = {
508            "defect_cells": list(self._defect_data.keys()),
509            "cell_defect_types": {}
510        }
511        for vtk_id, layers in self._defect_data.items():
512            summary["cell_defect_types"][vtk_id] = []
513            for layer_id, layer_data in layers.items():
514                summary["cell_defect_types"][vtk_id].extend(layer_data.keys())
515            summary["cell_defect_types"][vtk_id] = list(set(summary["cell_defect_types"][vtk_id]))
516        return summary
517
518    def generate_input_set_display_label(self) -> str:
519        """Return string display for object in list displays."""
520        summ = self.get_defects()
521        c = Counter([x.type_id for x in summ])
522        occurence_string = ", ".join(["{}: {}".format(value, count) for value, count in c.most_common()])
523        return "Total: {} | {}".format(c.total(), occurence_string)
524
525    def get_defects(self) -> list:
526        """Get all defect objects of input set
527        
528        Returns:
529            list of InputDefect objects
530        """
531        defects = []
532        for _, cell_data in self._defect_data.items():
533            for _, layer_data in cell_data.items():
534                for defect_id, defect in layer_data.items():
535                    defects.append(defect)
536        return defects
537
538    @staticmethod
539    def get_available_defect_types() -> list:
540        """Return all subclasses of the class InputDefect"""
541        return InputDefect.__subclasses__()
542
543    def generate_ontology_label(self) -> str:
544        """Generate ontology instance iri from object."""
545        return "__DefectPlacementInputSet_{}".format(self._id)
546
547    @staticmethod
548    def get_id_from_ontology_iri(label: str) -> int:
549        """Extract id from full ontology instance iri."""
550        return int(label.split("_")[-1])
551
552    def generate_store_insert_stub(self, uniq_id):
553        return """
554            senso:__DefectPlacementInputSet_{uniq_id} a senso:DefectPlacementInputSet .
555        """.format(uniq_id=uniq_id)
556
557    def save_entry_to_store(self, set_id: int):
558        """Save object to store connection passed during initialization."""
559        self._id = set_id
560        label = self.generate_ontology_label()
561        insert_stubs = [self.generate_store_insert_stub(self._id)]
562        for i, defect in enumerate(self.get_defects()):
563            new_id = "{}_{}".format(self._id, i)
564            insert_stubs.append(defect.generate_store_insert_stub(new_id))  
565        query = """
566            INSERT {{
567            {stubs}
568            }} WHERE {{ }}
569            """.format(stubs="\n".join(insert_stubs))
570        self._store_connection.update_data(query)
571
572    @staticmethod
573    def get_all_entries_from_store(conn: StoreConnection) -> dict:
574        """Get all instances of DefectInputDataSet from store connection passed during initialization.
575
576        Args:
577            conn: Any subclass instance of StoreConnection
578        Returns:
579            dict of int -> DefectInputDataSet
580        """
581        defects = {}
582        for defect_type in DefectInputDataSet.get_available_defect_types():
583            defects[defect_type.__name__] = defect_type.get_all_entries_from_store(conn)
584        query = """ 
585            SELECT DISTINCT ?x
586            WHERE {
587              ?x a senso:DefectPlacementInputSet .
588            }
589            """
590        result = {}
591        for x in conn.get_data(query):
592            uniq_id = DefectInputDataSet.get_id_from_ontology_iri(x[0])
593            result[uniq_id] = DefectInputDataSet(uniq_id=uniq_id, conn=conn)
594        for defect_type, defect_dict in defects.items():
595            for iri, defect in defect_dict.items():
596                set_id = defect.get_set_id_from_ontology_iri(iri)
597                result[set_id].add_defect_to_cell(defect.get_cell_id(), defect.get_layer_id(), defect)
598        return result
599
600    def __str__(self):
601        summ = self.get_defects()
602        c = Counter([x.display_name for x in summ])
603        occurence_string = ", ".join(["{}: {}".format(value, count) for value, count in c.most_common()])
604        return "DefectInputDataSet ID {} with {} defects: {}".format(self._id, c.total(), occurence_string)
605
606    def __repr__(self):
607        return "DefectInputDataSet(uniq_id={uniq_id}, defects={defects}, conn={conn})".format(uniq_id=self._id,defects=repr(self.get_defects()),conn=repr(self._store_connection))
608
609    def _to_hdf(self, hdf=None, group_name=None):
610        with hdf.open("defect_placement_input_data") as hdf_store:
611            hdf_store["_id"] = self._id
612            hdf_store["_defects"] = repr(self.get_defects())
613            hdf_store["_store_connection"] = repr(self._store_connection)
614
615    def _from_hdf(self, hdf=None, version=None):
616        pass
617
618    def from_hdf_args(hdf):
619        with hdf.open("defect_placement_input_data") as hdf_store:
620            arg_dict = {
621                "uniq_id": hdf_store["_id"], 
622                "defects": eval(hdf_store["_defects"]),
623                "conn": eval(hdf_store["_store_connection"])
624            }
625        return arg_dict
626
627
628class CellLayersDataSet:
629    """Data set containing information about layer structure of all cells.
630
631    reads data from .vtt file containing information about the different layers for each cell of the 3D model
632    expects vtk table structure according to following definition:
633    
634    "element_label": int (id of associated cell), starting at 1
635    "layer_id": int (id of layer, unique per cell)
636    "layer_material": str (layer material name)
637    "layer_thickness_mm": float (thickness of layer in mm)
638    "layer_angle_deg": int (angle of fiber alignment in °, [-90 to 90])
639
640    """
641    NECESSARY_KEYS = ["element_label", "layer_id", "layer_material", "layer_thickness_mm", "layer_angle_deg"]
642    def __init__(self, vtt_path: str):
643        """Initialise data set from file and check if necessary columns are present.
644
645        Args:
646            vtt_path: full or relative path of .vtt file containing cell information table
647        """
648        self._file_path = vtt_path
649        self._dataframe = read_vtt.get_dataframe(self._file_path)
650        self.check_data_source()
651        self._dataframe.layer_material.replace(to_replace={"SAERTEX-U-E-SKIN": "GLASS-U-E-SKIN","SAERTEX-U-E-WEB": "GLASS-U-E-WEB", "E-LT-5500(UD)": "GLASS-UD"}, inplace=True)
652
653    def get_available_layers_for_cell(self, cell_id: int) -> pd.DataFrame:
654        """Return dataframe containing the data subset of the passed cell_id """
655        return self._dataframe.loc[self._dataframe.element_label == cell_id]
656
657    def get_layer_of_cell(self, cell_id: int, layer_id: int) -> pd.DataFrame:
658        """Return one specific entry to dataset with the correct combination of cell id and layer id"""
659        return self._dataframe.loc[(self._dataframe.element_label == cell_id) & (self._dataframe.layer_id == layer_id)].iloc[0]
660
661    def check_data_source(self):
662        """Check if data source contains all necessary keys.
663        
664        Raises:
665            KeyError: If any key as defined in NECESSARY_KEYS is not found
666            ValueError: If serial ids in element_label do not start with 1
667        """
668        for key in self.NECESSARY_KEYS:
669            if key not in self._dataframe:
670                raise KeyError("'{}' not found in input data '{}'".format(key, self._file_path))
671        if self._dataframe["element_label"].min() != 1:
672            raise ValueError("Serial IDs in 'element_label' need to start at 1, minimum value found: {}".format(self._dataframe["element_label"].min()))
673
674    def __str__(self):
675        return "CellLayersDataSet with {} cells with up to {} layers per cell".format(len(self._dataframe["element_label"].unique()), len(self._dataframe["layer_id"].unique()))
676
677    def __repr__(self):
678        return self.__str__()
679
680
681def get_material_color(name: str) -> str:
682    """Get color for specific layer in matplotlib material layup display."""
683    color_dict = defaultdict(lambda: 'white')
684    color_dict['gelcoat'] = 'red'
685    color_dict['GELCOAT'] = 'red'
686    color_dict['SNL(Triax)'] = 'green'
687    color_dict['saertex(DB)'] = 'blue'
688    color_dict['foam'] = 'yellow'
689    color_dict['FOAM'] = 'yellow'
690    color_dict['Carbon(UD)'] = 'cyan'
691    color_dict['CARBON(UD)'] = 'cyan'
692    color_dict['E-LT-5500(UD)'] = 'salmon'
693    color_dict["GLASS-UD"] = 'salmon'
694    color_dict['E-LT-5500(UD)-SKIN'] = 'orange'
695    color_dict['GLASS-TRIAX'] = 'orange'
696    color_dict['E-LT-5500(UD)-WEB'] = 'peachpuff'
697    color_dict['SAERTEX-U-E-SKIN'] = 'orange'
698    color_dict['SAERTEX-U-E-WEB'] = 'peachpuff'
699    color_dict['GLASS-U-E-SKIN'] = 'orange'
700    color_dict['GLASS-U-E-WEB'] = 'peachpuff'
701    return color_dict[name]
class InputDefect(abc.ABC):
10class InputDefect(ABC):
11    """Base class for all defect types, only used to search for available defect types via __subclasses__.
12    
13    Attributes:
14        type_id: every subclass must have unique integer id, creating an uninterruped serial starting from 1 to total number of subclasses
15    """
16    type_id = 0
17    _id = None
18    @abstractmethod
19    def __init__(self):
20        pass
21
22    @abstractmethod
23    def generate_display_label(self):
24        pass
25
26    @abstractmethod
27    def generate_ontology_label(self, set_id, iter_id):
28        pass
29
30    @abstractmethod
31    def generate_store_insert_stub(self):
32        pass
33
34    @staticmethod
35    @abstractmethod
36    def get_all_entries_from_store(conn):
37        pass
38
39    def get_cell_id(self) -> int:
40        """Return cell position of defect."""
41        return self._cell_id
42
43    def get_layer_id(self) -> int:
44        """Return layer position of defect."""
45        return self._layer_id
46
47    @staticmethod
48    def get_id_from_ontology_iri(label) -> int:
49        """Extract defect id from full ontology instance iri."""
50        return int(label.split("_")[-1])
51
52    @staticmethod
53    def get_set_id_from_ontology_iri(label) -> int:
54        """Extract input set id from full ontology instance iri."""
55        return int(label.split("_")[-2])

Base class for all defect types, only used to search for available defect types via __subclasses__.

Attributes: type_id: every subclass must have unique integer id, creating an uninterruped serial starting from 1 to total number of subclasses

type_id = 0
@abstractmethod
def generate_display_label(self):
22    @abstractmethod
23    def generate_display_label(self):
24        pass
@abstractmethod
def generate_ontology_label(self, set_id, iter_id):
26    @abstractmethod
27    def generate_ontology_label(self, set_id, iter_id):
28        pass
@abstractmethod
def generate_store_insert_stub(self):
30    @abstractmethod
31    def generate_store_insert_stub(self):
32        pass
@staticmethod
@abstractmethod
def get_all_entries_from_store(conn):
34    @staticmethod
35    @abstractmethod
36    def get_all_entries_from_store(conn):
37        pass
def get_cell_id(self) -> int:
39    def get_cell_id(self) -> int:
40        """Return cell position of defect."""
41        return self._cell_id

Return cell position of defect.

def get_layer_id(self) -> int:
43    def get_layer_id(self) -> int:
44        """Return layer position of defect."""
45        return self._layer_id

Return layer position of defect.

@staticmethod
def get_id_from_ontology_iri(label) -> int:
47    @staticmethod
48    def get_id_from_ontology_iri(label) -> int:
49        """Extract defect id from full ontology instance iri."""
50        return int(label.split("_")[-1])

Extract defect id from full ontology instance iri.

@staticmethod
def get_set_id_from_ontology_iri(label) -> int:
52    @staticmethod
53    def get_set_id_from_ontology_iri(label) -> int:
54        """Extract input set id from full ontology instance iri."""
55        return int(label.split("_")[-2])

Extract input set id from full ontology instance iri.

class PlyWavinessDefect(InputDefect):
 58class PlyWavinessDefect(InputDefect):
 59    """Ply waviness defect.
 60
 61    Attributes:
 62        type_id: Integer unique among all subclasses of InputDefect belonging to one specific defect input set
 63        display_name: Human readable name of defect type for legends
 64        display_color: tuple of RGB color values scaled from 0 to 1
 65    """
 66    data = None
 67    type_id = 1
 68    display_name = "Ply Waviness"
 69    display_color = (200 / 256, 200 / 256, 0 / 256)
 70
 71    def __init__(self, cell_id: int=None, layer_id: int=None, orientation: float=None, length: float=None, amplitude: float=None):
 72        """Initialize object.
 73
 74        Args:
 75            cell_id: integer cell id from 3D mesh of wind turbine
 76            layer_id: integer layer id from 3D mesh of wind turbine
 77            orientation: orientation of waviness in °
 78            length: length of waviness in m
 79            amplitude: amplitude of waviness in m
 80        """
 81        self._cell_id = cell_id
 82        self._layer_id = layer_id
 83        self._orientation = orientation
 84        self._length = length
 85        self._amplitude = amplitude
 86
 87    def generate_display_label(self):
 88        """Return string display for object in list displays."""
 89        return "{}, O: {}°, L: {}m, A: {}m".format(self.display_name, self._orientation, self._length, self._amplitude)
 90
 91    def generate_ontology_label(self, set_id: int, iter_id: int) -> str:
 92        """Generate ontology instance iri from object.
 93
 94        Args:
 95            set_id: id of input set this defect belongs to
 96            iter_id: unique id of defect within this specific input set
 97
 98        Returns:
 99            relative iri of ontology instance
100        """
101        return "__PlyWavinessDefect_{set_id}_{iter_id}".format(set_id=set_id, iter_id=iter_id)
102
103    def generate_store_insert_stub(self, uniq_id: str) -> str:
104        """Generate SPARQL stub for inserting this object in a multi INSERT query.
105
106        Args:
107            uniq_id: unique string identifier with a combination of input set and defect ids
108
109        Returns:
110            SPARQL insert statement without INSERT, PREFIXES or WHERE clause
111        """
112        return """
113            senso:__PlyWavinessDefect_{uniq_id} a senso:PlyWavinessDefect ;
114                senso:defectOrientation {orientation} ;
115                senso:defectLength {length} ;
116                senso:defectAmplitude {amplitude} ;
117                senso:hasCellNumber {cell_id} ;
118                senso:hasLayerNumber {layer_id} .
119        """.format(uniq_id=uniq_id, cell_id=self._cell_id, layer_id=self._layer_id, orientation=self._orientation, length=self._length, amplitude=self._amplitude)
120
121    @staticmethod
122    def get_all_entries_from_store(conn: StoreConnection) -> dict:
123        """Get all instances of PlyWavinessDefect from store connection passed during initialization.
124
125        Args:
126            conn: Any subclass instance of StoreConnection
127        Returns:
128            dict of int -> PlyWavinessDefect
129        """
130        query = """
131            SELECT ?x ?cell_number ?layer_number ?orientation ?length ?amplitude
132            WHERE {
133                ?x a senso:PlyWavinessDefect .
134                ?x senso:defectOrientation ?orientation .
135                ?x senso:defectLength ?length .
136                ?x senso:defectAmplitude ?amplitude .
137                ?x senso:hasCellNumber ?cell_number .
138                ?x senso:hasLayerNumber ?layer_number .
139            }
140            """
141        result = {}
142        for x in conn.get_data(query):
143            result[x[0]] = PlyWavinessDefect(cell_id=int(x[1]), layer_id=int(x[2]), orientation=float(x[3]), length=float(x[4]), amplitude=float(x[5]))
144        return result
145
146    def to_simulation_input_dict(self) -> dict:
147        """Return dict representation of object intended for input into process simulation."""
148        return {
149            "type": self.display_name,
150            "cell_id": self._cell_id,
151            "layer_id": self._layer_id,
152            "absolute_local_ply_orientation": self._orientation,
153            "amplitude": self._amplitude,
154            "length": self._length
155        }
156
157    def __str__(self):
158        return "{} (Type ID {}) in cell {}, layer {}, data TBA".format(self.display_name, self.type_id, self._cell_id, self._layer_id)
159
160    def __repr__(self):
161        return "PlyWavinessDefect(cell_id={cell_id}, layer_id={layer_id}, orientation={orientation}, length={length}, amplitude={amplitude})".format(
162            cell_id = self._cell_id,
163            layer_id = self._layer_id,
164            orientation = self._orientation,
165            length = self._length,
166            amplitude = self._amplitude)

Ply waviness defect.

Attributes: type_id: Integer unique among all subclasses of InputDefect belonging to one specific defect input set display_name: Human readable name of defect type for legends display_color: tuple of RGB color values scaled from 0 to 1

PlyWavinessDefect( cell_id: int = None, layer_id: int = None, orientation: float = None, length: float = None, amplitude: float = None)
71    def __init__(self, cell_id: int=None, layer_id: int=None, orientation: float=None, length: float=None, amplitude: float=None):
72        """Initialize object.
73
74        Args:
75            cell_id: integer cell id from 3D mesh of wind turbine
76            layer_id: integer layer id from 3D mesh of wind turbine
77            orientation: orientation of waviness in °
78            length: length of waviness in m
79            amplitude: amplitude of waviness in m
80        """
81        self._cell_id = cell_id
82        self._layer_id = layer_id
83        self._orientation = orientation
84        self._length = length
85        self._amplitude = amplitude

Initialize object.

Args: cell_id: integer cell id from 3D mesh of wind turbine layer_id: integer layer id from 3D mesh of wind turbine orientation: orientation of waviness in ° length: length of waviness in m amplitude: amplitude of waviness in m

data = None
type_id = 1
display_name = 'Ply Waviness'
display_color = (0.78125, 0.78125, 0.0)
def generate_display_label(self):
87    def generate_display_label(self):
88        """Return string display for object in list displays."""
89        return "{}, O: {}°, L: {}m, A: {}m".format(self.display_name, self._orientation, self._length, self._amplitude)

Return string display for object in list displays.

def generate_ontology_label(self, set_id: int, iter_id: int) -> str:
 91    def generate_ontology_label(self, set_id: int, iter_id: int) -> str:
 92        """Generate ontology instance iri from object.
 93
 94        Args:
 95            set_id: id of input set this defect belongs to
 96            iter_id: unique id of defect within this specific input set
 97
 98        Returns:
 99            relative iri of ontology instance
100        """
101        return "__PlyWavinessDefect_{set_id}_{iter_id}".format(set_id=set_id, iter_id=iter_id)

Generate ontology instance iri from object.

Args: set_id: id of input set this defect belongs to iter_id: unique id of defect within this specific input set

Returns: relative iri of ontology instance

def generate_store_insert_stub(self, uniq_id: str) -> str:
103    def generate_store_insert_stub(self, uniq_id: str) -> str:
104        """Generate SPARQL stub for inserting this object in a multi INSERT query.
105
106        Args:
107            uniq_id: unique string identifier with a combination of input set and defect ids
108
109        Returns:
110            SPARQL insert statement without INSERT, PREFIXES or WHERE clause
111        """
112        return """
113            senso:__PlyWavinessDefect_{uniq_id} a senso:PlyWavinessDefect ;
114                senso:defectOrientation {orientation} ;
115                senso:defectLength {length} ;
116                senso:defectAmplitude {amplitude} ;
117                senso:hasCellNumber {cell_id} ;
118                senso:hasLayerNumber {layer_id} .
119        """.format(uniq_id=uniq_id, cell_id=self._cell_id, layer_id=self._layer_id, orientation=self._orientation, length=self._length, amplitude=self._amplitude)

Generate SPARQL stub for inserting this object in a multi INSERT query.

Args: uniq_id: unique string identifier with a combination of input set and defect ids

Returns: SPARQL insert statement without INSERT, PREFIXES or WHERE clause

@staticmethod
def get_all_entries_from_store(conn: sensotwin.store_connection.StoreConnection) -> dict:
121    @staticmethod
122    def get_all_entries_from_store(conn: StoreConnection) -> dict:
123        """Get all instances of PlyWavinessDefect from store connection passed during initialization.
124
125        Args:
126            conn: Any subclass instance of StoreConnection
127        Returns:
128            dict of int -> PlyWavinessDefect
129        """
130        query = """
131            SELECT ?x ?cell_number ?layer_number ?orientation ?length ?amplitude
132            WHERE {
133                ?x a senso:PlyWavinessDefect .
134                ?x senso:defectOrientation ?orientation .
135                ?x senso:defectLength ?length .
136                ?x senso:defectAmplitude ?amplitude .
137                ?x senso:hasCellNumber ?cell_number .
138                ?x senso:hasLayerNumber ?layer_number .
139            }
140            """
141        result = {}
142        for x in conn.get_data(query):
143            result[x[0]] = PlyWavinessDefect(cell_id=int(x[1]), layer_id=int(x[2]), orientation=float(x[3]), length=float(x[4]), amplitude=float(x[5]))
144        return result

Get all instances of PlyWavinessDefect from store connection passed during initialization.

Args: conn: Any subclass instance of StoreConnection Returns: dict of int -> PlyWavinessDefect

def to_simulation_input_dict(self) -> dict:
146    def to_simulation_input_dict(self) -> dict:
147        """Return dict representation of object intended for input into process simulation."""
148        return {
149            "type": self.display_name,
150            "cell_id": self._cell_id,
151            "layer_id": self._layer_id,
152            "absolute_local_ply_orientation": self._orientation,
153            "amplitude": self._amplitude,
154            "length": self._length
155        }

Return dict representation of object intended for input into process simulation.

class PlyMisorientationDefect(InputDefect):
169class PlyMisorientationDefect(InputDefect):
170    """Defect for different fibre angle in layer than intended.
171
172    Attributes:
173        type_id: Integer unique among all subclasses of InputDefect belonging to one specific defect input set
174        display_name: Human readable name of defect type for legends
175        display_color: tuple of RGB color values scaled from 0 to 1
176    """
177    data = None
178    type_id = 2
179    display_name = "Ply Misorientation"
180    display_color = (12 / 256, 238 / 256, 246 / 256)
181
182    def __init__(self, cell_id: int=None, layer_id: int=None, angle: float=None):
183        """Initialize object.
184
185        Args:
186            cell_id: integer cell id from 3D mesh of wind turbine
187            layer_id: integer layer id from 3D mesh of wind turbine
188            angle: relative deviation from intended angle in °
189        """
190        self._cell_id = cell_id
191        self._layer_id = layer_id
192        self._angle = angle
193
194    def generate_display_label(self) -> str:
195        """Return string display for object in list displays."""
196        return "{}, Offset: {}°".format(self.display_name, self._angle)
197
198    def generate_ontology_label(self, set_id: int, iter_id: int) -> str:
199        """Generate ontology instance iri from object.
200
201        Args:
202            set_id: id of input set this defect belongs to
203            iter_id: unique id of defect within this specific input set
204
205        Returns:
206            relative iri of ontology instance
207        """
208        return "__PlyMisorientationDefect_{set_id}_{iter_id}".format(set_id=set_id, iter_id=iter_id)
209
210    def generate_store_insert_stub(self, uniq_id: str) -> str:
211        """Generate SPARQL stub for inserting this object in a multi INSERT query.
212
213        Args:
214            uniq_id: unique string identifier with a combination of input set and defect ids
215
216        Returns:
217            SPARQL insert statement without INSERT, PREFIXES or WHERE clause
218        """
219        return """
220            senso:__PlyMisorientationDefect_{uniq_id} a senso:PlyMisorientationDefect ;
221                co:value {angle} ;
222                senso:hasCellNumber {cell_id} ;
223                senso:hasLayerNumber {layer_id} .
224        """.format(uniq_id=uniq_id, cell_id=self._cell_id, layer_id=self._layer_id, angle=self._angle)
225
226    @staticmethod
227    def get_all_entries_from_store(conn: StoreConnection) -> dict:
228        """Get all instances of PlyMisorientationDefect from store connection passed during initialization.
229
230        Args:
231            conn: Any subclass instance of StoreConnection
232        Returns:
233            dict of int -> PlyMisorientationDefect
234        """
235        query = """
236            SELECT ?x ?angle ?cell_number ?layer_number
237            WHERE {
238                ?x a senso:PlyMisorientationDefect .
239                ?x co:value ?angle .
240                ?x senso:hasCellNumber ?cell_number .
241                ?x senso:hasLayerNumber ?layer_number .
242            }
243            """
244        result = {}
245        for x in conn.get_data(query):
246            result[x[0]] = PlyMisorientationDefect(cell_id=int(x[2]), layer_id=int(x[3]), angle=float(x[1]))
247        return result
248
249    def to_simulation_input_dict(self) -> dict:
250        """Return dict representation of object intended for input into process simulation."""
251        return {
252            "type": self.display_name,
253            "cell_id": self._cell_id,
254            "layer_id": self._layer_id,
255            "local_angular_deviation": self._angle
256        }
257
258    def __str__(self):
259        return "{} (Type ID {}) in cell {}, layer {}, data TBA".format(self.display_name, self.type_id, self._cell_id, self._layer_id)
260
261    def __repr__(self):
262        return "PlyMisorientationDefect(cell_id={cell_id}, layer_id={layer_id}, angle={angle})".format(cell_id = self._cell_id, layer_id = self._layer_id, angle = self._angle)

Defect for different fibre angle in layer than intended.

Attributes: type_id: Integer unique among all subclasses of InputDefect belonging to one specific defect input set display_name: Human readable name of defect type for legends display_color: tuple of RGB color values scaled from 0 to 1

PlyMisorientationDefect(cell_id: int = None, layer_id: int = None, angle: float = None)
182    def __init__(self, cell_id: int=None, layer_id: int=None, angle: float=None):
183        """Initialize object.
184
185        Args:
186            cell_id: integer cell id from 3D mesh of wind turbine
187            layer_id: integer layer id from 3D mesh of wind turbine
188            angle: relative deviation from intended angle in °
189        """
190        self._cell_id = cell_id
191        self._layer_id = layer_id
192        self._angle = angle

Initialize object.

Args: cell_id: integer cell id from 3D mesh of wind turbine layer_id: integer layer id from 3D mesh of wind turbine angle: relative deviation from intended angle in °

data = None
type_id = 2
display_name = 'Ply Misorientation'
display_color = (0.046875, 0.9296875, 0.9609375)
def generate_display_label(self) -> str:
194    def generate_display_label(self) -> str:
195        """Return string display for object in list displays."""
196        return "{}, Offset: {}°".format(self.display_name, self._angle)

Return string display for object in list displays.

def generate_ontology_label(self, set_id: int, iter_id: int) -> str:
198    def generate_ontology_label(self, set_id: int, iter_id: int) -> str:
199        """Generate ontology instance iri from object.
200
201        Args:
202            set_id: id of input set this defect belongs to
203            iter_id: unique id of defect within this specific input set
204
205        Returns:
206            relative iri of ontology instance
207        """
208        return "__PlyMisorientationDefect_{set_id}_{iter_id}".format(set_id=set_id, iter_id=iter_id)

Generate ontology instance iri from object.

Args: set_id: id of input set this defect belongs to iter_id: unique id of defect within this specific input set

Returns: relative iri of ontology instance

def generate_store_insert_stub(self, uniq_id: str) -> str:
210    def generate_store_insert_stub(self, uniq_id: str) -> str:
211        """Generate SPARQL stub for inserting this object in a multi INSERT query.
212
213        Args:
214            uniq_id: unique string identifier with a combination of input set and defect ids
215
216        Returns:
217            SPARQL insert statement without INSERT, PREFIXES or WHERE clause
218        """
219        return """
220            senso:__PlyMisorientationDefect_{uniq_id} a senso:PlyMisorientationDefect ;
221                co:value {angle} ;
222                senso:hasCellNumber {cell_id} ;
223                senso:hasLayerNumber {layer_id} .
224        """.format(uniq_id=uniq_id, cell_id=self._cell_id, layer_id=self._layer_id, angle=self._angle)

Generate SPARQL stub for inserting this object in a multi INSERT query.

Args: uniq_id: unique string identifier with a combination of input set and defect ids

Returns: SPARQL insert statement without INSERT, PREFIXES or WHERE clause

@staticmethod
def get_all_entries_from_store(conn: sensotwin.store_connection.StoreConnection) -> dict:
226    @staticmethod
227    def get_all_entries_from_store(conn: StoreConnection) -> dict:
228        """Get all instances of PlyMisorientationDefect from store connection passed during initialization.
229
230        Args:
231            conn: Any subclass instance of StoreConnection
232        Returns:
233            dict of int -> PlyMisorientationDefect
234        """
235        query = """
236            SELECT ?x ?angle ?cell_number ?layer_number
237            WHERE {
238                ?x a senso:PlyMisorientationDefect .
239                ?x co:value ?angle .
240                ?x senso:hasCellNumber ?cell_number .
241                ?x senso:hasLayerNumber ?layer_number .
242            }
243            """
244        result = {}
245        for x in conn.get_data(query):
246            result[x[0]] = PlyMisorientationDefect(cell_id=int(x[2]), layer_id=int(x[3]), angle=float(x[1]))
247        return result

Get all instances of PlyMisorientationDefect from store connection passed during initialization.

Args: conn: Any subclass instance of StoreConnection Returns: dict of int -> PlyMisorientationDefect

def to_simulation_input_dict(self) -> dict:
249    def to_simulation_input_dict(self) -> dict:
250        """Return dict representation of object intended for input into process simulation."""
251        return {
252            "type": self.display_name,
253            "cell_id": self._cell_id,
254            "layer_id": self._layer_id,
255            "local_angular_deviation": self._angle
256        }

Return dict representation of object intended for input into process simulation.

class MissingPlyDefect(InputDefect):
265class MissingPlyDefect(InputDefect):
266    """Defect for an entire layer missing.
267
268    Attributes:
269        type_id: Integer unique among all subclasses of InputDefect belonging to one specific defect input set
270        display_name: Human readable name of defect type for legends
271        display_color: tuple of RGB color values scaled from 0 to 1
272    """
273    data = None
274    type_id = 3
275    display_name = "Missing Ply"
276    display_color = (25 / 256, 248 / 256, 5 / 256)
277
278    def __init__(self, cell_id: int=None, layer_id: int=None):
279        """Initialize object.
280
281        Args:
282            cell_id: integer cell id from 3D mesh of wind turbine
283            layer_id: integer layer id from 3D mesh of wind turbine
284        """
285        self._cell_id = cell_id
286        self._layer_id = layer_id
287
288    def generate_display_label(self) -> str:
289        """Return string display for object in list displays."""
290        return "{}, Ply missing".format(self.display_name)
291
292    def generate_ontology_label(self, set_id, iter_id):
293        """Generate ontology instance iri from object.
294
295        Args:
296            set_id: id of input set this defect belongs to
297            iter_id: unique id of defect within this specific input set
298
299        Returns:
300            relative iri of ontology instance
301        """
302        return "__MissingPlyDefect_{set_id}_{iter_id}".format(set_id=set_id, iter_id=iter_id)
303
304    def generate_store_insert_stub(self, uniq_id: str) -> str:
305        """Generate SPARQL stub for inserting this object in a multi INSERT query.
306
307        Args:
308            uniq_id: unique string identifier with a combination of input set and defect ids
309
310        Returns:
311            SPARQL insert statement without INSERT, PREFIXES or WHERE clause
312        """
313        return """
314            senso:__MissingPlyDefect_{uniq_id} a senso:MissingPlyDefect ;
315                senso:hasCellNumber {cell_id} ;
316                senso:hasLayerNumber {layer_id} .
317        """.format(uniq_id=uniq_id, cell_id=self._cell_id, layer_id=self._layer_id)
318
319    @staticmethod
320    def get_all_entries_from_store(conn: StoreConnection) -> dict:
321        """Get all instances of MissingPlyDefect from store connection passed during initialization.
322
323        Args:
324            conn: Any subclass instance of StoreConnection
325        Returns:
326            dict of int -> MissingPlyDefect
327        """
328        query = """
329            SELECT ?x ?cell_number ?layer_number
330            WHERE {
331                ?x a senso:MissingPlyDefect .
332                ?x senso:hasCellNumber ?cell_number .
333                ?x senso:hasLayerNumber ?layer_number .
334            }
335            """
336        result = {}
337        for x in conn.get_data(query):
338            result[x[0]] = MissingPlyDefect(cell_id=int(x[1]), layer_id=int(x[2]))
339        return result
340
341    def to_simulation_input_dict(self) -> dict:
342        """Return dict representation of object intended for input into process simulation."""
343        return {
344            "type": self.display_name,
345            "cell_id": self._cell_id,
346            "layer_id": self._layer_id,
347        }
348
349    def __str__(self):
350        return "{} (Type ID {}) in cell {}, layer {}, data TBA".format(self.display_name, self.type_id, self._cell_id, self._layer_id)
351
352    def __repr__(self):
353        return "MissingPlyDefect(cell_id={cell_id}, layer_id={layer_id})".format(cell_id = self._cell_id, layer_id = self._layer_id)

Defect for an entire layer missing.

Attributes: type_id: Integer unique among all subclasses of InputDefect belonging to one specific defect input set display_name: Human readable name of defect type for legends display_color: tuple of RGB color values scaled from 0 to 1

MissingPlyDefect(cell_id: int = None, layer_id: int = None)
278    def __init__(self, cell_id: int=None, layer_id: int=None):
279        """Initialize object.
280
281        Args:
282            cell_id: integer cell id from 3D mesh of wind turbine
283            layer_id: integer layer id from 3D mesh of wind turbine
284        """
285        self._cell_id = cell_id
286        self._layer_id = layer_id

Initialize object.

Args: cell_id: integer cell id from 3D mesh of wind turbine layer_id: integer layer id from 3D mesh of wind turbine

data = None
type_id = 3
display_name = 'Missing Ply'
display_color = (0.09765625, 0.96875, 0.01953125)
def generate_display_label(self) -> str:
288    def generate_display_label(self) -> str:
289        """Return string display for object in list displays."""
290        return "{}, Ply missing".format(self.display_name)

Return string display for object in list displays.

def generate_ontology_label(self, set_id, iter_id):
292    def generate_ontology_label(self, set_id, iter_id):
293        """Generate ontology instance iri from object.
294
295        Args:
296            set_id: id of input set this defect belongs to
297            iter_id: unique id of defect within this specific input set
298
299        Returns:
300            relative iri of ontology instance
301        """
302        return "__MissingPlyDefect_{set_id}_{iter_id}".format(set_id=set_id, iter_id=iter_id)

Generate ontology instance iri from object.

Args: set_id: id of input set this defect belongs to iter_id: unique id of defect within this specific input set

Returns: relative iri of ontology instance

def generate_store_insert_stub(self, uniq_id: str) -> str:
304    def generate_store_insert_stub(self, uniq_id: str) -> str:
305        """Generate SPARQL stub for inserting this object in a multi INSERT query.
306
307        Args:
308            uniq_id: unique string identifier with a combination of input set and defect ids
309
310        Returns:
311            SPARQL insert statement without INSERT, PREFIXES or WHERE clause
312        """
313        return """
314            senso:__MissingPlyDefect_{uniq_id} a senso:MissingPlyDefect ;
315                senso:hasCellNumber {cell_id} ;
316                senso:hasLayerNumber {layer_id} .
317        """.format(uniq_id=uniq_id, cell_id=self._cell_id, layer_id=self._layer_id)

Generate SPARQL stub for inserting this object in a multi INSERT query.

Args: uniq_id: unique string identifier with a combination of input set and defect ids

Returns: SPARQL insert statement without INSERT, PREFIXES or WHERE clause

@staticmethod
def get_all_entries_from_store(conn: sensotwin.store_connection.StoreConnection) -> dict:
319    @staticmethod
320    def get_all_entries_from_store(conn: StoreConnection) -> dict:
321        """Get all instances of MissingPlyDefect from store connection passed during initialization.
322
323        Args:
324            conn: Any subclass instance of StoreConnection
325        Returns:
326            dict of int -> MissingPlyDefect
327        """
328        query = """
329            SELECT ?x ?cell_number ?layer_number
330            WHERE {
331                ?x a senso:MissingPlyDefect .
332                ?x senso:hasCellNumber ?cell_number .
333                ?x senso:hasLayerNumber ?layer_number .
334            }
335            """
336        result = {}
337        for x in conn.get_data(query):
338            result[x[0]] = MissingPlyDefect(cell_id=int(x[1]), layer_id=int(x[2]))
339        return result

Get all instances of MissingPlyDefect from store connection passed during initialization.

Args: conn: Any subclass instance of StoreConnection Returns: dict of int -> MissingPlyDefect

def to_simulation_input_dict(self) -> dict:
341    def to_simulation_input_dict(self) -> dict:
342        """Return dict representation of object intended for input into process simulation."""
343        return {
344            "type": self.display_name,
345            "cell_id": self._cell_id,
346            "layer_id": self._layer_id,
347        }

Return dict representation of object intended for input into process simulation.

class VaryingThicknessDefect(InputDefect):
356class VaryingThicknessDefect(InputDefect):
357    """Defect for a different layer thickness than intended.
358
359    Attributes:
360        type_id: Integer unique among all subclasses of InputDefect belonging to one specific defect input set
361        display_name: Human readable name of defect type for legends
362        display_color: tuple of RGB color values scaled from 0 to 1
363    """
364    data = None
365    type_id = 4
366    display_name = "Varying Thickness"
367    display_color = (255 / 256, 130 / 256, 3 / 256)
368
369    def __init__(self, cell_id: int=None, layer_id: int=None, fvc: float=None):
370        self._cell_id = cell_id
371        self._layer_id = layer_id
372        self._fvc = fvc
373
374    def generate_display_label(self) -> str:
375        """Return string display for object in list displays."""
376        return "{}, {}% FVC".format(self.display_name, self._fvc)
377
378    def generate_ontology_label(self, set_id: int, iter_id: int) -> str:
379        """Generate ontology instance iri from object.
380
381        Args:
382            set_id: id of input set this defect belongs to
383            iter_id: unique id of defect within this specific input set
384
385        Returns:
386            relative iri of ontology instance
387        """
388        return "__VaryingThicknessDefect__{set_id}_{iter_id}".format(set_id=set_id, iter_id=iter_id)
389
390    def generate_store_insert_stub(self, uniq_id: str) -> str:
391        """Generate SPARQL stub for inserting this object in a multi INSERT query.
392
393        Args:
394            uniq_id: unique string identifier with a combination of input set and defect ids
395
396        Returns:
397            SPARQL insert statement without INSERT, PREFIXES or WHERE clause
398        """
399        return """
400            senso:__VaryingThicknessDefect_{uniq_id} a senso:VaryingThicknessDefect ;
401                co:value {fvc} ;
402                senso:hasCellNumber {cell_id} ;
403                senso:hasLayerNumber {layer_id} .
404        """.format(uniq_id=uniq_id, cell_id=self._cell_id, layer_id=self._layer_id, fvc=self._fvc)
405
406    @staticmethod
407    def get_all_entries_from_store(conn: StoreConnection) -> dict:
408        """Get all instances of VaryingThicknessDefect from store connection passed during initialization.
409
410        Args:
411            conn: Any subclass instance of StoreConnection
412        Returns:
413            dict of int -> VaryingThicknessDefect
414        """
415        query = """
416            SELECT ?x ?fvc ?cell_number ?layer_number
417            WHERE {
418                ?x a senso:VaryingThicknessDefect .
419                ?x co:value ?fvc .
420                ?x senso:hasCellNumber ?cell_number .
421                ?x senso:hasLayerNumber ?layer_number .
422            }
423            """
424        result = {}
425        for x in conn.get_data(query):
426            result[x[0]] = VaryingThicknessDefect(cell_id=int(x[2]), layer_id=int(x[3]), fvc=float(x[1]))
427        return result
428
429    def to_simulation_input_dict(self) -> dict:
430        """Return dict representation of object intended for input into process simulation."""
431        return {
432            "type": self.display_name,
433            "cell_id": self._cell_id,
434            "layer_id": self._layer_id,
435            "fvc": self._fvc
436        }
437
438    def __str__(self):
439        return "{} (Type ID {}) in cell {}, layer {}, data TBA".format(self.display_name, self.type_id, self._cell_id, self._layer_id)
440
441    def __repr__(self):
442        return "VaryingThicknessDefect(cell_id={cell_id}, layer_id={layer_id}, fvc={fvc})".format(cell_id = self._cell_id, layer_id = self._layer_id, fvc = self._fvc)

Defect for a different layer thickness than intended.

Attributes: type_id: Integer unique among all subclasses of InputDefect belonging to one specific defect input set display_name: Human readable name of defect type for legends display_color: tuple of RGB color values scaled from 0 to 1

VaryingThicknessDefect(cell_id: int = None, layer_id: int = None, fvc: float = None)
369    def __init__(self, cell_id: int=None, layer_id: int=None, fvc: float=None):
370        self._cell_id = cell_id
371        self._layer_id = layer_id
372        self._fvc = fvc
data = None
type_id = 4
display_name = 'Varying Thickness'
display_color = (0.99609375, 0.5078125, 0.01171875)
def generate_display_label(self) -> str:
374    def generate_display_label(self) -> str:
375        """Return string display for object in list displays."""
376        return "{}, {}% FVC".format(self.display_name, self._fvc)

Return string display for object in list displays.

def generate_ontology_label(self, set_id: int, iter_id: int) -> str:
378    def generate_ontology_label(self, set_id: int, iter_id: int) -> str:
379        """Generate ontology instance iri from object.
380
381        Args:
382            set_id: id of input set this defect belongs to
383            iter_id: unique id of defect within this specific input set
384
385        Returns:
386            relative iri of ontology instance
387        """
388        return "__VaryingThicknessDefect__{set_id}_{iter_id}".format(set_id=set_id, iter_id=iter_id)

Generate ontology instance iri from object.

Args: set_id: id of input set this defect belongs to iter_id: unique id of defect within this specific input set

Returns: relative iri of ontology instance

def generate_store_insert_stub(self, uniq_id: str) -> str:
390    def generate_store_insert_stub(self, uniq_id: str) -> str:
391        """Generate SPARQL stub for inserting this object in a multi INSERT query.
392
393        Args:
394            uniq_id: unique string identifier with a combination of input set and defect ids
395
396        Returns:
397            SPARQL insert statement without INSERT, PREFIXES or WHERE clause
398        """
399        return """
400            senso:__VaryingThicknessDefect_{uniq_id} a senso:VaryingThicknessDefect ;
401                co:value {fvc} ;
402                senso:hasCellNumber {cell_id} ;
403                senso:hasLayerNumber {layer_id} .
404        """.format(uniq_id=uniq_id, cell_id=self._cell_id, layer_id=self._layer_id, fvc=self._fvc)

Generate SPARQL stub for inserting this object in a multi INSERT query.

Args: uniq_id: unique string identifier with a combination of input set and defect ids

Returns: SPARQL insert statement without INSERT, PREFIXES or WHERE clause

@staticmethod
def get_all_entries_from_store(conn: sensotwin.store_connection.StoreConnection) -> dict:
406    @staticmethod
407    def get_all_entries_from_store(conn: StoreConnection) -> dict:
408        """Get all instances of VaryingThicknessDefect from store connection passed during initialization.
409
410        Args:
411            conn: Any subclass instance of StoreConnection
412        Returns:
413            dict of int -> VaryingThicknessDefect
414        """
415        query = """
416            SELECT ?x ?fvc ?cell_number ?layer_number
417            WHERE {
418                ?x a senso:VaryingThicknessDefect .
419                ?x co:value ?fvc .
420                ?x senso:hasCellNumber ?cell_number .
421                ?x senso:hasLayerNumber ?layer_number .
422            }
423            """
424        result = {}
425        for x in conn.get_data(query):
426            result[x[0]] = VaryingThicknessDefect(cell_id=int(x[2]), layer_id=int(x[3]), fvc=float(x[1]))
427        return result

Get all instances of VaryingThicknessDefect from store connection passed during initialization.

Args: conn: Any subclass instance of StoreConnection Returns: dict of int -> VaryingThicknessDefect

def to_simulation_input_dict(self) -> dict:
429    def to_simulation_input_dict(self) -> dict:
430        """Return dict representation of object intended for input into process simulation."""
431        return {
432            "type": self.display_name,
433            "cell_id": self._cell_id,
434            "layer_id": self._layer_id,
435            "fvc": self._fvc
436        }

Return dict representation of object intended for input into process simulation.

class DefectInputDataSet(pyiron_base.interfaces.has_hdf.HasHDF):
445class DefectInputDataSet(HasHDF):
446    """Input data set for future simulation containing placed defects.
447
448    Contains all info for a single simulation concerning deviations from the standard 3D model
449    Information is sorted according to cell id of the 3D model first and then layer information of
450    composite material markup second, individual defects are instances of an InputDefect subclass; 
451    implements pyiron HasHDF interface for automatic HDF5 serialization during job execution for storage
452    """
453    def __init__(self, uniq_id: int=None, defects: list=None, conn: StoreConnection=None):
454        """Initialize empty internal data storage object"""
455        self._defect_data = {}
456        self._id = uniq_id
457        self._store_connection = conn
458        if defects:
459            for defect in defects:
460                self.add_defect_to_cell(defect.get_cell_id(), defect.get_layer_id(), defect)
461
462    def get_id(self):
463        """Return id of input data set, can be None if object not saved to data storage yet"""
464        return self._id
465    
466    def get_defects_of_cell(self, cell_id: int) -> dict:
467        """Return all defects for specified cell
468
469        Args:
470            cell_id: unique cell id of associated 3D model
471
472        Returns:
473            dict of layer id to defect dicts (defect id => defect object) 
474        """
475        if cell_id not in self._defect_data:
476            return {}
477        else:
478            return self._defect_data[cell_id]
479
480    def add_defect_to_cell(self, cell_id: int, layer_id: int, defect: InputDefect):
481        """Add 1 defect,overwriting any existing defect of this specific InputDefect subclass.
482
483        Args:
484            cell_id: unique cell id of associated 3D model
485            layer_id: id of layer in material of defect
486            defect: child class of InputDefect containing defect data
487        """
488        if cell_id not in self._defect_data:
489            self._defect_data[cell_id] = {}
490        if layer_id not in self._defect_data[cell_id]:
491            self._defect_data[cell_id][layer_id] = {}
492        self._defect_data[cell_id][layer_id][defect.type_id] = defect
493
494    def clear_defects_of_cell(self, cell_id: int):
495        """Remove all defects of specific cell"""
496        if cell_id in self._defect_data:
497            self._defect_data.pop(cell_id)
498
499    def generate_input_file(self):
500        print("generate the calculix input file i guess")
501
502    def generate_defect_display_summary(self) -> dict:
503        """Generate summary containing ids of all cells with defects and list of contained defect types, disregarding layer information.
504
505        Returns:
506            dictionary containing list of cells of with defects and list of defect types per cell
507        """
508        summary = {
509            "defect_cells": list(self._defect_data.keys()),
510            "cell_defect_types": {}
511        }
512        for vtk_id, layers in self._defect_data.items():
513            summary["cell_defect_types"][vtk_id] = []
514            for layer_id, layer_data in layers.items():
515                summary["cell_defect_types"][vtk_id].extend(layer_data.keys())
516            summary["cell_defect_types"][vtk_id] = list(set(summary["cell_defect_types"][vtk_id]))
517        return summary
518
519    def generate_input_set_display_label(self) -> str:
520        """Return string display for object in list displays."""
521        summ = self.get_defects()
522        c = Counter([x.type_id for x in summ])
523        occurence_string = ", ".join(["{}: {}".format(value, count) for value, count in c.most_common()])
524        return "Total: {} | {}".format(c.total(), occurence_string)
525
526    def get_defects(self) -> list:
527        """Get all defect objects of input set
528        
529        Returns:
530            list of InputDefect objects
531        """
532        defects = []
533        for _, cell_data in self._defect_data.items():
534            for _, layer_data in cell_data.items():
535                for defect_id, defect in layer_data.items():
536                    defects.append(defect)
537        return defects
538
539    @staticmethod
540    def get_available_defect_types() -> list:
541        """Return all subclasses of the class InputDefect"""
542        return InputDefect.__subclasses__()
543
544    def generate_ontology_label(self) -> str:
545        """Generate ontology instance iri from object."""
546        return "__DefectPlacementInputSet_{}".format(self._id)
547
548    @staticmethod
549    def get_id_from_ontology_iri(label: str) -> int:
550        """Extract id from full ontology instance iri."""
551        return int(label.split("_")[-1])
552
553    def generate_store_insert_stub(self, uniq_id):
554        return """
555            senso:__DefectPlacementInputSet_{uniq_id} a senso:DefectPlacementInputSet .
556        """.format(uniq_id=uniq_id)
557
558    def save_entry_to_store(self, set_id: int):
559        """Save object to store connection passed during initialization."""
560        self._id = set_id
561        label = self.generate_ontology_label()
562        insert_stubs = [self.generate_store_insert_stub(self._id)]
563        for i, defect in enumerate(self.get_defects()):
564            new_id = "{}_{}".format(self._id, i)
565            insert_stubs.append(defect.generate_store_insert_stub(new_id))  
566        query = """
567            INSERT {{
568            {stubs}
569            }} WHERE {{ }}
570            """.format(stubs="\n".join(insert_stubs))
571        self._store_connection.update_data(query)
572
573    @staticmethod
574    def get_all_entries_from_store(conn: StoreConnection) -> dict:
575        """Get all instances of DefectInputDataSet from store connection passed during initialization.
576
577        Args:
578            conn: Any subclass instance of StoreConnection
579        Returns:
580            dict of int -> DefectInputDataSet
581        """
582        defects = {}
583        for defect_type in DefectInputDataSet.get_available_defect_types():
584            defects[defect_type.__name__] = defect_type.get_all_entries_from_store(conn)
585        query = """ 
586            SELECT DISTINCT ?x
587            WHERE {
588              ?x a senso:DefectPlacementInputSet .
589            }
590            """
591        result = {}
592        for x in conn.get_data(query):
593            uniq_id = DefectInputDataSet.get_id_from_ontology_iri(x[0])
594            result[uniq_id] = DefectInputDataSet(uniq_id=uniq_id, conn=conn)
595        for defect_type, defect_dict in defects.items():
596            for iri, defect in defect_dict.items():
597                set_id = defect.get_set_id_from_ontology_iri(iri)
598                result[set_id].add_defect_to_cell(defect.get_cell_id(), defect.get_layer_id(), defect)
599        return result
600
601    def __str__(self):
602        summ = self.get_defects()
603        c = Counter([x.display_name for x in summ])
604        occurence_string = ", ".join(["{}: {}".format(value, count) for value, count in c.most_common()])
605        return "DefectInputDataSet ID {} with {} defects: {}".format(self._id, c.total(), occurence_string)
606
607    def __repr__(self):
608        return "DefectInputDataSet(uniq_id={uniq_id}, defects={defects}, conn={conn})".format(uniq_id=self._id,defects=repr(self.get_defects()),conn=repr(self._store_connection))
609
610    def _to_hdf(self, hdf=None, group_name=None):
611        with hdf.open("defect_placement_input_data") as hdf_store:
612            hdf_store["_id"] = self._id
613            hdf_store["_defects"] = repr(self.get_defects())
614            hdf_store["_store_connection"] = repr(self._store_connection)
615
616    def _from_hdf(self, hdf=None, version=None):
617        pass
618
619    def from_hdf_args(hdf):
620        with hdf.open("defect_placement_input_data") as hdf_store:
621            arg_dict = {
622                "uniq_id": hdf_store["_id"], 
623                "defects": eval(hdf_store["_defects"]),
624                "conn": eval(hdf_store["_store_connection"])
625            }
626        return arg_dict

Input data set for future simulation containing placed defects.

Contains all info for a single simulation concerning deviations from the standard 3D model Information is sorted according to cell id of the 3D model first and then layer information of composite material markup second, individual defects are instances of an InputDefect subclass; implements pyiron HasHDF interface for automatic HDF5 serialization during job execution for storage

DefectInputDataSet( uniq_id: int = None, defects: list = None, conn: sensotwin.store_connection.StoreConnection = None)
453    def __init__(self, uniq_id: int=None, defects: list=None, conn: StoreConnection=None):
454        """Initialize empty internal data storage object"""
455        self._defect_data = {}
456        self._id = uniq_id
457        self._store_connection = conn
458        if defects:
459            for defect in defects:
460                self.add_defect_to_cell(defect.get_cell_id(), defect.get_layer_id(), defect)

Initialize empty internal data storage object

def get_id(self):
462    def get_id(self):
463        """Return id of input data set, can be None if object not saved to data storage yet"""
464        return self._id

Return id of input data set, can be None if object not saved to data storage yet

def get_defects_of_cell(self, cell_id: int) -> dict:
466    def get_defects_of_cell(self, cell_id: int) -> dict:
467        """Return all defects for specified cell
468
469        Args:
470            cell_id: unique cell id of associated 3D model
471
472        Returns:
473            dict of layer id to defect dicts (defect id => defect object) 
474        """
475        if cell_id not in self._defect_data:
476            return {}
477        else:
478            return self._defect_data[cell_id]

Return all defects for specified cell

Args: cell_id: unique cell id of associated 3D model

Returns: dict of layer id to defect dicts (defect id => defect object)

def add_defect_to_cell( self, cell_id: int, layer_id: int, defect: InputDefect):
480    def add_defect_to_cell(self, cell_id: int, layer_id: int, defect: InputDefect):
481        """Add 1 defect,overwriting any existing defect of this specific InputDefect subclass.
482
483        Args:
484            cell_id: unique cell id of associated 3D model
485            layer_id: id of layer in material of defect
486            defect: child class of InputDefect containing defect data
487        """
488        if cell_id not in self._defect_data:
489            self._defect_data[cell_id] = {}
490        if layer_id not in self._defect_data[cell_id]:
491            self._defect_data[cell_id][layer_id] = {}
492        self._defect_data[cell_id][layer_id][defect.type_id] = defect

Add 1 defect,overwriting any existing defect of this specific InputDefect subclass.

Args: cell_id: unique cell id of associated 3D model layer_id: id of layer in material of defect defect: child class of InputDefect containing defect data

def clear_defects_of_cell(self, cell_id: int):
494    def clear_defects_of_cell(self, cell_id: int):
495        """Remove all defects of specific cell"""
496        if cell_id in self._defect_data:
497            self._defect_data.pop(cell_id)

Remove all defects of specific cell

def generate_input_file(self):
499    def generate_input_file(self):
500        print("generate the calculix input file i guess")
def generate_defect_display_summary(self) -> dict:
502    def generate_defect_display_summary(self) -> dict:
503        """Generate summary containing ids of all cells with defects and list of contained defect types, disregarding layer information.
504
505        Returns:
506            dictionary containing list of cells of with defects and list of defect types per cell
507        """
508        summary = {
509            "defect_cells": list(self._defect_data.keys()),
510            "cell_defect_types": {}
511        }
512        for vtk_id, layers in self._defect_data.items():
513            summary["cell_defect_types"][vtk_id] = []
514            for layer_id, layer_data in layers.items():
515                summary["cell_defect_types"][vtk_id].extend(layer_data.keys())
516            summary["cell_defect_types"][vtk_id] = list(set(summary["cell_defect_types"][vtk_id]))
517        return summary

Generate summary containing ids of all cells with defects and list of contained defect types, disregarding layer information.

Returns: dictionary containing list of cells of with defects and list of defect types per cell

def generate_input_set_display_label(self) -> str:
519    def generate_input_set_display_label(self) -> str:
520        """Return string display for object in list displays."""
521        summ = self.get_defects()
522        c = Counter([x.type_id for x in summ])
523        occurence_string = ", ".join(["{}: {}".format(value, count) for value, count in c.most_common()])
524        return "Total: {} | {}".format(c.total(), occurence_string)

Return string display for object in list displays.

def get_defects(self) -> list:
526    def get_defects(self) -> list:
527        """Get all defect objects of input set
528        
529        Returns:
530            list of InputDefect objects
531        """
532        defects = []
533        for _, cell_data in self._defect_data.items():
534            for _, layer_data in cell_data.items():
535                for defect_id, defect in layer_data.items():
536                    defects.append(defect)
537        return defects

Get all defect objects of input set

Returns: list of InputDefect objects

@staticmethod
def get_available_defect_types() -> list:
539    @staticmethod
540    def get_available_defect_types() -> list:
541        """Return all subclasses of the class InputDefect"""
542        return InputDefect.__subclasses__()

Return all subclasses of the class InputDefect

def generate_ontology_label(self) -> str:
544    def generate_ontology_label(self) -> str:
545        """Generate ontology instance iri from object."""
546        return "__DefectPlacementInputSet_{}".format(self._id)

Generate ontology instance iri from object.

@staticmethod
def get_id_from_ontology_iri(label: str) -> int:
548    @staticmethod
549    def get_id_from_ontology_iri(label: str) -> int:
550        """Extract id from full ontology instance iri."""
551        return int(label.split("_")[-1])

Extract id from full ontology instance iri.

def generate_store_insert_stub(self, uniq_id):
553    def generate_store_insert_stub(self, uniq_id):
554        return """
555            senso:__DefectPlacementInputSet_{uniq_id} a senso:DefectPlacementInputSet .
556        """.format(uniq_id=uniq_id)
def save_entry_to_store(self, set_id: int):
558    def save_entry_to_store(self, set_id: int):
559        """Save object to store connection passed during initialization."""
560        self._id = set_id
561        label = self.generate_ontology_label()
562        insert_stubs = [self.generate_store_insert_stub(self._id)]
563        for i, defect in enumerate(self.get_defects()):
564            new_id = "{}_{}".format(self._id, i)
565            insert_stubs.append(defect.generate_store_insert_stub(new_id))  
566        query = """
567            INSERT {{
568            {stubs}
569            }} WHERE {{ }}
570            """.format(stubs="\n".join(insert_stubs))
571        self._store_connection.update_data(query)

Save object to store connection passed during initialization.

@staticmethod
def get_all_entries_from_store(conn: sensotwin.store_connection.StoreConnection) -> dict:
573    @staticmethod
574    def get_all_entries_from_store(conn: StoreConnection) -> dict:
575        """Get all instances of DefectInputDataSet from store connection passed during initialization.
576
577        Args:
578            conn: Any subclass instance of StoreConnection
579        Returns:
580            dict of int -> DefectInputDataSet
581        """
582        defects = {}
583        for defect_type in DefectInputDataSet.get_available_defect_types():
584            defects[defect_type.__name__] = defect_type.get_all_entries_from_store(conn)
585        query = """ 
586            SELECT DISTINCT ?x
587            WHERE {
588              ?x a senso:DefectPlacementInputSet .
589            }
590            """
591        result = {}
592        for x in conn.get_data(query):
593            uniq_id = DefectInputDataSet.get_id_from_ontology_iri(x[0])
594            result[uniq_id] = DefectInputDataSet(uniq_id=uniq_id, conn=conn)
595        for defect_type, defect_dict in defects.items():
596            for iri, defect in defect_dict.items():
597                set_id = defect.get_set_id_from_ontology_iri(iri)
598                result[set_id].add_defect_to_cell(defect.get_cell_id(), defect.get_layer_id(), defect)
599        return result

Get all instances of DefectInputDataSet from store connection passed during initialization.

Args: conn: Any subclass instance of StoreConnection Returns: dict of int -> DefectInputDataSet

def from_hdf_args(hdf):
619    def from_hdf_args(hdf):
620        with hdf.open("defect_placement_input_data") as hdf_store:
621            arg_dict = {
622                "uniq_id": hdf_store["_id"], 
623                "defects": eval(hdf_store["_defects"]),
624                "conn": eval(hdf_store["_store_connection"])
625            }
626        return arg_dict

Read arguments for instance creation from HDF5 file.

Args: hdf (ProjectHDFio): HDF5 group object

Returns: dict: arguments that can be **kwarg-passed to cls().

Inherited Members
pyiron_base.interfaces.has_hdf.HasHDF
from_hdf
to_hdf
rewrite_hdf
class CellLayersDataSet:
629class CellLayersDataSet:
630    """Data set containing information about layer structure of all cells.
631
632    reads data from .vtt file containing information about the different layers for each cell of the 3D model
633    expects vtk table structure according to following definition:
634    
635    "element_label": int (id of associated cell), starting at 1
636    "layer_id": int (id of layer, unique per cell)
637    "layer_material": str (layer material name)
638    "layer_thickness_mm": float (thickness of layer in mm)
639    "layer_angle_deg": int (angle of fiber alignment in °, [-90 to 90])
640
641    """
642    NECESSARY_KEYS = ["element_label", "layer_id", "layer_material", "layer_thickness_mm", "layer_angle_deg"]
643    def __init__(self, vtt_path: str):
644        """Initialise data set from file and check if necessary columns are present.
645
646        Args:
647            vtt_path: full or relative path of .vtt file containing cell information table
648        """
649        self._file_path = vtt_path
650        self._dataframe = read_vtt.get_dataframe(self._file_path)
651        self.check_data_source()
652        self._dataframe.layer_material.replace(to_replace={"SAERTEX-U-E-SKIN": "GLASS-U-E-SKIN","SAERTEX-U-E-WEB": "GLASS-U-E-WEB", "E-LT-5500(UD)": "GLASS-UD"}, inplace=True)
653
654    def get_available_layers_for_cell(self, cell_id: int) -> pd.DataFrame:
655        """Return dataframe containing the data subset of the passed cell_id """
656        return self._dataframe.loc[self._dataframe.element_label == cell_id]
657
658    def get_layer_of_cell(self, cell_id: int, layer_id: int) -> pd.DataFrame:
659        """Return one specific entry to dataset with the correct combination of cell id and layer id"""
660        return self._dataframe.loc[(self._dataframe.element_label == cell_id) & (self._dataframe.layer_id == layer_id)].iloc[0]
661
662    def check_data_source(self):
663        """Check if data source contains all necessary keys.
664        
665        Raises:
666            KeyError: If any key as defined in NECESSARY_KEYS is not found
667            ValueError: If serial ids in element_label do not start with 1
668        """
669        for key in self.NECESSARY_KEYS:
670            if key not in self._dataframe:
671                raise KeyError("'{}' not found in input data '{}'".format(key, self._file_path))
672        if self._dataframe["element_label"].min() != 1:
673            raise ValueError("Serial IDs in 'element_label' need to start at 1, minimum value found: {}".format(self._dataframe["element_label"].min()))
674
675    def __str__(self):
676        return "CellLayersDataSet with {} cells with up to {} layers per cell".format(len(self._dataframe["element_label"].unique()), len(self._dataframe["layer_id"].unique()))
677
678    def __repr__(self):
679        return self.__str__()

Data set containing information about layer structure of all cells.

reads data from .vtt file containing information about the different layers for each cell of the 3D model expects vtk table structure according to following definition:

"element_label": int (id of associated cell), starting at 1 "layer_id": int (id of layer, unique per cell) "layer_material": str (layer material name) "layer_thickness_mm": float (thickness of layer in mm) "layer_angle_deg": int (angle of fiber alignment in °, [-90 to 90])

CellLayersDataSet(vtt_path: str)
643    def __init__(self, vtt_path: str):
644        """Initialise data set from file and check if necessary columns are present.
645
646        Args:
647            vtt_path: full or relative path of .vtt file containing cell information table
648        """
649        self._file_path = vtt_path
650        self._dataframe = read_vtt.get_dataframe(self._file_path)
651        self.check_data_source()
652        self._dataframe.layer_material.replace(to_replace={"SAERTEX-U-E-SKIN": "GLASS-U-E-SKIN","SAERTEX-U-E-WEB": "GLASS-U-E-WEB", "E-LT-5500(UD)": "GLASS-UD"}, inplace=True)

Initialise data set from file and check if necessary columns are present.

Args: vtt_path: full or relative path of .vtt file containing cell information table

NECESSARY_KEYS = ['element_label', 'layer_id', 'layer_material', 'layer_thickness_mm', 'layer_angle_deg']
def get_available_layers_for_cell(self, cell_id: int) -> pandas.core.frame.DataFrame:
654    def get_available_layers_for_cell(self, cell_id: int) -> pd.DataFrame:
655        """Return dataframe containing the data subset of the passed cell_id """
656        return self._dataframe.loc[self._dataframe.element_label == cell_id]

Return dataframe containing the data subset of the passed cell_id

def get_layer_of_cell(self, cell_id: int, layer_id: int) -> pandas.core.frame.DataFrame:
658    def get_layer_of_cell(self, cell_id: int, layer_id: int) -> pd.DataFrame:
659        """Return one specific entry to dataset with the correct combination of cell id and layer id"""
660        return self._dataframe.loc[(self._dataframe.element_label == cell_id) & (self._dataframe.layer_id == layer_id)].iloc[0]

Return one specific entry to dataset with the correct combination of cell id and layer id

def check_data_source(self):
662    def check_data_source(self):
663        """Check if data source contains all necessary keys.
664        
665        Raises:
666            KeyError: If any key as defined in NECESSARY_KEYS is not found
667            ValueError: If serial ids in element_label do not start with 1
668        """
669        for key in self.NECESSARY_KEYS:
670            if key not in self._dataframe:
671                raise KeyError("'{}' not found in input data '{}'".format(key, self._file_path))
672        if self._dataframe["element_label"].min() != 1:
673            raise ValueError("Serial IDs in 'element_label' need to start at 1, minimum value found: {}".format(self._dataframe["element_label"].min()))

Check if data source contains all necessary keys.

Raises: KeyError: If any key as defined in NECESSARY_KEYS is not found ValueError: If serial ids in element_label do not start with 1

def get_material_color(name: str) -> str:
682def get_material_color(name: str) -> str:
683    """Get color for specific layer in matplotlib material layup display."""
684    color_dict = defaultdict(lambda: 'white')
685    color_dict['gelcoat'] = 'red'
686    color_dict['GELCOAT'] = 'red'
687    color_dict['SNL(Triax)'] = 'green'
688    color_dict['saertex(DB)'] = 'blue'
689    color_dict['foam'] = 'yellow'
690    color_dict['FOAM'] = 'yellow'
691    color_dict['Carbon(UD)'] = 'cyan'
692    color_dict['CARBON(UD)'] = 'cyan'
693    color_dict['E-LT-5500(UD)'] = 'salmon'
694    color_dict["GLASS-UD"] = 'salmon'
695    color_dict['E-LT-5500(UD)-SKIN'] = 'orange'
696    color_dict['GLASS-TRIAX'] = 'orange'
697    color_dict['E-LT-5500(UD)-WEB'] = 'peachpuff'
698    color_dict['SAERTEX-U-E-SKIN'] = 'orange'
699    color_dict['SAERTEX-U-E-WEB'] = 'peachpuff'
700    color_dict['GLASS-U-E-SKIN'] = 'orange'
701    color_dict['GLASS-U-E-WEB'] = 'peachpuff'
702    return color_dict[name]

Get color for specific layer in matplotlib material layup display.