From ce7ba377c6ad2a91247e82a0790c485a99494534 Mon Sep 17 00:00:00 2001
From: Jenna M Swarthout Goddard <38287809+jennaswa@users.noreply.github.com>
Date: Thu, 1 Aug 2024 09:32:59 -0400
Subject: [PATCH 01/23] Skeleton blog post for GSoC small project wrap-up
---
_posts/2024-08-01-gsoc2024-final-sm.md | 28 ++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
create mode 100644 _posts/2024-08-01-gsoc2024-final-sm.md
diff --git a/_posts/2024-08-01-gsoc2024-final-sm.md b/_posts/2024-08-01-gsoc2024-final-sm.md
new file mode 100644
index 00000000..92ff832d
--- /dev/null
+++ b/_posts/2024-08-01-gsoc2024-final-sm.md
@@ -0,0 +1,28 @@
+---
+layout: post
+title: Google Summer of Code (GSoC) 2024 Wrap-Up: Small Projects
+---
+
+
+
+
+We would like to highlight the work of two of our outstanding [Google Summer of Code](https://summerofcode.withgoogle.com/) (GSoC) contributors, [Lawson Woods](https://summerofcode.withgoogle.com/programs/2024/projects/BYYAE9MR) (@ljwoods2) and [Valerij Talagayev](https://summerofcode.withgoogle.com/programs/2024/projects/sfy3kuqc) (@talagayev), who successfully completed their [GSoC projects](https://summerofcode.withgoogle.com/programs/2024/organizations/mdanalysis) with MDAnalysis.
+
+As part of [GSoC's 20th anniversary celebration](https://opensource.googleblog.com/2023/11/google-summer-of-code-2024-celebrating-20th-year.html), Google introduced a new "small" project scope (~90 hour commitment) to its repertoire during the 2024 GSoC program to reduce time barriers to participation. Lawson and Valerij have both proven that though their projects may have been small in scope, their contributions to MDAnalysis during the GSoC period were invaluable.
+
+You can read more about Lawson and Valerij's projects in their blog posts:
+
+* Lawson: [GSoC 2024 - Enhancing the Interoperability and Efficiency of the Zarrtraj MDAKit][blog-lawson]
+* Valerij: [GSoC 2024 - 2D Visualization for Small Molecules][blog-valerij]
+
+We have tremendously enjoyed working with Lawson and Valerij and wish them the best in their future contributions to the MDAnalysis community and beyond!
+
+We also thank [Google](https://opensource.google/) for supporting the students and continuing to support MDAnalysis as a GSoC organization since 2016.
+
+— @cbouy @hmacdope @IAlibay @jennaswa @richardgowers @xhgchen @yuxuanzhuang (mentors and org admins)
+
+[blog-lawson]: {{ site.baseurl }}{% post_url .MD-FILE-NAME-HERE %}
+[blog-valerij]: {{ site.baseurl }}{% post_url .MD-FILE-NAME-HERE %}
\ No newline at end of file
From 17e6ec47644555b7efb5097ab37c2a1b2988ec07 Mon Sep 17 00:00:00 2001
From: Lawson Woods
Date: Sat, 3 Aug 2024 13:30:47 -0700
Subject: [PATCH 02/23] update lawson woods
---
_posts/2024-08-01-gsoc2024-final-sm.md | 2 +-
_posts/2024-08-03-gsoc2024_woods.markdown | 260 ++++++++++++++++++++++
2 files changed, 261 insertions(+), 1 deletion(-)
create mode 100644 _posts/2024-08-03-gsoc2024_woods.markdown
diff --git a/_posts/2024-08-01-gsoc2024-final-sm.md b/_posts/2024-08-01-gsoc2024-final-sm.md
index 92ff832d..1e97a3e1 100644
--- a/_posts/2024-08-01-gsoc2024-final-sm.md
+++ b/_posts/2024-08-01-gsoc2024-final-sm.md
@@ -24,5 +24,5 @@ We also thank [Google](https://opensource.google/) for supporting the students a
— @cbouy @hmacdope @IAlibay @jennaswa @richardgowers @xhgchen @yuxuanzhuang (mentors and org admins)
-[blog-lawson]: {{ site.baseurl }}{% post_url .MD-FILE-NAME-HERE %}
+[blog-lawson]: {{ site.baseurl }}{% post_url 2024-08-03-gsoc2024_woods %}
[blog-valerij]: {{ site.baseurl }}{% post_url .MD-FILE-NAME-HERE %}
\ No newline at end of file
diff --git a/_posts/2024-08-03-gsoc2024_woods.markdown b/_posts/2024-08-03-gsoc2024_woods.markdown
new file mode 100644
index 00000000..bdc5f88a
--- /dev/null
+++ b/_posts/2024-08-03-gsoc2024_woods.markdown
@@ -0,0 +1,260 @@
+---
+layout: single
+title: "GSoC 2024 - Streaming H5MD trajectories from the cloud"
+categories: zarrtraj
+---
+
+## What is Zarrtraj?
+
+[Zarrtraj](https://github.com/Becksteinlab/zarrtraj) is an [MDAKit](https://mdakits.mdanalysis.org/about.html) for storing and analyzing trajectories in [MDAnalysis](https://github.com/MDAnalysis/mdanalysis) from the cloud, representing a major milestone towards the MDAnalysis 3.0 goal of cloud streaming as well as a proof-of-concept for a new paradigm in the field of molecular dynamics as a whole.
+It can stream [H5MD](https://www.nongnu.org/h5md/h5md.html) trajectories from cloud storage
+providers including AWS S3, Google Cloud buckets, and Azure Blob storage and data lakes.
+Using Zarrtraj, anyone can reproduce your analyses or train their ML model on trajectory data
+without ever having to download massive files to their disk.
+
+This is possible thanks to [Zarr](https://github.com/zarr-developers/zarr-python), [fsspec](https://github.com/fsspec/filesystem_spec),
+and [kerchunk](https://github.com/fsspec/kerchunk), packages that have created a foundation for storing and interacting with
+large datasets in a uniform way across different storage backends. Interestingly, these projects were intially developed by geoscientists in the [Pangeo project](https://pangeo.io/) to make use of [cloud computing credits from an NSF partnership with cloud providers](https://medium.com/pangeo/pangeo-2-0-2bedf099582d), but have since undergone wider adoption by the broader Python community. This project also represents one of the first forays of the molecular dynamics field into the excellent Pangeo ecosystem of tools.
+
+Zarr is especially well-suited to the task of reading cloud-stored files due to its integration with
+[dask](https://docs.dask.org/en/stable/) for parallelized reading. This parallelization offsets
+the increased IO time in cloud-streaming, speeding up common analysis algorithms up to ~4x compared to sequential analysis.
+See the [zarrtraj benchmarks](https://zarrtraj.readthedocs.io/en/latest/benchmarks.html) for more.
+
+In this project, we also decided to experiment with storing trajectories directly in Zarr-backed files
+using the same specification that H5MD uses, so Zarrtraj can read both `.h5md` and H5MD-formatted `.zarrmd`
+files. See [this explanation of the modified format](https://zarrtraj.readthedocs.io/en/latest/zarrmd-file-spec/v0.2.0.html)
+to learn more.
+
+While this GSoC project started with the goal of building a new, Zarr-backed trajectory format, we pivoted
+to making the existing H5MD format streamable after getting feedback
+from the community that supporting widely adopted formats in the MD ecosystem makes code more sustainable and simplifies tool adoption.
+
+The next section is a walkthrough of Zarrtraj's features and usage also available
+[here](https://zarrtraj.readthedocs.io/en/latest/walkthrough.html).
+
+## How can I use it?
+
+Zarrtraj is currently available via PyPI and Conda Forge.
+
+Pip installation
+```bash
+pip install zarrtraj
+```
+
+Conda installation
+```bash
+conda install -c conda-forge zarrtraj
+```
+
+For more information on installation, see [the installation guide](https://zarrtraj.readthedocs.io/en/latest/installation.html#installation)
+
+This walkthrough will guide you through the process of reading and writing H5MD-formatted trajectories from cloud storage using
+AWS S3 as an example. To learn more about reading and writing trajectories from different cloud storage providers,
+including Google Cloud and Azure, see the [API documentation](https://zarrtraj.readthedocs.io/en/latest/api.html).
+
+### Reading H5MD trajectories from cloud storage
+
+#### Uploading your H5MD file
+
+First, upload your H5MD trajectories to an AWS S3 bucket. This requires that an S3 Bucket is setup and configured for
+write access using the credentials stored in "sample_profile". If you've never configured an S3 Bucket before, see
+[this guide](https://docs.aws.amazon.com/AmazonS3/latest/userguide/creating-bucket.html). You can setup a profile to easily manage AWS
+credentials using [this VSCode extension](https://marketplace.visualstudio.com/items?itemName=AmazonWebServices.aws-toolkit-vscode).
+Here is a sample profile (stored in ~/.aws/credentials) where
+[the key is an access key associated with a user that has read and write permissions for the bucket](https://stackoverflow.com/questions/50802319/create-a-single-iam-user-to-access-only-specific-s3-bucket)
+
+```
+[sample_profile]
+aws_access_key_id =
+```
+MDAnalysis can write a trajectory from
+[any of its supported formats into H5MD](https://docs.mdanalysis.org/stable/documentation_pages/coordinates/H5MD.html). We
+recommend using the ```chunks``` kwarg with the MDAnalysis H5MDWriter with a value that yields ~8-16MB chunks of data for best S3 performance.
+Once written locally, you can upload the trajectory to S3 programmatically:
+
+```python
+import os
+from botocore.exceptions import ClientError
+import boto3
+import logging
+
+os.environ["AWS_PROFILE"] = "sample_profile"
+# This is the AWS region where the bucket is located
+os.environ["AWS_REGION"] = "us-west-1"
+
+def upload_h5md_file(bucket_name, file_name):
+ s3_client = boto3.client("s3")
+ obj_name = os.path.basename(file_name)
+
+ response = s3_client.upload_file(
+ file_name, bucket_name, obj_name
+ )
+
+
+if __name__ == "__main__":
+ # Using test H5MD file from the Zarrtraj repo
+ upload_h5md_file("sample-bucket-name", "zarrtraj/data/COORDINATES_SYNTHETIC_H5MD.h5md")
+```
+
+You can also upload the H5MD file directly using the AWS web interface by navigating to S3, the bucket name, and pressing
+"upload".
+
+#### Reading your H5MD file
+
+After the file is uploaded, you can use the same credentials to stream the file into MDAnalysis:
+
+```python
+import zarrtraj
+import MDAnalysis as mda
+# This sample topology requires installing MDAnalysisTests
+from MDAnalysisTests.datafiles import COORDINATES_TOPOLOGY
+import os
+
+os.environ["AWS_PROFILE"] = "sample_profile"
+os.environ["AWS_REGION"] = "us-west-1"
+
+u = mda.Universe(COORDINATES_TOPOLOGY, "s3://sample-bucket-name/COORDINATES_SYNTHETIC_H5MD.h5md")
+for ts in u.trajectory:
+ pass
+```
+
+You can follow this same process for reading `.zarrmd` files with the added advantage
+that Zarrtarj can write `.zarrmd` files directly into an S3 bucket.
+
+### Writing trajectories from MDAnalysis into a zarrmd file in an S3 Bucket
+
+Using the same credentials with read/write access, you can write a trajectory
+into your bucket.
+
+You can change the stored precision of floating point values in the file with the optional
+`precision` kwarg and pass in any `numcodecs.Codec` compressor with the optional
+`compressor` kwarg. See [numcodecs](https://numcodecs.readthedocs.io/en/stable/)
+for more on the available compressors.
+
+Chunking is automatically determined for all datasets to be optimized for
+cloud storage and is not configurable by the user.
+Initial benchmarks show this chunking strategy is effective for disk storage as well.
+
+```python
+import zarrtraj
+import MDAnalysis as mda
+from MDAnalysisTests.datafiles import PSF, DCD
+import numcodecs
+import os
+
+os.environ["AWS_PROFILE"] = "sample_profile"
+os.environ["AWS_REGION"] = "us-west-1"
+
+u = mda.Universe(PSF, DCD)
+with mda.Writer("s3://sample-bucket-name/test.zarrmd",
+ n_atoms=u.trajectory.n_atoms,
+ precision=3,
+ compressor=numcodecs.Blosc(cname="zstd", clevel=9)) as W:
+ for ts in u.trajectory:
+ W.write(u.atoms)
+
+```
+
+If you have additional questions, please don't hesitate to open a discussion on the [zarrtarj github](https://github.com/Becksteinlab/zarrtraj).
+The [MDAnalysis discord](https://discord.com/channels/807348386012987462/) is also a
+great resource for asking questions and getting involved in MDAnalysis.
+
+## What's next for Zarrtraj?
+
+Zarrtraj is currently in a fully operational state and is ready for use!
+However, I'm excited about creating some new features in the future that will
+make Zarrtraj more flexible and faster.
+
+### Lazytimeseries
+
+In MDAnalysis, many trajectory readers expose a `timeseries` method for getting access to
+coordinate data for a subselection of atoms across a trajectory. This provides
+a viable way to sidestep the `Timestep` (eagerly-loaded frame-based) paradigm that
+MDAnalysis uses for handling trajectory data. Zarrtraj could implement a
+"lazytimeseries" that returns a lazy dask array of a selection of atoms' positions
+across the trajectory. Early benchmarks show that analysis based on such a lazy array
+can outperform `Timestep`-based analysis.
+
+### Asynchronous Reading
+
+The performance impact of network IO could be reduced by creating a multi-threaded `ZARRH5MDReader` that isn't blocked
+by analysis code executing. The reader could eagerly load the cache with the next frames
+the analysis code will need to reduce the impact of network IO on exeution time.
+
+## Acknowledgements
+
+Thank you to Hugo MacDermott-Opeskin and Yuxuan Zhuang for their mentorship and feedback
+throughout this project.
+
+I also want to thank Oliver Beckstein and Edis Jakupovic for lending their expertise
+in H5MD and all things MDAnalysis.
+
+Finally, another thanks to Martin Durant, author of Kerchunk, who was incredibly helpful in refining and merging
+a new feature in his codebase necessary for this project to work.
+
+### Citations ###
+
+Alistair Miles, jakirkham, M Bussonnier, Josh Moore, Dimitri Papadopoulos Orfanos, Davis Bennett, David Stansby, Joe Hamman, James Bourbeau, Andrew Fulton, Gregory Lee, Ryan Abernathey, Norman Rzepka, Zain Patel, Mads R. B. Kristensen, Sanket Verma, Saransh Chopra, Matthew Rocklin, AWA BRANDON AWA, … shikharsg. (2024). zarr-developers/zarr-python: v3.0.0-alpha (v3.0.0-alpha). Zenodo. https://doi.org/10.5281/zenodo.11592827
+
+de Buyl, P., Colberg, P. H., & Höfling, F. (2014). H5MD: A structured, efficient, and portable file format for molecular data. In Computer Physics Communications (Vol. 185, Issue 6, pp. 1546–1553). Elsevier BV. https://doi.org/10.1016/j.cpc.2014.01.018
+
+Gowers, R., Linke, M., Barnoud, J., Reddy, T., Melo, M., Seyler, S., Domański, J., Dotson, D., Buchoux, S., Kenney, I., & Beckstein, O. (2016). MDAnalysis: A Python Package for the Rapid Analysis of Molecular Dynamics Simulations. In Proceedings of the Python in Science Conference. Python in Science Conference. SciPy. https://doi.org/10.25080/majora-629e541a-00e
+
+Jakupovic, E., & Beckstein, O. (2021). MPI-parallel Molecular Dynamics Trajectory Analysis with the H5MD Format in the MDAnalysis Python Package. In Proceedings of the Python in Science Conference. Python in Science Conference. SciPy. https://doi.org/10.25080/majora-1b6fd038-005
+
+Michaud‐Agrawal, N., Denning, E. J., Woolf, T. B., & Beckstein, O. (2011). MDAnalysis: A toolkit for the analysis of molecular dynamics simulations. In Journal of Computational Chemistry (Vol. 32, Issue 10, pp. 2319–2327). Wiley. https://doi.org/10.1002/jcc.21787
+
+## Extras: Upstream code merged during this GSOC project
+
+### MDAnalysis
+
+One feature I needed for testing Zarrtraj was full use of writer kwargs
+when aligning a trajectory and writing it immediately rather than storing it in memory.
+However, this feature hadn't yet been implemented, and luckily, it was a small change,
+so I worked with the core developers to merge this PR with the new feature and tests:
+-
+
+### MDAKits
+
+Since Zarrtraj is based on the [MDAnalysis MDAKit Cookiecutter](https://github.com/MDAnalysis/cookiecutter-mdakit)
+(which is a fantastic tool for getting started in making and distributing Python packages), I was able
+to find and fix a few small bugs along the way in my GSoC journey including:
+-
+-
+-
+
+### Kerchunk
+
+[Kerchunk](https://github.com/fsspec/kerchunk) is central to Zarrtraj's ability
+to read hdf5 files using Zarr. However, H5MD files (stored in hdf5) have linked
+datasets as per the H5MD standard, but Kerchunk did not translate these from
+hdf5 to Zarr previously. I was able to work alongside a Kerchunk core developer
+to add the ability to translate hdf5 datasets into Zarr along with comprehensive
+tests of this new feature.
+-
+
+## Extras: Lessons Learned
+
+Here are a bunch of random things I learned while doing this project!
+
+- Any time you need to run code that will take several hours to execute
+ due to file size or some other factor, create a minimal, quickly-executing
+ example of the code to work out bugs before running the full thing. You will
+ save yourself so, so much frustration
+- It is worth investing time into getting a debugging environment properly configured.
+ If you're hunting down a specific bug, it is worth the 20 minutes it will take to create
+ a barebones example of the bug instead of trying to hunt it down "in-situ". A lot of the time,
+ just creating the example will make you realize what was wrong. GH Actions runners sometimes
+ behave differently than your development machine. [This action](https://github.com/namespacelabs/breakpoint-action)
+ for SSHing into a runner is FANTASTIC!
+- Maintain a "tmp" directory in your locally cloned repos, gitignore it, and use it for testing random ideas
+ you have or working through bugs. Take the time to give each file in it a descriptive name!
+ Having these random scripts and ideas all in one place will pay off massively later on.
+- Take risks with ideas if you suspect they might result in cleaner and faster code,
+ even if you're not 100% sure! Experimenting is worth it.
+- Don't be afraid to read source code! Sometimes the fastest way to solving a problem
+ is seeing how someone else solved it, and sometimes the fastest way to learning
+ why someone else's code isn't doing what you expected is to read the code rather than
+ the docs.
+
From 582fbe5838bbd91417e20c96a95ce08321e642d4 Mon Sep 17 00:00:00 2001
From: Lawson Woods
Date: Sat, 3 Aug 2024 13:41:36 -0700
Subject: [PATCH 03/23] acknowledgments tweaks
---
_posts/2024-08-03-gsoc2024_woods.markdown | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/_posts/2024-08-03-gsoc2024_woods.markdown b/_posts/2024-08-03-gsoc2024_woods.markdown
index bdc5f88a..b134d8f0 100644
--- a/_posts/2024-08-03-gsoc2024_woods.markdown
+++ b/_posts/2024-08-03-gsoc2024_woods.markdown
@@ -184,10 +184,11 @@ the analysis code will need to reduce the impact of network IO on exeution time.
## Acknowledgements
-Thank you to Hugo MacDermott-Opeskin and Yuxuan Zhuang for their mentorship and feedback
-throughout this project.
+Thank you to Dr. Hugo MacDermott-Opeskin and Dr. Yuxuan Zhuang for their mentorship and feedback
+throughout this project and to Dr. Jenna Swarthout Goddard for supporting the GSoC program
+at MDAnalysis.
-I also want to thank Oliver Beckstein and Edis Jakupovic for lending their expertise
+I also want to thank Dr. Oliver Beckstein and Edis Jakupovic for lending their expertise
in H5MD and all things MDAnalysis.
Finally, another thanks to Martin Durant, author of Kerchunk, who was incredibly helpful in refining and merging
From 8939605f694bfadc6b3461aaafe3776beb67ddf7 Mon Sep 17 00:00:00 2001
From: Lawson Woods
Date: Sat, 3 Aug 2024 13:43:12 -0700
Subject: [PATCH 04/23] spelling
---
_posts/2024-08-03-gsoc2024_woods.markdown | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/_posts/2024-08-03-gsoc2024_woods.markdown b/_posts/2024-08-03-gsoc2024_woods.markdown
index b134d8f0..1be37ae8 100644
--- a/_posts/2024-08-03-gsoc2024_woods.markdown
+++ b/_posts/2024-08-03-gsoc2024_woods.markdown
@@ -206,7 +206,7 @@ Jakupovic, E., & Beckstein, O. (2021). MPI-parallel Molecular Dynamics Trajector
Michaud‐Agrawal, N., Denning, E. J., Woolf, T. B., & Beckstein, O. (2011). MDAnalysis: A toolkit for the analysis of molecular dynamics simulations. In Journal of Computational Chemistry (Vol. 32, Issue 10, pp. 2319–2327). Wiley. https://doi.org/10.1002/jcc.21787
-## Extras: Upstream code merged during this GSOC project
+## Extras: Upstream code merged during this GSoC project
### MDAnalysis
From 6381cd139551d2cc38c355586a3501cbdf5dc752 Mon Sep 17 00:00:00 2001
From: Valerij Talagayev <82884038+talagayev@users.noreply.github.com>
Date: Thu, 15 Aug 2024 09:50:31 +0200
Subject: [PATCH 05/23] GSoC 2024 - 2D visualization for small molecules (#28)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* Create 2024-08-02-gsoc2024_talagayev.md
* Update 2024-08-01-gsoc2024-final-sm.md
* Changed Figure URL
* Added figure for mdonatello display
* Update 2024-08-02-gsoc2024_talagayev.md
Adjusted the figure path
* Update _posts/2024-08-02-gsoc2024_talagayev.md
Co-authored-by: Jenna M Swarthout Goddard <38287809+jennaswa@users.noreply.github.com>
* Update _posts/2024-08-02-gsoc2024_talagayev.md
Added RDKit ref
Co-authored-by: Jenna M Swarthout Goddard <38287809+jennaswa@users.noreply.github.com>
* Update _posts/2024-08-02-gsoc2024_talagayev.md
typo error an/a
Co-authored-by: Jenna M Swarthout Goddard <38287809+jennaswa@users.noreply.github.com>
* Update _posts/2024-08-02-gsoc2024_talagayev.md
Co-authored-by: Jenna M Swarthout Goddard <38287809+jennaswa@users.noreply.github.com>
* Update _posts/2024-08-02-gsoc2024_talagayev.md
typo error in shoutout
Co-authored-by: Jenna M Swarthout Goddard <38287809+jennaswa@users.noreply.github.com>
* Update _posts/2024-08-02-gsoc2024_talagayev.md
Addition of google opensource link
Co-authored-by: Jenna M Swarthout Goddard <38287809+jennaswa@users.noreply.github.com>
* Update _posts/2024-08-02-gsoc2024_talagayev.md
Adjusted code to widget
Co-authored-by: Cédric Bouysset
* Update _posts/2024-08-02-gsoc2024_talagayev.md
Co-authored-by: Cédric Bouysset
* Update _posts/2024-08-02-gsoc2024_talagayev.md
Co-authored-by: Cédric Bouysset
* Update _posts/2024-08-02-gsoc2024_talagayev.md
Co-authored-by: Cédric Bouysset
* Update 2024-08-02-gsoc2024_talagayev.md
removed separate import of mdonatello
* Update _posts/2024-08-02-gsoc2024_talagayev.md
Co-authored-by: Cédric Bouysset
* Update _posts/2024-08-02-gsoc2024_talagayev.md
Co-authored-by: Cédric Bouysset
* Update _posts/2024-08-02-gsoc2024_talagayev.md
Co-authored-by: Cédric Bouysset
* Update _posts/2024-08-02-gsoc2024_talagayev.md
Co-authored-by: Cédric Bouysset
* Update 2024-08-02-gsoc2024_talagayev.md
removed mention of stable version
* Update _posts/2024-08-02-gsoc2024_talagayev.md
Co-authored-by: Cédric Bouysset
* Update _posts/2024-08-02-gsoc2024_talagayev.md
Co-authored-by: Cédric Bouysset
* Update 2024-08-02-gsoc2024_talagayev.md
Separated into separate bullet points the features
* Update 2024-08-02-gsoc2024_talagayev.md
Adjusted the wording in the code restructure section
---------
Co-authored-by: Jenna M Swarthout Goddard <38287809+jennaswa@users.noreply.github.com>
Co-authored-by: Cédric Bouysset
---
_posts/2024-08-01-gsoc2024-final-sm.md | 2 +-
_posts/2024-08-02-gsoc2024_talagayev.md | 197 ++++++++++++++++++++++++
public/images/mdonatello_display.png | Bin 0 -> 62742 bytes
3 files changed, 198 insertions(+), 1 deletion(-)
create mode 100644 _posts/2024-08-02-gsoc2024_talagayev.md
create mode 100644 public/images/mdonatello_display.png
diff --git a/_posts/2024-08-01-gsoc2024-final-sm.md b/_posts/2024-08-01-gsoc2024-final-sm.md
index 92ff832d..f95a7cef 100644
--- a/_posts/2024-08-01-gsoc2024-final-sm.md
+++ b/_posts/2024-08-01-gsoc2024-final-sm.md
@@ -25,4 +25,4 @@ We also thank [Google](https://opensource.google/) for supporting the students a
— @cbouy @hmacdope @IAlibay @jennaswa @richardgowers @xhgchen @yuxuanzhuang (mentors and org admins)
[blog-lawson]: {{ site.baseurl }}{% post_url .MD-FILE-NAME-HERE %}
-[blog-valerij]: {{ site.baseurl }}{% post_url .MD-FILE-NAME-HERE %}
\ No newline at end of file
+[blog-valerij]: {{ site.baseurl }}{% post_url 2024-08-02-gsoc2024_talagayev %}
diff --git a/_posts/2024-08-02-gsoc2024_talagayev.md b/_posts/2024-08-02-gsoc2024_talagayev.md
new file mode 100644
index 00000000..a373f2e1
--- /dev/null
+++ b/_posts/2024-08-02-gsoc2024_talagayev.md
@@ -0,0 +1,197 @@
+---
+layout: post
+title: GSoC 2024 - 2D visualization for small molecules
+---
+
+**Contributor**: Valerij Talagayev ([@talagayev](https://github.com/talagayev))
+
+**Mentors**: Cédric Bouysset ([@cbouy](https://github.com/cbouy)), Richard Gowers ([@richardjgowers](https://github.com/richardjgowers)) and Yuxuan Zhuang ([@yuxuanzhuang](https://github.com/yuxuanzhuang))
+
+**Organization**: [MDAnalysis](https://www.mdanalysis.org/)
+
+**Release**: [GSoC 2024: 2D visualization for small molecules Release](https://github.com/talagayev/MDonatello/releases/tag/0.0.1)
+
+During the Google Summer of Code 2024 program I was working on the [2D Visualization of small molecules](https://summerofcode.withgoogle.com/programs/2024/projects/sfy3kuqc), which is an important project, that would allow people to easily visualize the molecule that they have in their file
+through the selection of the molecule as an `AtomGroup` in `MDAnalysis`.
+
+## Goals of the project
+
+The goal of the project was to create a code, that would allow the user to select an `AtomGroup` with the help of `MDAnalysis`, which would be used with an [RDKit](https://www.rdkit.org/) Converter to convert the molecule into an rdkit mol object, which would be used for the visualization.
+
+My Proposal consisted of the following steps:
+
+- Select the AtomGroup via an input from the user via `u = mda.Universe("input.pdb")` to create an MDAnalysis Universe and `ag = u.select_atoms("resname UNK")` to select the `AtomGroup`
+with the molecule that needs to be displayed
+- Convert the selected AtomGroup into an rdkit mol object via `ag.convert_to("RDKit")`
+- Apply `Chem.RemoveHs` and `AllChem.Compute2DCoords` to obtain a 2D visualization of the molecule
+- Display the molecule via `IpyWidgets` with different checkboxes, that by selection would highlight specific parts of the molecule
+
+After discussion with the mentors and suggestions regarding how the code should be structured, it was decided that I would proceed with this suggestion and would apply the following steps with later on adding the additional
+features in the `IpyWidgets` visualization, which would give the user important information in regards to the characteristics of the molecule that is being visualized.
+
+## What I did
+
+The outcome of this GSoC program is a package called `mdonatello` which was created as follow:
+
+### Main Visualization Code
+
+The main part of the code consisted of setting up the widget for the visualization, which would allow the display of the molecule in a jupyter notebook. This is performed in the
+`MoleculeVisualizer` class that is responsible for the visualization.
+It initializes several interactive widgets from `IpyWidgets` such as a dropdown menu to select the molecule that the user wants to display and the
+checkboxes that control the aspect of the image displayed, as explained in the next section.
+
+This main code was the first part of the code that I designed and was in the beginning only able to display the molecule and had only one interactive checkbox, which displayed the atom
+indices of the molecules, but as more and more features were added the visualization grew bigger and had more features that it needed to display.
+
+### Feature Addition
+
+The feature addition was the next step that I was working on and was mainly the biggest part of the project since there was always an additional interesting feature that could be added
+that was proposed either by myself or one of the mentors.
+
+The first feature addition that I was working on were the physiochemical properties as well as the number of hydrogen bond donors and acceptors of the molecule.
+
+Next, I added checkboxes that would highlight the related features on the image. For example, I implemented pharmacophore checkboxes,
+which by selection would highlight the selected pharmacophores, thus by selecting a hydrophobic feature, the atoms of the molecule that are hydrophobic via the `RDKit` pharmacophore
+recognition were highlighted in the assigned colors.
+
+Here is a short summary of features that I added for the visualization, which would show a value for the corresponding feature or adjust the figure of the molecule to display the values:
+
+- **Phyisochemical Properties**
+- **Atom Indices**
+- **Partial Charges**
+- **Hydrogen Bond Donors&Acceptors**
+
+And here is a short summary of features, that will highlight a specific atoms and bonds corresponding to their features if they are selected:
+
+- **Rotatable Bonds**
+- **Partial Charge Heatmap**
+- **Functional Groups**
+- **Stereocenters**
+- **Murcko Scaffold**
+- **Pharmacophores**
+
+There is a separate checkbox for each pharmacophoric feature, thus you can select the specific feature
+that needs to be highlighted.
+
+For the functional groups it currently uses SMART Patterns to identify certain functional groups and will then generate the checkboxes of the functional groups that were recognized and
+by selecting them you are able to see the atoms of this functional group.
+
+### Code Restructure
+
+This is also a section where the work that was done throughout the whole project. In the beginning, the code was mainly consisting of functions in one file and this was one of the points that I was glad that my mentors helped me with. The code restructure allowed me to go from a code that was first based upon only function to structure it with classes. In the end, the
+separate classes were moved into separate files. The benefit of such a structure is that by having each class/function have a single responsibility, the code is divided into small parts, which makes it easier to understand the code and maintain it.
+
+### Actions, Testing and Documentation
+
+This would be the final part of what I did and here I would put all these three parts together. A testsuite based on the [pytest](https://docs.pytest.org/) framework was created for this project, in addition to the code being uploaded to
+[Codecov](https://app.codecov.io/gh/talagayev/mdonatello) to display the coverage of the code. Furthermore, a CI CD workflow was created, which installs the package and runs the tests on
+Linux, MacOS and Windows systems with the Python versions 3.10, 3.11 and 3.12 with different `IpyWidgets` versions, with the oldest supported version for this code being `7.6.4`. Finally,
+a documentation based on the MDAKits Template was created and can be found here: https://mdonatello.readthedocs.io/
+
+## Current State
+
+MDonatello is available and can be installed and used on your system (see the [How to use it section](#how-to-use-it)). Some improvements are planned as explained below.
+
+## What's left to do
+
+The code is working, but there is always things that can be improved. The main parts of the code that would need to be improved would be the functional groups, since currently the SMART
+Patterns are not optimal and it leads to cases of functional groups overlapping, an example being the recognition of an hydroxyl group in an carboxylic acid group, thus such cases need to
+be separated. Additionally, the figure generation is not optimal, since currently it uses `Draw.MolToImage`, which during the discussion with the mentors was decided as an not so good option
+and it would need to be adjusted. Additionally, the **Partial Charge Heatmap** is currently mainly highlighting the atoms, but there is an option to display it as a heatmap, which would require
+ code adjustment. Then the `update_display` is also not optimal currently and would need to be improved. There are also some small code structure details, that would need to be adjusted for
+the code to be more clean and structured and last, but not least the code would need to be moved into the `MDAKits` and also published in `conda-forge` and `pypi` to make it more accessible.
+
+## What code got merged (or not) upstream
+
+There were multiple PRs created for this project, but they were merged to obtain a big and summarized [PR](https://github.com/talagayev/MDonatello/pull/1), which is also the version that is
+used in the [Release](https://github.com/talagayev/MDonatello/releases/tag/0.0.1)
+
+## How to use it
+
+Currently `MDonatello` is a separate package that can be git cloned and installed with the following steps:
+
+First clone the repository:
+
+```
+git clone https://github.com/talagayev/MDonatello
+```
+
+Create a virtual environment and activate it:
+
+```
+conda create --name mdonatello
+conda activate mdonatello
+```
+
+Then go into the MDonatello folder:
+
+```
+cd MDonatello
+```
+
+Finally this package from source:
+
+```
+pip install -e .
+```
+
+To use the **mdonatello** package you need to run a jupyter notebook, thus run the command:
+
+
+```
+jupyter notebook
+```
+
+Now that you started a jupyter notebook create a notebook file and enter the following command to use **mdonatello**:
+Here you need to adjust the name of the PDB File to your PDB File and the resname of the molecule to your molecule
+
+```python
+import MDAnalysis as mda
+from mdonatello import MoleculeVisualizer
+
+u = mda.Universe("input.pdb")
+ag = u.select_atoms("resname UNK")
+visualizer = MoleculeVisualizer(ag, show_atom_indices=False, width=-1, height=-1)
+```
+
+This would lead you to obtain the following display, where you could then select the molecule and checkboxes:
+
+
+
+## Lessons Learned During GSoC
+
+Here I would highlight some lessons that I learned during GSoC2024:
+
+- Have an Idea of the overall structure of the code
+- Discuss the ideas with the mentors to see their opinion
+- Don't be afraid to ask questions
+- Try to work on different aspects of the code (in my case I was almost always only focusing on feature addition and needed to get reminded that there are other parts)
+- Try to learn as much from the mentors and apply it in your code
+- Getting a meeting with all mentors that have different time zones is sometimes tricky :)
+
+## Conclusion & The Future
+
+It was a fun project and I liked working on it, but the work doesn't stop here. As I mentioned some aspects of the code can be improved and things that can be
+done, so I will continue to work on the code after GSoC 2024, here are again the short highlights that I already mentioned that I would work on:
+
+- Code structure improvement
+- Figure Generation and SMART Patterns need to be improved
+- Heatmap needs to be created for partial charges instead of atom highlighting
+- Adding the package to `MDAKits` and `conda-forge`
+- New Features can be added
+
+## Acknowledgements
+
+I would like to thank [MDAnalysis](https://www.mdanalysis.org/) for giving me the opportunity to work on this project. The application process was very nice and detailed,
+I liked it that during the application process. I was able to get to know the MDAnalysis code more and contribute to the code and get to know some people from the community
+during this time.
+
+I would like to thank Oliver Beckstein ([@orbeckst](https://github.com/orbeckst)) and Jenna M Swarthout Goddard([@jennaswa](https://github.com/jennaswa)) for the insights and help with the organization and structure during the application, I am glad that I was able to contribute to MDAnalysis with this project.
+
+I would also like to thank my mentors Cédric Bouysset ([@cbouy](https://github.com/cbouy)), Richard Gowers ([@richardjgowers](https://github.com/richardjgowers)) and Yuxuan Zhuang ([@yuxuanzhuang](https://github.com/yuxuanzhuang)), who helped me a lot during the project, with their helpful and insightful mentoring. I am glad, that I was able to learn from you and it helped me to improve
+my coding skills. Also, shoutout to Hugo MacDermott-Opeskin ([@hmacdope](https://github.com/hmacdope)) for his help with the PR requests during the application process.
+
+Finally, I would also like to thank [Google](https://opensource.google/) for offering this program and supporting open-source software.
diff --git a/public/images/mdonatello_display.png b/public/images/mdonatello_display.png
new file mode 100644
index 0000000000000000000000000000000000000000..00c38c95299c3605ad0d2a73c14a11c7f78a16d2
GIT binary patch
literal 62742
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
z
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