ruhi's Blog

Week 4: Local builds and Python API design

ruhi
Published: 06/22/2023

Overview

This week I was setting up d-seams in my Mac, but that did not seem like a great idea as some requirements for d-seams were not supported on the M1 Mac (I opened an issue and PR regarding this). I had to figure out a way to run it on a remote linux machine.

I was also working with how the code design would look like.

import pyseams

# Configuration Variables
cutoffRadius = 3.5
oxygenAtomType = 2
hydrogenAtomType = 1
targetFrame = 1
finalFrame = 1
frameGap = 1
maxDepth = 6
isSlice = False
sliceLowerLimits = [0, 0, 0]
sliceUpperLimits = [0, 0, 0]
outDir = "runOne/"
trajectory = "input/traj/exampleTraj.lammpstrj"
lowestAtomID = 0

print("\nWelcome to the Ice Type Determination Module\n")

resCloud = None  # Initialize resCloud variable

for frame in range(targetFrame, finalFrame + 1, frameGap):
    resCloud = pyseams.readFrameOnlyOne(trajectory, frame, resCloud, oxygenAtomType, isSlice, sliceLowerLimits, sliceUpperLimits)
    nList = pyseams.neighborList(cutoffRadius, resCloud, oxygenAtomType)
    hbnList = pyseams.getHbondNetwork(trajectory, resCloud, nList, frame, hydrogenAtomType)
    hbnList = pyseams.bondNetworkByIndex(resCloud, hbnList)
    rings = pyseams.getPrimitiveRings(hbnList, maxDepth)
    pyseams.prismAnalysis(outDir, rings, hbnList, resCloud, maxDepth, lowestAtomID, targetFrame, frame, False)

print("Ice Type Determination completed.")

This is just a rough draft. I will be working on it to make it more perfectly.

Check-in Questions

What did you do this week?

  1. build issues in GitHub.

  2. did a pull request on GitHub.

  3. worked a little bit on pybind design.

What is coming up next?

  1. I will make a repository with python bindings which will be linked with d-seams as a shared library.

  2. d-seams and python binding uses cmake. I am not that comfortable with cmake so I was planning to use meson for the python bindings. Meson supports pybind11 as mentioned here

  3. I will also work on the python design a bit more.

Did you get stuck anywhere?

I was stuck as my M1-macos machine didn't support certain requirements of d-seams which set me back a little bit. I had to work on a linux machine. My mentor helped me out with the process.

View Blog Post

Week 3: Embedding and automated bindings

ruhi
Published: 06/15/2023

Overview

Since last week, I was going over the Pybind11 documentation and also looking into automated binding generators. I have been mulling over what it means to provide bindings and how the interface is going to change. I tested out cppyy and its examples, but my mentor suggested that it may not be the right fit for the project as it is unlikely to be able to handle templates without more involved bindings.

