Guide to using CIF_dREL

Introduction

CIF_dREL provides methods and types that take advantage of code embedded in CIF dictionaries (ontologies) that describes mathematical relationships between data names defined in those ontologies. To do this, it translates those methods into Julia code that can be executed, for example, to find or check missing values.

Before reading the following, you should be familiar with the CrystalInfoFramework.jl documentation for working with CIF files and dictionaries.

Usage

Preparation

Read in the CIF dictionary, and prepare any dREL functions defined in the dictionary:

dict = DDLm_Dictionary("cif_core.dic")
define_dict_funcs!(dict)    #add dREL Functions to dictionary

In DDLm, dREL functions are defined in categories that have _definition.class of Function. They should not be confused with dREL methods, which are associated with particular data names or categories.

The DDLm_Dictionary type used above is defined in CrystalInfoFramework.jl. DDL2_Dictionarys may also be used, but only methods of type dREL will be recognised.

define_dict_funcs! will process all dREL functions found in the dictionary and make them available to dREL methods. They can be inspected via the CrystalInfoFramework get_dict_func method.

dREL methods operate on any source of data that returns the correct data types and has a relational structure. We use a CrystalInfoFramework TypedDataSource created from a CIF block:

n = Cif("nick1.cif")
b = n["saly2_all_aniso"] #select a data block
t = TypedDataSource(b,dict)

The final step is to create a DynamicDDLmRC type that allows new values to be derived given a dictionary describing the mathematical relationships:

dd = DynamicDDLmRC(t,dict)

Note that in this case the dictionary used for typing, and the dictionary used for dREL methods and to create the relational structure, are the same dictionary.

Derivation

A request for a data name whose value is not found in the DynamicDDLmRC object will trigger derivation:

dd["_cell.volume"]

A whole category may also be computed if the values needed for the calculation are present:

dd["geom_bond"]

Note that, as computations (currently) can take significant time, results are cached. To clear this cache, call empty_cache!.

test/drel_exec.jl contains demonstrations of how to make use of dREL scripts found in dictionaries.

Namespaces

Advanced users may have DataSources with data names from different namespaces. Provide a further nspace argument to disambiguate in this case:

dd["_cell.volume","CifCore"]

Translating dREL

If you wish simply to transform some dREL code into Julia, you can use make_julia_code. You will need to provide the dREL fragment, the data name it is associated with (or category name), and the CIF dictionary. The returned Expr will need to be evaluated and assigned to a variable before it can be executed. The arguments to the returned function are the datablock and a single row of the category to which the defined value belongs.

dreltext = """
      With c  as  cell
 
      _cell.volume =  c.vector_a * ( c.vector_b ^ c.vector_c )

"""
make_julia_code(dreltext,"_cell.volume",dict)

# output

function (__datablock::DynamicRelationalContainer, __packet::CatPacket)
    #= /home/jrh/programs/CIF/dRELTools.jl/src/drel_ast.jl:397 =#
    __dict = missing
    c = missing
    __dreltarget = missing
    #= /home/jrh/programs/CIF/dRELTools.jl/src/jl_transformer.jl:120 =#
    #= /home/jrh/programs/CIF/dRELTools.jl/src/jl_transformer.jl:122 =#
    begin
        __dict = get_dictionary(__datablock, "CifCore")
        begin
            c = __packet
            #= /home/jrh/programs/CIF/dRELTools.jl/src/jl_transformer.jl:651 =#
            begin
                __dreltarget = drel_property_access(c, "vector_a", __datablock)::drelvector * cross(drel_property_access(c, "vector_b", __datablock)::drelvector, drel_property_access(c, "vector_c", __datablock)::drelvector)
            end
        end
        return __dreltarget
    end
end