buildingSMART Forums

Anyone know how to get this ifcschemareader.py working?

github .com/mvaerle/python-ifc/blob/master/ifcschemareader.py

How do I run this in python IDE? Anyone try this before?

This should convert an IFC file to a Database Schema format?

This was mentioned in www .int-arch-photogramm-remote-sens-spatial-inf-sci.net/XLII-2-W5/467/2017/isprs-archives-XLII-2-W5-467-2017.pdf

hmm
Got it working and Parsed but where did the parsed files go?

===============================================
import re, copy

class IfcSchema:
SIMPLETYPES = [“INTEGER”, “REAL”, “STRING”, “NUMBER”, “LOGICAL”, “BOOLEAN”]
NO_ATTR = [“WHERE”, “INVERSE”,“WR2”,“WR3”, “WR4”, “WR5”, “UNIQUE”, “DERIVE”]

def __init__(self, filename = "D:\python-ifc-master\BathroomWindow.ifc"):
    self.filename = filename
    self.file = open(self.filename)
    self.data = self.file.read()
    self.types = self.readTypes()
    self.entities = self.readEntities()
    print "Parsed from schema %s: %s entities and %s types" % (self.filename, len(self.entities), len(self.types))

def readTypes(self):
    """
    Parse all the possible types from the schema, 
    returns a dictionary Name -> Type
    """
    types = {}
    for m in re.finditer("TYPE (.*) = (.*);", self.data):
        typename, typetype = m.groups() 
        if typetype in self.SIMPLETYPES:
            types[typename] = typetype
        else:
            types[typename] = "#" + typetype
            
    return types
    
def readEntities(self):
    """
    Parse all the possible entities from the schema,
    returns a dictionary of the form:
    { name: { 
        "supertype": supertype, 
        "attributes": [{ key: value }, ..]
    }}  
    """
    entities = {}
    
    # Regexes must be greedy to prevent matching outer entity and end_entity strings
    # Regexes have re.DOTALL to match newlines
    for m in re.finditer("ENTITY (.*?)END_ENTITY;", self.data, re.DOTALL):
        entity = {}
        raw_entity_str = m.groups()[0]

        entity["name"] = re.search("(.*?)[;|\s]", raw_entity_str).groups()[0].upper()

        subtypeofmatch = re.search(".*SUBTYPE OF \((.*?)\);", raw_entity_str)
        entity["supertype"] = subtypeofmatch.groups()[0].upper() if subtypeofmatch else None

        # find the shortest string matched from the end of the entity type header to the
        # first occurence of a NO_ATTR string (when it occurs on a new line)
        inner_str = re.search(";(.*?)$", raw_entity_str, re.DOTALL).groups()[0]            

        attrs_str = min([inner_str.partition("\r\n "+a)[0] for a in self.NO_ATTR])
        attrs = []
        for am in re.finditer("(.*?) : (.*?);", attrs_str, re.DOTALL):
            name, attr_type = [s.replace("\r\n\t","") for s in am.groups()]
            attrs.append((name, attr_type))
        
        entity["attributes"] = attrs
        entities[entity["name"]] = entity
    

    return entities

def getAttributes(self, name):
    """
    Get all attributes af an entity, including supertypes
    """
    ent = self.entities[name]

    attrs = []
    while ent != None:
        this_ent_attrs = copy.copy(ent["attributes"])
        this_ent_attrs.reverse()
        attrs.extend(this_ent_attrs)
        ent = self.entities.get(ent["supertype"], None)

    attrs.reverse()
    return attrs

if name == “main”:
schema = IfcSchema(“D:\python-ifc-master\IFC2X3_TC1.exp”)

Hi

I started with python some weeks ago, and nice that you posted to script and may test it next days.

The following line “only” returns the content of the file into the variable entities:
self.entities = self.readEntities()
with adding the line
print(self.entities)
it should print the content of the variable as a dict to the screen.

Thanks Rok! It did print to the console/Terminal with that "print(self.entities).
Now wondering how to output to a text file the results.

On Unix systems, you can simply use output redirection. For example:

python myscript.py > myoutputfile

Alternatively, a standard way to write to file within the Python script itself would be as follows:

with open('somefile.txt', 'a') as the_file:
    the_file.write(str(self.entities))

You may consider using Python JSON or XML modules to store the data in one of those formats.

As a general word of caution. The express schema definition language is not a “regular language”, so parsing it with regular expressions is likely very brittle. I’d recommend looking at the more formal parsers out there such as https://github.com/ikeough/IFC-gen/ and https://github.com/IfcOpenShell/IfcOpenShell/tree/master/src/ifcexpressparser

1 Like

It’s odd to me why some suggest some projects which are good but outdated like IFC-Gen which nobody has worked on them for years, or other solutions which are “AVERAGE”

If you all want to build your solutions based on IfcOpenShell, or BIMServer, or these kinds of projects which are good but not well, it’s up to you, but these solutions won’t change anything and just repeat issues in a new ways

CC: @jwouellette @TLiebich

Thanks Moult!

I got it working to a log file now with your code.

with open(‘somefile.txt’, ‘a’) as the_file:
** the_file.write(str(self.entities))**

It is very hard to see what is current in the IFC standards. Lots of programmers and companies coming up with a lot of viewers and some with IFC editors. It is very hard to interact with IFC files. Possibly for my usage, I would like to see if IFC files can be stored into an Object Oriented database like Postgre to see if and how it can be searched and have the IFC files compared.
Alas. not a lot of information on this. Just some research papers on the web but don’t go into depth.
What do you recommend ReD_CoDE?

I think many have worked on Object-Oriented approach, especially restoring Ifc and IfcXML data/information in Object-Oriented databases
But few have worked on “Relational” approach

There are two parts:

  1. Develop an IFC data/information model (schema)
  1. Restore IFC data/information in databases
  • Relational database
  • Object-Oriented database
  • Graph database

So, what are you talking about is related to second part, databases
And I think IFC has some issues and mainly should solve the issues in first part