However, as I began setting up a new repository for the bindings, it occurred to me that for backwards compatibility, though providing a compiled extension will be useful for more users, switching over from Lua really needs an embedding of the Python interpreter! I am fairly sure of this, as the binary (from last week's main.cpp) essentially copies into C++ data from Lua. Embedding is part of Pybind11's feature-set:

// Starts the interpreter and keeps it alive
py::scoped_interpreter guard{};

However, there's a catch, we need both the bindings (to run seams-core) from python so we can transfer data into the C++ in a robust manner! This means my timeline is a little altered, I will need to write the compiled extension, and then interface that to the main.cpp. So:

from pyseams import PointCloud
pinp = PointCloud(...)

Which will then be read in on the C++ side by the embedded interpreter. Sort of like the existing examples:

print("\n Welcome to the manual lua function evaluation environment.\n");
for frame=targetFrame,finalFrame,frameGap do
   resCloud=readFrame(trajectory,frame,resCloud,oxygenAtomType,isSlice,sliceLowerLimits,sliceUpperLimits) --- Get the frame
   nList=neighborList(cutoffRadius, resCloud, oxygenAtomType); --- Calculate the neighborlist by ID
   ---
   resCloud=chillPlus_cij(resCloud,nList,isSlice); --- Calculate Cij (cloud,slice)
   resCloud=chillPlus_iceType(resCloud,nList,outDir,targetFrame,isSlice,chillPlus_noMod); --- Write out data (cloud,slice,name)
   writeDump(resCloud,outDir,dumpChillP); --- Dump the rescloud which currently has CHILL Plus classifications
   --- Modified CHILL+
   avgQ6=averageQ6(resCloud,nList,isSlice); --- Average Q6 (cloud,slice)
   resCloud=modifyChill(resCloud,avgQ6); --- Modification (cloud,q6)
   percentage_Ice(resCloud,outDir,targetFrame,isSlice,chillPlus_mod); --- Post reclassification writeOut
   writeDump(resCloud,outDir,dumpSupaaP); --- Dump the rescloud which now has the supaa CHILL Plus Trajectory
   --- Get the largest ice cluster. Here, iceNeighbourList is the neighbour list by index.
   clusterAnalysis(outDir, clusterCloud, resCloud, nList, iceNeighbourList, cutoffRadius, targetFrame, "q6");
   --- Recenter the cluster such that the centroid is at the center of the simulation box
   recenterCluster(clusterCloud, iceNeighbourList);
   writeDump(resCloud,outDir,largestClusterDump); --- Dump the recentered largest ice cluster
end

This is a tentative design which I will discuss with my mentor this week.

Check-in Questions

What did you do this week?

  • Looked into automated bindings (cppyy)
  • Realized I need to embed an interpreter for backwards compatibility
  • Started designing the classes based on pypotlib

    What is coming up next?

  • I'm still planning on that personal site
  • I will publicly post my repo for the python-bindings
    • My mentor will move it into the dseams workspace
    • This will be my first time working in an organization on Github
  • I will start a design document
  • I will go over the C-Python documentation to understand the automated / manual bindings system in a bit more detail

The goal is to have working code examples by my midway evaluation as per the original plan.

Did you get stuck anywhere?

  • The embedding of the interpreter was something which I hadn't considered, not even in my proposal
  • I was interested (and a bit caught up on) how automatic bindings work
  • I am having some trouble (the "tyranny of a blank page") getting started with runnable code
    • Especially when I realized I cannot run the exact code (main.cpp) until after the bindings are complete!
  • I was having trouble formatting my posts on the PSF GSoC blogroll
    • Figured out I can use this site (or pandoc)
View Blog Post

Week 2: Into the Lua Bindings

ruhi
Published: 06/07/2023

Overview

I have been going over the source code of d-SEAMS and puzzling out the minimal required objects and functions. It seems that for the `lua` bindings, the objects were mostly constructed in `C++` and then populated in `lua`, however, for the `python` bindings each class will need to have separate bindings. I have narrowed my focus to a single workflow, not the entire driver (which is controlled by the `yaml` file), that is as discussed in the paper (from here):

```cpp
if (config["topoTwoDim"]["use"].as<bool>()) {
    // Use the variables script
    lua.script_file(vars);
    // -----------------
    // Variables which must be declared in C++
    //
    // Newer pointCloud (rescloud -> ice structure, solcloud -> largest cluster)
    molSys::PointCloud<molSys::Point<double>, double> resCloud;
    // Some neighbor lists
    std::vector<std::vector<int>> nList, hbnList;
    // For the list of all rings (of all sizes)
    std::vector<std::vector<int>> ringsAllSizes;
    std::vector<std::vector<int>> rings;
    // RDF stuff
    std::vector<double> rdfValues; // RDF vector
    // -----------------
    // This section basically only registers functions and handles the rest in
    // lua Use the functions defined here
    auto lscript = lua.get<std::string>("functionScript");
    // Transfer variables to lua
    lua["doBOP"] = config["bulk"]["use"].as<bool>();
    lua["topoOneDim"] = config["topoOneDim"]["use"].as<bool>();
    lua["topoTwoDim"] = config["topoTwoDim"]["use"].as<bool>();
    lua["topoBulk"] = config["bulk"]["use"].as<bool>();
    //
    lua["nList"] = &nList;
    lua["hbnList"] = &hbnList;
    lua["resCloud"] = &resCloud;
    lua["trajectory"] = tFile;
    // Confined ice stuff
    lua["ringsAllSizes"] = &rings;
    // RDF stuff
    lua["rdf"] = &rdfValues;
    // -----------------
    // Register functions
    //
    // Writing stuff
    // Generic requirements
    lua.set_function("readFrameOnlyOne", sinp::readLammpsTrjreduced);
    lua.set_function("readFrameOnlyOneAllAtoms", sinp::readLammpsTrj); // reads in all atoms regardless of type  
    lua.set_function("neighborList", nneigh::neighListO);
    // -----------------
    // Topological Network Method Specific Functions
    // Generic requirements (read in only inside the slice)
    lua.set_function("getHbondNetwork", bond::populateHbonds);
    lua.set_function("bondNetworkByIndex", nneigh::neighbourListByIndex);
    // -----------------
    // Primitive rings
    lua.set_function("getPrimitiveRings", primitive::ringNetwork);
    // -----------------
    // Quasi-two-dimensional ice
    lua.set_function("ringAnalysis", ring::polygonRingAnalysis);
    // --------------------------
    // RDF functions
    lua.set_function("calcRDF", rdf2::rdf2Danalysis_AA);
    // --------------------------
    // Use the script
    lua.script_file(lscript);
    // --------------------------
  } // end of two-dimensional ice block
```

It is clear that the bindings might be a mite more complicated in `python`, especially as I realized many of the core structures are templated.

Check-in Questions

What did you do this week?

  • Went over the `d-seams` documentation and examples locally
    • Settled on a workflow to bind
    • Looked into the classes and functions needed
  • Went over the `sol3` documentation on the `lua` bindings

What is coming up next?

1.  I intend to have a personal site with more details of the internals
2. I shall start designing the code and determine a style guide with my mentor
3. I will finish enumerating the functions and objects needed to be bound for this workflow

Did you get stuck anywhere?

I was a bit confused about the manner in which memory was managed between `lua` and `cpp` and how it would change with the `python` bindings. I hope to clarify this further, and have a minimal toy setup on my machine to work with when I meet my mentor later this week.

View Blog Post

Community Bonding and Week 1

ruhi
Published: 06/01/2023

Overview

As this post is at the start of the first week of the coding period, there haven't been any concrete pull requests, though over the course of the community bonding period I pointed towards a project called pypotlib (GH source) as an example of the split binding / core library design I will be implementing.

Check-in Questions

What did you do this week?

1. Went over the pybind11 documentation and examples locally

2. Looked into style and design guides for PyPI a bit

What is coming up next?

1. Local setup

2. Setting up an issue with the order in which I will implement the bindings

Did you get stuck anywhere?

I was able to meet my mentor and the project organisers. I think I am on track and do not feel stuck so far.

View Blog Post