coudertlab / CrystalNets.jl

A julia package for the manipulation of crystal net representations and topology
MIT License
40 stars 3 forks source link

Call CrystalNets from Python? #15

Closed qzhu2017 closed 1 year ago

qzhu2017 commented 1 year ago

Hi, this is really a nice package. I have some python script that would generate many cif files. I want to use this package to determine the topology and then pass the value to my python script.

Do you know if I can call CrystalNets from Python?

Many thanks,

Liozou commented 1 year ago

Hi and thank you for your interest!

Sure, you can call julia from python using juliacall. To do so, go to the folder with your python script and add a new file called juliapkg.json with the following content:

{
    "julia": "1",
    "packages": {
        "CrystalNets": {
            "uuid": "7952bbbe-a946-4118-bea0-081a0932faa9",
            "version": "0.3"
        }
    }
}

then install juliacall with pip install juliacall. From there, you can call CrystalNets by starting your python script with the following three lines:

import juliacall
jl = juliacall.newmodule("TheNameOfYourModule") # put whatever name here
jl.seval("using CrystalNets")

(Note that the first time you run those, julia will install CrystalNets and its dependencies, which can take a while, but you only need to do that once)

Afterwards, you can call any function of CrystalNets.jl by prefixing them with jl., for instance:

>>> jl.determine_topology("/tmp/MIL-53.cif")
[ Error: Atom ?, used in a bond, has either zero or multiple placements in the CIF file. This invalidates all bonds from the file, which will thus be discarded.
[ Warning: Guessing bonds with custom algorithm (from Chemfiles and VMD). This may take a while for big structures and may be inexact.
[ Info: To avoid guessing bonds, use a file format that contains the bonds.
Export of input is enabled: saving file at /tmp/input_MIL-53_other1.vtf
Export of subnet_Auto is enabled: saving file at /tmp/subnet_Auto_MIL-53_1_other1.vtf
Julia: rna

(rna is the name of the topology of MIL-53)

If you want, you can disable the warnings and/or the exports by adding the following lines after the three initial lines above:

jl.CrystalNets.toggle_warning(False) # to disable warnings
jl.CrystalNets.toggle_export(False) # to disable exports

A more programmatic use-case would then look like

>>> x = jl.determine_topology("/tmp/UiO-66.cif", jl.CrystalNets.Options(structure=jl.StructureType.MOF))
>>> str(x)
'AllNodes, SingleNodes: fcu'

The nature of the x above depends on whether your cif files contains inter-penetrating substructures, or which clusterings you asked, there are examples for all cases in the documentation.

Please let me know if you encounter any other issue with this!

Liozou commented 1 year ago

I included the explanation above, as well as a slightly more detailed example, in a new Python interface tutorial now accessible in the documentation: https://molsim.info/CrystalNets.jl/dev/python Let me know if you'd like to see something else in the tutorial!

qzhu2017 commented 1 year ago

Hi, @Liozou Can you tell me how to extract the dimension information if I choose the auto option as follows

result = jl.determine_topology(cif_file, jl.CrystalNets.Options(structure=jl.StructureType.Auto))
Liozou commented 1 year ago

Sure, the code at https://molsim.info/CrystalNets.jl/dev/python/ should contain the necessary information. Note that specifying structure=jl.StructureType.Auto is not necessary since this is the default value for the structure keyword anyway (check https://molsim.info/CrystalNets.jl/dev/lib/public/#CrystalNets.Options).

In general the dimension depends on the net, and thus it may depend on the clustering. So, to detail the steps in the current version of CrystalNets, (v0.4), you should: 1) Extract the relevant TopologyResult, so if there are multiple interpenetrated substructures and you want the second one for instance, you can do tresult, tresultnfold = result[1] where tresultnfold will be the catenation multiplicity of the net. If you want the first one, do tresult, tresultnfold = result[0], etc. 2) Extract the TopologicalGenome of the net with the relevant clustering, so if you are interested in the SingleNodes clustering for instance, you can do genome = tresult[jl.Clustering.SingleNodes]. Note that, if you have not specified explicitly the clusterings keyword, then: