<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://hydroaggie.github.io/feed.xml" rel="self" type="application/atom+xml"/><link href="https://hydroaggie.github.io/" rel="alternate" type="text/html" hreflang="en"/><updated>2026-06-16T20:23:56+00:00</updated><id>https://hydroaggie.github.io/feed.xml</id><title type="html">Shuai Computational and Integrated Hydrology Group</title><subtitle>The SCI-Hy research group at USU. </subtitle><entry><title type="html">Academic Use Cases with Claude</title><link href="https://hydroaggie.github.io/blog/2026/Academic-Usecase-with-Claude/" rel="alternate" type="text/html" title="Academic Use Cases with Claude"/><published>2026-04-23T00:00:00+00:00</published><updated>2026-04-23T00:00:00+00:00</updated><id>https://hydroaggie.github.io/blog/2026/Academic-Usecase-with-Claude</id><content type="html" xml:base="https://hydroaggie.github.io/blog/2026/Academic-Usecase-with-Claude/"><![CDATA[<p>With agentic AI tools taking the world by storm, this post explores various academic use cases with <a href="https://code.claude.com/docs/en/overview">Claude Code</a>, an AI assistant developed by Anthropic. We will focus on research tasks such as literature assistance, codebase support, etc. The idea is to use AI as your personal research assistant but not to replace your own thinking and creativity.</p> <blockquote class="block-tip"> <p><strong>Note:</strong> This post will be updated as I discover new use cases and tools. Check back for the latest additions.</p> </blockquote> <h2 id="literature-search">Literature Search</h2> <p>I usually start my research by doing a literature search on Google Scholar, finding a few interesting papers, and then—based on those papers—searching for other related papers (e.g., papers that have cited them). This is time-consuming and often I find myself getting lost in the sea of papers. With Claude, I can quickly find relevant papers based on a specific topic or keyword using natural language. For example, if I’m interested in “machine learning in hydrology,” I can ask Claude to retrieve relevant papers published in the last 5 years using a prompt like:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Find the top 5 most cited papers on "machine learning in hydrology" published in the last 5 years.
</code></pre></div></div> <p>Claude will search the web including Google Scholar and return a list of relevant papers, including their titles, authors, publication years, and even a brief summary if available. Then, I can further ask Claude to look for papers that have cited these key papers, like a citation graph, to get other relevant papers. Optionally, you can ask Claude to retrieve the PDF or fulltext of the papers if they are accessible. You can then pass those papers to Zotero for management and annotation (see next section).</p> <p>You can even ask Claude to write a literature review based on the retrieved papers, though I haven’t tested that yet.</p> <h3 id="setup">Setup</h3> <ul> <li>Install the <a href="https://github.com/openags/paper-search-mcp">Paper Search MCP</a>.</li> </ul> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone https://github.com/openags/paper-search-mcp.git ~/paper-search-mcp

<span class="c"># Set up the skill for Claude Code</span>
<span class="nb">mkdir</span> <span class="nt">-p</span> ~/.claude/skills/paper-search
<span class="nb">cp</span> ~/paper-search-mcp/claude-code/SKILL.md ~/.claude/skills/paper-search/SKILL.md
</code></pre></div></div> <ul> <li>Edit the <code class="language-plaintext highlighter-rouge">SKILL.md</code> file to replace the placeholder values <code class="language-plaintext highlighter-rouge">&lt;REPO_PATH&gt;</code>. You can also just ask Claude to edit the file for you.</li> </ul> <h2 id="literature-management">Literature Management</h2> <h3 id="search-for-relevant-papers-in-zotero">Search for Relevant Papers in Zotero</h3> <p>I find this the most useful feature. I use Zotero to manage my references, and I often struggle to find relevant papers when the library contains hundreds of entries. The search function in Zotero is just not that good. With Claude, I can quickly find papers related to a specific topic or keyword using natural language. For instance, if I’m researching “machine learning in hydrology,” I can ask Claude to retrieve relevant papers from my Zotero library, using a prompt like:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Find papers in my Zotero library related to "machine learning in hydrology" in the last 5 years.
</code></pre></div></div> <p>Then Claude will return a list of relevant papers, including their titles, authors, publication years, and even a brief summary if available. This saves me a lot of time and helps me stay organized with my research materials.</p> <p>The main benefit of using Zotero is it prevents Claude from hallucinating papers that do not exist.</p> <h3 id="summarize-research-papers">Summarize Research Papers</h3> <p>Another great use case is summarizing research papers. I often annotate papers as I read and have developed a color code for different annotation types. When I am done, I export the annotations as notes to my Obsidian app (see my previous <a href="/blog/2023/A-Zotero-to-Obsidian-Workflow/">post</a> on this workflow). I also like to write a short summary highlighting the key points and knowledge gaps. All of this was done manually, and it can be time-consuming when you have many papers. With Claude, I can quickly generate summaries of papers based on my annotations and let it write the note into Zotero or Obsidian. For example, I can ask:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Summarize the key findings and knowledge gaps of Shuai et al., 2017 based on my annotations and write this as note in Zotero.
</code></pre></div></div> <p>Claude may ask a few clarifying questions about the note. It will then generate a concise summary based on the annotations. When you open Zotero, the note is there. This is especially useful when I want to quickly review the key points of a paper without having to read through the entire document again. It also helps me keep my notes organized and easily accessible for future reference.</p> <p>You can also ask Claude to write a “when to cite” section based on the summary and annotations.</p> <h3 id="setup-1">Setup</h3> <ul> <li>Install the <a href="https://github.com/54yyyu/zotero-mcp">Zotero MCP</a>.</li> </ul> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># install zotero mcp</span>
uv tool <span class="nb">install </span>zotero-mcp-server

<span class="c"># set up </span>
zotero-mcp setup  <span class="c"># Auto-configure (Claude Desktop supported)</span>
<span class="c"># this will configure a few options</span>

<span class="c">#optional. this will enable pdf outline extraction, scite citation...</span>
uv tool <span class="nb">install</span> <span class="s2">"zotero-mcp-server[all]"</span>    <span class="c"># Full install with all features</span>
</code></pre></div></div> <ul> <li>Enable Zotero Local API: <code class="language-plaintext highlighter-rouge">Settings--&gt;Advanced--&gt;Miscellaneous</code>, toggle the box for <em>Allow other applications on this computer to communicate with Zotero</em>. It will say <code class="language-plaintext highlighter-rouge">Available at http://localhost:23119/api/</code></li> <li>Initialize and Update database.</li> </ul> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Build the semantic search database (fast, metadata-only)</span>
zotero-mcp update-db

<span class="c"># Build with full-text extraction (slower, more comprehensive)</span>
zotero-mcp update-db <span class="nt">--fulltext</span>
</code></pre></div></div> <h2 id="manage-email-subscription">Manage Email Subscription</h2> <p>I often subscribe to Google Scholar alerts for my research topic and have them sent to my Gmail account. I then read those emails to find new papers relevant to my research. With Claude, I can automate this process by having it access my Gmail account and retrieve the alerts and create a well formatted newsletter for me on a regular basis (e.g., weekly). Claude can intelligently group papers by themes, summarize the key findings, and even highlight the most relevant papers based on my research interests. This way, I can stay up-to-date with the latest research without having to manually check my email for alerts.</p> <p>This may sound like the scariest scenario—having Claude access your personal email—but if you prefer not to use your personal account, you can set up a separate dummy Gmail account just for this purpose.</p> <h3 id="setup-2">Setup</h3> <p>Set up is pretty straightforward. You just need to connect your Gmail account to Claude.</p> <ul> <li>Download and install the Claude Desktop app.</li> <li>Go to <code class="language-plaintext highlighter-rouge">Customize--&gt;Connectors--&gt;Gmail</code> and connect your Gmail account. You can choose the different read/write permissions based on your needs.</li> </ul> <h2 id="codebase-expert">Codebase Expert</h2> <p>I often use open-source code in my research, but it can be difficult to understand how it works, especially when the codebase is large and complex. For example, I use ATS for hydrologic modeling and sometimes need to know how ATS calculates certain fields and what the governing equations are. With Claude, I can quickly get the answer by asking specific questions about how certain functions or modules work. For example, if I want to understand how ATS calculates longwave radiation internally, I can ask Claude:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Can you explain how the longwave radiation is calculated in ATS?
</code></pre></div></div> <p>Claude will then search through the codebase and provide a detailed explanation of the relevant functions and equations used in the calculation.</p> <h3 id="setup-3">Setup</h3> <p>This requires a customized MCP that connects to the codebase. Without an MCP, Claude will try to search the web or the GitHub repo, which may not be efficient and can lead to hallucinations. With an MCP, Claude can directly access the codebase and provide accurate, detailed explanations.</p> <p>I do not have experience with this, so I just ask Claude to build the MCP for me using existing examples. I mostly followed the <code class="language-plaintext highlighter-rouge">pywrdrb-mcp</code> <a href="https://waterprogramming.wpcomstaging.com/2026/03/03/a-beginners-guide-for-the-llm-curious-part-2-custom-model-context-protocol-to-improve-llm-supported-code-development/">example</a> and adopted their <a href="https://github.com/Pywr-DRB/pywrdrb-mcp">repo</a> structure.</p> <p>In the end, I built a custom MCP—<code class="language-plaintext highlighter-rouge">ats-mcp</code>—which I can use to ask questions about the ATS codebase, including source code, documentation, test cases, and demo examples across multiple repositories.</p> <h2 id="usgs-water-data-retrieval">USGS Water Data Retrieval</h2> <p>Retrieve USGS water data using the <a href="https://github.com/pinshuai/usgs-water-mcp">USGS Water Data MCP</a>. This MCP uses the USGS Water Data API to retrieve water data such as streamflow, groundwater levels, and water quality parameters based on user queries. For example, if I want to retrieve streamflow data for a specific location and time period, I can ask Claude:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Plot the streamflow for the Logan River in Utah for the last year.
</code></pre></div></div> <h2 id="other-applications">Other Applications</h2> <ul> <li><strong>Git commit message</strong>: Use Claude to generate descriptive commit messages based on the changes in the code. Just say:</li> </ul> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>commit this
</code></pre></div></div> <p>This requires authentication with GitHub or another version control system. I find Claude very helpful for generating clear and concise commit messages, especially since I often forget exactly what changes I made.</p> <h2 id="tips">Tips</h2> <p>These are some tips that I found useful when using Claude. Many of these can also be found in the <a href="https://code.claude.com/docs/en/best-practices">official documentation</a> and community posts (e.g., <a href="https://github.com/ykdojo/claude-code-tips">claude-code-tips</a>).</p> <ul> <li> <p><strong>Context matters</strong>. Use <code class="language-plaintext highlighter-rouge">@</code> to directly reference files and <code class="language-plaintext highlighter-rouge">/add-dir</code> to add a directory to the context, or paste screenshots or code snippets. This will help Claude understand the task better and provide more accurate responses. However, too much context will slow down Claude and cause it to forget what was told earlier.</p> </li> <li> <p><strong>Plan first</strong> before you let Claude do the work. Ask Claude to come up with a detailed plan for a task. Let Claude ask you clarifying questions to make sure it understands the task correctly. This will save you time and tokens in the long run. E.g.,<code class="language-plaintext highlighter-rouge">I want to build a personal website. Interview me in detail to understand my needs and preferences, then come up with a detailed plan for how to build the website.</code></p> </li> <li> <p>Provide <strong>verification</strong> or success criteria for the task you want to accomplish. If possible, provide some test cases or expected outputs (e.g., a screenshot). At the minimum, put a “success criteria” section in the end of the prompt and let Claude verify if the task is accomplished successfully. This can greatly reduce the chances of getting an inaccurate or incomplete response from Claude.</p> </li> <li> <p>Ask Claude to correct its own mistakes. If you find that the response from Claude is not accurate or contains errors, you can ask it to correct itself and put what it has learned into the memory so it won’t make the same mistake again. It is kind of like training an AI to improve itself over time.</p> </li> <li> <p>Provide a concise readme file–<code class="language-plaintext highlighter-rouge">CLAUDE.md</code> for every project. This could include specific instructions, commands, best practices, and common gotchas for using Claude with that project.</p> </li> <li> <p>Use skills–<code class="language-plaintext highlighter-rouge">SKILL.md</code> for repetitive workflows. If you find yourself doing the same thing over and over again, consider creating a skill for it. For example, if you often ask Claude to create a newsletter from common sources in a specific format, you can create a skill (e.g., <code class="language-plaintext highlighter-rouge">/create-newsletter</code>) that automates this process.</p> </li> <li> <p>Ask Claude if you don’t know how to do something. For example, if you want to set up a MCP but don’t know how to do it, just ask Claude:<code class="language-plaintext highlighter-rouge"> How can I set up a MCP to connect to my codebase?</code> Even better, provide an example that you found somewhere and ask Claude to understand it and learn from it: <code class="language-plaintext highlighter-rouge">Use this example (link to the example) to learn how to set up a MCP, then use it to create a MCP for my codebase.</code></p> </li> <li> <p>Don’t be afraid to experiment and try new things with Claude. The more you use it, the more you will discover its capabilities and how it can best assist you in your academic work.</p> </li> </ul> <h2 id="reference">Reference</h2> <ul> <li><a href="https://waterprogramming.wpcomstaging.com/2026/03/03/a-beginners-guide-for-the-llm-curious-part-2-custom-model-context-protocol-to-improve-llm-supported-code-development">A Beginner’s Guide for the LLM-Curious, Part 2</a></li> <li><a href="https://code.claude.com/docs/en/best-practices">Claude Code Best Practices</a></li> <li><a href="https://github.com/ykdojo/claude-code-tips">claude-code-tips</a></li> </ul>]]></content><author><name></name></author><category term="tutorial"/><category term="claude"/><category term="MCP"/><category term="AI tools"/><summary type="html"><![CDATA[A collection of use cases for academics using Claude Code.]]></summary></entry><entry><title type="html">Publish A Python Package on Conda</title><link href="https://hydroaggie.github.io/blog/2025/Publish-Python-Package-on-Conda/" rel="alternate" type="text/html" title="Publish A Python Package on Conda"/><published>2025-09-17T00:00:00+00:00</published><updated>2025-09-17T00:00:00+00:00</updated><id>https://hydroaggie.github.io/blog/2025/Publish-Python-Package-on-Conda</id><content type="html" xml:base="https://hydroaggie.github.io/blog/2025/Publish-Python-Package-on-Conda/"><![CDATA[<p>This post will show the process of publish a python package on Anaconda, specifically on conda-forge. The steps mostly follows this <a href="https://blog.gishub.org/how-to-publish-a-python-package-on-conda-forge">post</a> by <a href="https://github.com/giswqs">Qiusheng Wu</a> and the official <a href="https://docs.conda.io/projects/conda-build/en/stable/user-guide/tutorials/build-pkgs.html">guide</a>.</p> <p>Before you start, make sure you have created and published the python package on Pypi.</p> <h2 id="create-conda-environment-and-install-conda-install">Create conda environment and install conda-install</h2> <p>In this example, we use <code class="language-plaintext highlighter-rouge">pypackage</code> as the environment name.</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>conda create --name pypackage python
conda activate pypackage
conda install conda-build
conda install grayskull
</code></pre></div></div> <h2 id="download-pypi-package-locally">Download Pypi package locally</h2> <p>This assumes that you have already published your package on Pypi. If not, please refer to my previous <a href="https://hydroaggie.github.io/blog/2022/Publish-Python-Package-on-Pypi/">post</a> on how to publish a python package on Pypi.</p> <p>You can download the package from Pypi using:</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pip download --no-deps --no-binary :all: &lt;package_name&gt;
</code></pre></div></div> <p>This will download a tarball file (e.g., <code class="language-plaintext highlighter-rouge">&lt;package_name&gt;-0.1.0.tar.gz</code>) to the current working directory.</p> <h2 id="create-conda-recipe">Create conda recipe</h2> <p>The only thing that’s needed for creating the conda package is a <code class="language-plaintext highlighter-rouge">meta.yaml</code> file. I will use the <a href="https://github.com/conda-forge/staged-recipes/blob/main/recipes/example/meta.yaml">template</a> provided by Conda-recipe.</p> <p>To fill the <code class="language-plaintext highlighter-rouge">meta.yaml</code> file, we can use <code class="language-plaintext highlighter-rouge">grayskull</code> to generate a template based on the package on Pypi.</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>grayskull pypi &lt;package_name&gt;
</code></pre></div></div> <p>Open the template and change the following fields:</p> <ul> <li><code class="language-plaintext highlighter-rouge">package/name</code>: the name of your package</li> <li><code class="language-plaintext highlighter-rouge">package/version</code>: the version of your package</li> <li><code class="language-plaintext highlighter-rouge">source/url</code>: the URL of the source code, usually the tarball link on Pypi</li> <li><code class="language-plaintext highlighter-rouge">source/sha256</code>: the sha256 checksum of the source code tarball. You can get it using <code class="language-plaintext highlighter-rouge">sha256sum &lt;package_name-xxx.tar.gz&gt; </code></li> <li><code class="language-plaintext highlighter-rouge">requirements/build</code>: the build dependencies, usually <code class="language-plaintext highlighter-rouge">python</code> and <code class="language-plaintext highlighter-rouge">pip</code></li> <li><code class="language-plaintext highlighter-rouge">requirements/run</code>: the runtime dependencies, usually the packages listed in <code class="language-plaintext highlighter-rouge">requirements.txt</code> on Github repo</li> <li>license: the license of your package, e.g., <code class="language-plaintext highlighter-rouge">MIT</code></li> <li>license_file: the license file, e.g., <code class="language-plaintext highlighter-rouge">LICENSE.txt</code></li> </ul> <p>The rest of the fields can be left as default.</p> <h2 id="add-recipe-to-staged-recipes-repo">Add recipe to staged-recipes repo</h2> <ul> <li>Fork the <a href="https://github.com/conda-forge/staged-recipes">staged-recipes</a> repo</li> <li>Clone the forked repo to your local machine</li> <li>Create a new branch using <code class="language-plaintext highlighter-rouge">git checkout -b add-&lt;package_name&gt;</code></li> <li>Create a new folder under <code class="language-plaintext highlighter-rouge">recipes</code> with the same name as your package</li> <li>Add the <code class="language-plaintext highlighter-rouge">meta.yaml</code> file to the new folder</li> <li>Commit the changes using <code class="language-plaintext highlighter-rouge">git commit -m "Add &lt;package_name&gt; recipe"</code></li> <li>Push the changes to your forked repo using `git push origin add-&lt;package_name</li> <li>Create a pull request to the original <code class="language-plaintext highlighter-rouge">staged-recipes</code> repo</li> </ul> <p>After your PR passes the review (make sure your ping using the comment “@conda-forge/help-python, ready for review!”), it will be merged to the main branch and your package will be built and uploaded to conda-forge automatically.</p> <h2 id="test-the-package">Test the package</h2> <p>You can create a new conda environment and install your package from conda-forge to test if it works.</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>conda create --name testenv python
conda activate testenv
conda install -c conda-forge &lt;package_name&gt;
</code></pre></div></div> <h2 id="update-the-package">Update the package</h2> <p>To update the package, you need to:</p> <ol> <li>Update the version number in the <code class="language-plaintext highlighter-rouge">meta.yaml</code> file.</li> <li>Update the source/url using the new version from Pypi.</li> <li>Download the new tarball and update the <code class="language-plaintext highlighter-rouge">source/url</code> and <code class="language-plaintext highlighter-rouge">source/sha256</code> fields in the <code class="language-plaintext highlighter-rouge">meta.yaml</code> file.</li> <li>Commit the changes and push to your forked repo.</li> <li>Create a pull request to the original <code class="language-plaintext highlighter-rouge">staged-recipes</code> repo.</li> </ol> <h2 id="reference">Reference</h2> <ul> <li>Build conda package from scratch: https://docs.conda.io/projects/conda-build/en/stable/user-guide/tutorials/build-pkgs.html</li> <li>How to publish a python package on conda-forge: https://blog.gishub.org/how-to-publish-a-python-package-on-conda-forge</li> </ul>]]></content><author><name></name></author><category term="tutorial"/><category term="python"/><summary type="html"><![CDATA[A tutorial on how to publish a python package on Conda]]></summary></entry><entry><title type="html">How to use LaTeX in VScode as an Overleaf alternative</title><link href="https://hydroaggie.github.io/blog/2025/Use-Latex-in-VScode/" rel="alternate" type="text/html" title="How to use LaTeX in VScode as an Overleaf alternative"/><published>2025-07-22T00:00:00+00:00</published><updated>2025-07-22T00:00:00+00:00</updated><id>https://hydroaggie.github.io/blog/2025/Use-Latex-in-VScode</id><content type="html" xml:base="https://hydroaggie.github.io/blog/2025/Use-Latex-in-VScode/"><![CDATA[<p>This post follows the <a href="https://mark-wang.com/blog/2022/latex/">original blog</a> by Mark Wang with a few modifications.</p> <h2 id="motivation">Motivation</h2> <p>I previously used <a href="https://www.overleaf.com/">Overleaf</a>, a cloud-based LaTeX editor, during my time at PNNL. Overleaf is excellent for creating professional manuscripts and supports collaboration, especially for premium users. However, after moving to the university, I lost access to the premium subscription and had to rely on the free version, which comes with limitations such as restricted compile time and slower performance. This prompted me to search for alternatives, and I discovered Mark Wang’s <a href="https://mark-wang.com/blog/2022/latex/">post</a> about using LaTeX in VSCode as a replacement for Overleaf. If you’re curious about how LaTeX works in VSCode, I recommend checking out his original <a href="https://mark-wang.com/blog/2022/latex/">post</a> for a detailed overview.</p> <h2 id="setup-environment">Setup environment</h2> <p>You will need a local installation of LaTeX, VScode and LaTex-Workshop extension to make it work.</p> <h3 id="installing-latex">Installing LaTeX</h3> <p>To install LaTeX using Mac as an example, go to TeX Live <a href="https://tug.org/texlive/quickinstall.html">quick install page</a>. I followed the macOS approach by downloading MacTeX (~6 GB) and installing it on my Mac Studio (Apple silicon).</p> <h3 id="installing-vscode-and-extension">Installing VScode and extension</h3> <p>Install VSCode for Mac from the offical <a href="https://code.visualstudio.com/download">website</a>. Once installed, open VSCode and install the extension named <code class="language-plaintext highlighter-rouge">LaTeX Workshop</code>.</p> <h2 id="using-latex-in-vscode">Using LaTeX in VSCode</h2> <p>First, download or locate the LaTeX files on your computer. For me, I have downloaded my LaTeX files from Overleaf. Then use VSCode to open the folder that contains the LaTeX files. Open the LaTeX file (e.g., <code class="language-plaintext highlighter-rouge">paper.tex</code>) using the VSCode editor.</p> <p>Now you can view and edit your LaTeX file and make any changes. After you are done, click on the green triangle located on the top right panel to compile the LaTeX file. Or simply use keyboard shortcut <code class="language-plaintext highlighter-rouge">Cmd + Option + B</code> (Mac) or <code class="language-plaintext highlighter-rouge">Ctrl + Alt + B</code> (Windows/Linux) to compile the LaTeX file.</p> <p>To view the compiled PDF, you can either click on the <code class="language-plaintext highlighter-rouge">View LaTeX PDF</code> button on the top right panel or use the keyboard shortcut <code class="language-plaintext highlighter-rouge">Cmd + Option + V</code> (Mac) or <code class="language-plaintext highlighter-rouge">Ctrl + Alt + V</code> (Windows/Linux). This will open a new tab in VSCode showing the compiled PDF.</p> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/blog/latex_vscode-480.webp 480w,/assets/img/blog/latex_vscode-800.webp 800w,/assets/img/blog/latex_vscode-1400.webp 1400w," type="image/webp" sizes="95vw"/> <img src="/assets/img/blog/latex_vscode.png" class="img-fluid rounded z-depth-1" width="100%" height="auto" loading="eager" onerror="this.onerror=null; $('.responsive-img-srcset').remove();"/> </picture> <figcaption class="caption">An example of using LaTeX in VSCode with side-by-side editor and PDF preview.</figcaption> </figure> <p>To jump from a specific line in the LaTeX file to the corresponding location in the PDF, you can use the <code class="language-plaintext highlighter-rouge">SyncTeX</code> feature. Simply place your cursor on the line you want to jump from and press <code class="language-plaintext highlighter-rouge">Cmd + Option + J</code> (Mac) or <code class="language-plaintext highlighter-rouge">Ctrl + Alt + J</code> (Windows/Linux). This will synchronize the LaTeX file with the PDF and take you to the corresponding location. To do the reverse, you can click on the PDF and press <code class="language-plaintext highlighter-rouge">Cmd + Click</code> (Mac) or <code class="language-plaintext highlighter-rouge">Ctrl + Click</code> (Windows/Linux) to jump back to the LaTeX file.</p> <h2 id="configuring-latex-workshop-to-make-it-more-like-overleaf">Configuring LaTeX-Workshop to make it more like Overleaf</h2> <ol> <li>To enable auto build in VSCode, go to the settings (<code class="language-plaintext highlighter-rouge">Cmd + Shift + P</code>) and search for “Preferences: Configure language specific settings…”. Check the box for “Files: Auto Save”. This will automatically trigger the build when you make changes, allowing for an instant preview of your latest PDF.</li> <li>Under the same settings, go to “Editor: Word Wrap”. Set it to <code class="language-plaintext highlighter-rouge">on</code> to enable line wrapping in LaTeX files.</li> </ol> <h2 id="conclusion">Conclusion</h2> <p>Using LaTeX in VSCode is a great alternative to Overleaf, especially if you prefer a local setup or you do not need collaboration features. Plus, you can also utilize the rich collection of extensions offered by VSCode. For example, you can use the CoPilot extension to get AI-assisted writing suggestions.</p> <p>On the downside, this setup requires a local installation of LaTeX, which can take up significant disk space and may require some initial configuration. However, once set up, it provides a powerful and flexible environment for writing LaTeX documents.</p>]]></content><author><name></name></author><category term="tutorial"/><category term="LaTeX"/><category term="VScode"/><summary type="html"><![CDATA[Tutorial on how to use LaTeX in VScode as an alternative to Overleaf]]></summary></entry><entry><title type="html">A Quick Intro to Markdown</title><link href="https://hydroaggie.github.io/blog/2025/How-to-Markdown/" rel="alternate" type="text/html" title="A Quick Intro to Markdown"/><published>2025-03-21T00:00:00+00:00</published><updated>2025-03-21T00:00:00+00:00</updated><id>https://hydroaggie.github.io/blog/2025/How-to-Markdown</id><content type="html" xml:base="https://hydroaggie.github.io/blog/2025/How-to-Markdown/"><![CDATA[<p>Redirecting to another page.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Slides of a quick introduction to Markdown]]></summary></entry><entry><title type="html">Steps to manually calibrate a Solinst Levelogger</title><link href="https://hydroaggie.github.io/blog/2025/How-to-levelogger/" rel="alternate" type="text/html" title="Steps to manually calibrate a Solinst Levelogger"/><published>2025-03-21T00:00:00+00:00</published><updated>2025-03-21T00:00:00+00:00</updated><id>https://hydroaggie.github.io/blog/2025/How-to-levelogger</id><content type="html" xml:base="https://hydroaggie.github.io/blog/2025/How-to-levelogger/"><![CDATA[<p>Redirecting to pdf</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Steps for manually calibrating a Solinst Levelogger using barometric compensation]]></summary></entry><entry><title type="html">Tutorial on Building a PFLOTRAN Docker Image</title><link href="https://hydroaggie.github.io/blog/2025/Build-PFLOTRAN-Docker-Image/" rel="alternate" type="text/html" title="Tutorial on Building a PFLOTRAN Docker Image"/><published>2025-02-04T00:00:00+00:00</published><updated>2025-02-04T00:00:00+00:00</updated><id>https://hydroaggie.github.io/blog/2025/Build-PFLOTRAN-Docker-Image</id><content type="html" xml:base="https://hydroaggie.github.io/blog/2025/Build-PFLOTRAN-Docker-Image/"><![CDATA[<p>Docker is a powerful tool for creating reproducible environments. In this tutorial, I will show you how to build a Docker image for running PFLOTRAN and JupyterLab. The image is built on top of the <code class="language-plaintext highlighter-rouge">ubuntu:20.04</code> image and includes PFLOTRAN, PETSc, and JupyterLab. The image is built for both <code class="language-plaintext highlighter-rouge">x86_64</code> and <code class="language-plaintext highlighter-rouge">arm64</code> architectures on a Mac M1 chip.</p> <h2 id="pre-requisites">Pre-requisites:</h2> <ul> <li>Docker installed on your machine. If you don’t have Docker installed, you can download it from <a href="https://docs.docker.com/get-docker/">here</a>.</li> </ul> <h2 id="setup">Setup</h2> <h3 id="create-a-dockerfile">Create a Dockerfile</h3> <p>A Dockerfile is a text document that contains all the commands a user could call on the command line to assemble an image. The Dockerfile named “<code class="language-plaintext highlighter-rouge">dockerfile-jupyter-pflotran</code>” for building PFLOTRAN is shown below.</p> <div class="language-dockerfile highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Base image and setup</span>
<span class="k">FROM</span><span class="w"> </span><span class="s">ubuntu:22.04</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="s">base</span>
<span class="k">LABEL</span><span class="s"> org.opencontainers.image.ref.name="ubuntu"</span>
<span class="k">LABEL</span><span class="s"> org.opencontainers.image.version="22.04"</span>
<span class="k">LABEL</span><span class="s"> org.opencontainers.image.authors="Pin Shuai"</span>
<span class="k">LABEL</span><span class="s"> org.opencontainers.image.description="Docker image for running PFLOTRAN v6.0 with JupyterLab"</span>

<span class="k">ARG</span><span class="s"> NB_USER=aggie</span>
<span class="k">ARG</span><span class="s"> NB_UID=1000</span>
<span class="k">ARG</span><span class="s"> NB_GID=100</span>
<span class="k">ARG</span><span class="s"> PETSC_VERSION=v3.21.4  # Replace with the desired PETSc version so it works with the pflotran branch</span>
<span class="k">ARG</span><span class="s"> pflotran_branch=v6.0  # Replace with the desired PFLOTRAN branch</span>
<span class="k">ENV</span><span class="s"> DEBIAN_FRONTEND=noninteractive</span>
<span class="k">ENV</span><span class="s"> NB_USER=$NB_USER NB_UID=$NB_UID NB_GID=$NB_GID</span>
<span class="k">ENV</span><span class="s"> SHELL=/bin/bash</span>
<span class="k">ENV</span><span class="s"> PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin</span>

<span class="k">ENV</span><span class="s"> PETSC_DIR=/scratch/petsc \</span>
    PETSC_ARCH=petsc-arch 

<span class="c"># Add fix-permissions script</span>
<span class="k">COPY</span><span class="s"> fix-permissions /usr/local/bin/fix-permissions</span>
<span class="k">RUN </span><span class="nb">chmod</span> +x /usr/local/bin/fix-permissions

<span class="c"># Install prerequisites</span>
<span class="k">RUN </span>apt update <span class="nt">-qq</span> <span class="o">&amp;&amp;</span> <span class="se">\
</span>    apt <span class="nb">install</span> <span class="nt">-y</span> <span class="nt">--no-install-recommends</span> <span class="se">\
</span>        git make cmake gcc gfortran g++ wget nano vim python3 python3-pip lcov ca-certificates <span class="o">&amp;&amp;</span> <span class="se">\
</span>    apt clean <span class="o">&amp;&amp;</span> <span class="se">\
</span>    <span class="nb">rm</span> <span class="nt">-rf</span> /var/lib/apt/lists/<span class="k">*</span>


<span class="c"># Create user and set permissions. -m creates the home directory, -s sets the shell, -N does not create a group</span>
<span class="k">RUN </span>useradd <span class="nt">-m</span> <span class="nt">-s</span> /bin/bash <span class="nt">-N</span> <span class="nt">-u</span> <span class="nv">$NB_UID</span> <span class="nv">$NB_USER</span> <span class="o">&amp;&amp;</span> <span class="se">\
</span>    fix-permissions /home/<span class="nv">$NB_USER</span>

<span class="c"># Conda and Python setup</span>
<span class="k">USER</span><span class="s"> $NB_USER</span>
<span class="k">WORKDIR</span><span class="s"> /home/$NB_USER</span>

<span class="c"># install jupyter and Install Python packages</span>
<span class="k">RUN </span>pip3 <span class="nb">install</span> <span class="nt">-U</span> virtualenv
<span class="k">RUN </span>pip3 <span class="nb">install</span> <span class="nt">-U</span> jupyterlab h5py matplotlib hydroeval numpy scipy pandas <span class="o">&amp;&amp;</span> pip3 cache purge
<span class="k">ENV</span><span class="s"> PATH=/home/${NB_USER}/.local/bin:$PATH</span>

<span class="c"># Add JupyterLab configuration</span>
<span class="k">USER</span><span class="s"> root</span>
<span class="k">COPY</span><span class="s"> jupyter_server_config.py /etc/jupyter/</span>
<span class="k">COPY</span><span class="s"> jupyter_notebook_config.py /etc/jupyter/</span>
<span class="k">RUN </span><span class="nb">chmod</span> +x /etc/jupyter/jupyter_server_config.py 
<span class="k">RUN </span><span class="nb">chmod</span> +x /etc/jupyter/jupyter_notebook_config.py
<span class="k">RUN </span><span class="nb">mkdir</span> /home/<span class="k">${</span><span class="nv">NB_USER</span><span class="k">}</span>/.jupyter
<span class="k">COPY</span><span class="s"> jupyter_notebook_config.py /home/${NB_USER}/.jupyter</span>
<span class="k">RUN </span><span class="nb">chmod</span> +x /home/<span class="k">${</span><span class="nv">NB_USER</span><span class="k">}</span>/.jupyter/jupyter_notebook_config.py
<span class="k">RUN </span><span class="nb">chown</span> <span class="nt">-R</span> <span class="nv">$NB_USER</span> /home/<span class="k">${</span><span class="nv">NB_USER</span><span class="k">}</span>/.jupyter
<span class="k">COPY</span><span class="s"> start.sh start-notebook.sh start-singleuser.sh /usr/local/bin/</span>
<span class="k">RUN </span><span class="nb">chmod</span> +x /usr/local/bin/start<span class="k">*</span>.sh

<span class="c"># Set up the build environment</span>
<span class="k">WORKDIR</span><span class="s"> /scratch</span>

<span class="c"># Expose ports and final configuration</span>
<span class="k">ENV</span><span class="s"> JUPYTER_ENABLE_LAB=yes</span>
<span class="k">EXPOSE</span><span class="s"> 8888</span>

<span class="c"># Build MPICH</span>
<span class="k">RUN </span>wget https://www.mpich.org/static/downloads/4.1/mpich-4.1.tar.gz <span class="nt">--no-check-certificate</span>

<span class="c"># Copy and build PETSc</span>
<span class="k">COPY</span><span class="s"> ./build-petsc.sh /scratch/build-petsc.sh</span>
<span class="k">RUN </span><span class="nb">chmod</span> +x /scratch/build-petsc.sh <span class="o">&amp;&amp;</span> /scratch/build-petsc.sh
<span class="k">ENV</span><span class="s"> PATH=/scratch/mpich-4.1/install/bin:$PATH</span>

<span class="c"># Verify PETSc environment</span>
<span class="k">RUN </span><span class="nb">echo</span> <span class="s2">"PETSC version = </span><span class="k">${</span><span class="nv">PETSC_VERSION</span><span class="k">}</span><span class="s2">"</span> <span class="o">&amp;&amp;</span> <span class="se">\
</span>    <span class="nb">echo</span> <span class="s2">"PETSC directory = </span><span class="k">${</span><span class="nv">PETSC_DIR</span><span class="k">}</span><span class="s2">"</span> <span class="o">&amp;&amp;</span> <span class="se">\
</span>    <span class="nb">echo</span> <span class="s2">"PETSC arch = </span><span class="k">${</span><span class="nv">PETSC_ARCH</span><span class="k">}</span><span class="s2">"</span>

<span class="c"># Build PFLOTRAN</span>
<span class="k">RUN </span>git clone https://bitbucket.org/pflotran/pflotran.git /scratch/pflotran <span class="o">&amp;&amp;</span> <span class="se">\
</span>    <span class="nb">cd</span> /scratch/pflotran <span class="o">&amp;&amp;</span> <span class="se">\
</span>    git checkout <span class="k">${</span><span class="nv">pflotran_branch</span><span class="k">}</span> 
<span class="k">RUN </span><span class="nb">echo</span> <span class="s2">"PFLOTRAN branch = </span><span class="k">${</span><span class="nv">pflotran_branch</span><span class="k">}</span><span class="s2">"</span>
<span class="k">WORKDIR</span><span class="s"> /scratch/pflotran/src/pflotran</span>
<span class="k">RUN </span>make clean <span class="o">&amp;&amp;</span> <span class="se">\
</span>    make <span class="nt">-j4</span> <span class="se">\
</span>        <span class="nv">gnu_code_coverage</span><span class="o">=</span>1 <span class="se">\
</span>        <span class="nv">gnu_runtime_checks</span><span class="o">=</span>1 <span class="se">\
</span>        <span class="nv">catch_warnings_as_errors</span><span class="o">=</span>1 <span class="se">\
</span>        pflotran 

<span class="k">WORKDIR</span><span class="s"> /scratch/pflotran/src/pflotran/bin</span>
<span class="k">RUN </span><span class="nb">cp</span> ../pflotran .

<span class="k">RUN </span><span class="nb">chown</span> <span class="nv">$NB_UID</span>:<span class="nv">$NB_GID</span> <span class="nt">--from</span><span class="o">=</span>root:root <span class="nt">-R</span>  /scratch/pflotran/src 

<span class="c"># Set PFLOTRAN environment variables</span>
<span class="k">ENV</span><span class="s"> PFLOTRAN_DIR=/scratch/pflotran \</span>
    PFLOTRAN_EXE=/scratch/pflotran/src/pflotran/pflotran

<span class="c"># Set work directory back to user home</span>
<span class="k">USER</span><span class="s"> $NB_USER</span>
<span class="k">WORKDIR</span><span class="s"> /home/${NB_USER}</span>
<span class="c"># RUN echo "Current user is: $(whoami) in working directory: $(pwd)"</span>
<span class="c"># add pflotran to PATH </span>
<span class="k">ENV</span><span class="s"> PATH=/scratch/pflotran/src/pflotran/bin:$PATH</span>

<span class="c"># append the PATH and additional commands to the bashrc</span>
<span class="k">RUN </span><span class="nb">echo</span> <span class="nv">$PATH</span> <span class="o">&amp;&amp;</span> <span class="se">\
</span>    <span class="nb">echo</span> <span class="s2">"export PATH=</span><span class="k">${</span><span class="nv">PATH</span><span class="k">}</span><span class="s2">"</span> <span class="o">&gt;&gt;</span> ~/.bashrc

<span class="c"># Copy the local .bashrc file into the image</span>
<span class="k">COPY</span><span class="s"> ./local_bashrc /scratch/local_bashrc</span>
<span class="c"># Append the local .bashrc to the user's .bashrc in the image</span>
<span class="k">RUN </span><span class="nb">cat</span> /scratch/local_bashrc <span class="o">&gt;&gt;</span> ~/.bashrc

<span class="c"># Copy the local .vimrc file into the image</span>
<span class="k">COPY</span><span class="s"> ./local_vimrc /scratch/local_vimrc</span>
<span class="c"># Append the local .vimrc to the user's .vimrc in the image</span>
<span class="k">RUN </span><span class="nb">touch</span> ~/.vimrc <span class="o">&amp;&amp;</span> <span class="nb">cat</span> /scratch/local_vimrc <span class="o">&gt;&gt;</span> ~/.vimrc

<span class="c"># Copy the local gitconfig file into the image</span>
<span class="k">COPY</span><span class="s"> ./gitconfig /scratch/gitconfig</span>
<span class="c"># Append the local gitconfig to the user's gitconfig in the image</span>
<span class="k">RUN </span><span class="nb">touch</span> ~/.gitconfig <span class="o">&amp;&amp;</span> <span class="nb">cat</span> /scratch/gitconfig <span class="o">&gt;&gt;</span> ~/.gitconfig

<span class="c"># Final stage: Add metadata and expose ports</span>
<span class="c"># LABEL maintainer="Your Name &lt;your.email@example.com&gt;"</span>
<span class="k">EXPOSE</span><span class="s"> 8888</span>

<span class="c"># create a work directory</span>
<span class="k">WORKDIR</span><span class="s"> /home/${NB_USER}/work</span>

</code></pre></div></div> <h3 id="build-the-docker-image">Build the Docker image</h3> <p>The script below builds the Docker image using dockerfile <code class="language-plaintext highlighter-rouge">dockerfile-jupyter-pflotran</code>.</p> <ul> <li>General Build. The build architecture defaults to the host machine (e.g., <code class="language-plaintext highlighter-rouge">arm64</code>). Note the <code class="language-plaintext highlighter-rouge">.</code> in the end of the command which specifies the build context. For my Mac M1 chip, the build is pretty fast (~30 minutes).</li> </ul> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker build <span class="nt">--progress</span><span class="o">=</span>plain <span class="nt">-f</span> ./dockerfile-jupyter-pflotran <span class="nt">-t</span> pshuai/jupyter-pflotran:v6.0 <span class="nb">.</span>
</code></pre></div></div> <ul> <li>Platform-specific Build. The build architecture is specified as <code class="language-plaintext highlighter-rouge">linux/amd64</code>. Because the build is done on a Mac M1 chip, it took very long time (almost 2 hrs) to complete.</li> </ul> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker build <span class="nt">--platform</span> linux/amd64 <span class="nt">--progress</span><span class="o">=</span>plain <span class="nt">-f</span> ./dockerfile-jupyter-pflotran <span class="nt">-t</span> pshuai/pflotran-jupyter-amd64:v6.0 <span class="nb">.</span>
</code></pre></div></div> <ul> <li>Multiplatform Build. The build architecture is specified as <code class="language-plaintext highlighter-rouge">linux/amd64,linux/arm64</code>. Must include the <code class="language-plaintext highlighter-rouge">--push</code> flag to push the image to Dockerhub. <strong>Docker does not save multi-platform images unless the <code class="language-plaintext highlighter-rouge">--push</code> flag is used</strong>. The build took about 2 hrs on my Mac M1 chip.</li> </ul> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># First, create a new builder instance (e.g., desktop-linux) that enables building for multiple platforms.</span>
docker buildx create <span class="nt">--use</span> desktop-linux

<span class="c"># to check the builder instance</span>
docker buildx <span class="nb">ls</span>

<span class="c"># start build with the --platform args. </span>
<span class="c"># IMPORTANT! add --push to push to Dockerhub, otherwise the multi-platform image will not be saved! </span>
docker buildx build <span class="nt">--platform</span> linux/amd64,linux/arm64 <span class="nt">--progress</span><span class="o">=</span>plain <span class="nt">-f</span> ./dockerfile-jupyter-pflotran <span class="nt">-t</span> pshuai/jupyter-pflotran-multiplatform:latest <span class="nt">-t</span> pshuai/jupyter-pflotran-multiplatform:base_v6 <span class="nt">--push</span> <span class="nb">.</span>

</code></pre></div></div> <p>After the build is complete, you can pull the image and check the architecture on your machine.</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker run <span class="nt">--rm</span> pshuai/jupyter-pflotran-multiplatform:latest <span class="nb">uname</span> <span class="nt">-m</span>

<span class="c">#If you're running on an x86-64 machine, you should see x86_64</span>
x86_64
<span class="c">#If you're running on an ARM machine, you should see </span>
aarch64
</code></pre></div></div> <h3 id="inspect-the-docker-image">Inspect the Docker image</h3> <p>You can inspect the Docker image to see the layers and the size of the image.</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker inspect pshuai/jupyter-pflotran-multiplatform:latest
</code></pre></div></div> <p>You can also just check the labels of the image.</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker inspect <span class="nt">--format</span><span class="o">=</span><span class="s1">''</span> pshuai/jupyter-pflotran-multiplatform:latest
</code></pre></div></div> <h2 id="run-the-image">Run the image</h2> <h3 id="run-pflotran">Run PFLOTRAN</h3> <p>To run PFLOTRAN, use the following command. <code class="language-plaintext highlighter-rouge">$(PFLOTRAN_DIR)</code> is the directory to your PFLOTRAN repository. This will mount the <code class="language-plaintext highlighter-rouge">ufd</code> directory to the container’s <code class="language-plaintext highlighter-rouge">/home/aggie/work</code> directory and run the <code class="language-plaintext highlighter-rouge">ufd_abc.in</code> input file. You will see the screen output from PFLOTRAN if docker runs successfully.</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker run <span class="nt">-it</span> <span class="nt">--rm</span> <span class="nt">-v</span> <span class="nv">$PFLOTRAN_DIR</span>/regression_tests/ufd:/home/aggie/work pshuai/jupyter-pflotran-arm64:v6.0 pflotran <span class="nt">-pflotranin</span> ./ufd_abc.in
</code></pre></div></div> <h2 id="run-jupyterlab">Run JupyterLab</h2> <p>To run JupyterLab, use the following command. <code class="language-plaintext highlighter-rouge">$(pwd)</code> is the current directory in your terminal.</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker run <span class="nt">-it</span> <span class="nt">--rm</span> <span class="nt">-p</span> 8888:8888  <span class="nt">-v</span> <span class="si">$(</span><span class="nb">pwd</span><span class="si">)</span>:/home/aggie/work pshuai/jupyter-pflotran-arm64:v6.0 jupyter lab <span class="nt">--ip</span><span class="o">=</span>0.0.0.0 <span class="nt">--allow-root</span> <span class="nt">--NotebookApp</span>.token<span class="o">=</span><span class="s1">''</span>
</code></pre></div></div> <p>This will print out the following in the terminal:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    Jupyter Server 2.15.0 is running at:
    http://6392a6f60965:8888/lab
    http://127.0.0.1:8888/lab
</code></pre></div></div> <p>Open a browser and copy and paste the following <code class="language-plaintext highlighter-rouge">http://127.0.0.1:8888/lab</code> in the address to access the active jupyterlab session.</p> <h2 id="push-to-dockerhub">Push to Dockerhub</h2> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># check docker images</span>
docker images

<span class="c"># login to dockerhub</span>
<span class="nv">$ </span>docker login <span class="nt">-u</span> pshuai
Password: xxxx

<span class="c"># tag the local image with the remote repo. you can tag the same image multiple times with different tag names.</span>
<span class="nv">$ </span>docker tag pshuai/jupyter-pflotran-arm64:v6.0 pshuai/jupyter-pflotran-arm64:v6.0
<span class="nv">$ </span>docker tag pshuai/jupyter-pflotran-arm64:latest pshuai/jupyter-pflotran-arm64:latest
<span class="c"># push to dockerhub after you created a new repo on Dockerhub; -a pushes all tags</span>
<span class="nv">$ </span>docker push <span class="nt">-a</span> pshuai/jupyter-pflotran-arm64

</code></pre></div></div> <h2 id="update-the-image">Update the image</h2> <p>To update the existing image, you don’t need to rebuild the image from scratch. You can simply update the Dockerfile and run the following command to rebuild the image.</p> <h3 id="update-the-dockerfile">Update the Dockerfile</h3> <p>Use the existing image as your BASE image and create a new Dockerfile named <code class="language-plaintext highlighter-rouge">dockerfile-jupyter-pflotran-updated</code>. For example, you can add new packages.</p> <div class="language-dockerfile highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># This will use the existing multiplatform image as the base image. Choose the platform that you want to use.</span>
<span class="k">FROM</span><span class="w"> </span><span class="s">pshuai/jupyter-pflotran-multiplatform:base_v6</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="s">base</span>

<span class="k">USER</span><span class="s"> root</span>
<span class="c"># Install packages: tree</span>
<span class="k">RUN </span>apt update <span class="nt">-qq</span> <span class="o">&amp;&amp;</span> <span class="se">\
</span>    apt <span class="nb">install</span> <span class="nt">-y</span> <span class="nt">--no-install-recommends</span> <span class="se">\
</span>        tree <span class="o">&amp;&amp;</span> <span class="se">\
</span>    apt clean <span class="o">&amp;&amp;</span> <span class="se">\
</span>    <span class="nb">rm</span> <span class="nt">-rf</span> /var/lib/apt/lists/<span class="k">*</span>

<span class="k">ARG</span><span class="s"> NB_USER=aggie</span>

<span class="k">EXPOSE</span><span class="s"> 8888</span>

<span class="k">USER</span><span class="s"> ${NB_USER}</span>
<span class="c"># cd to work directory</span>
<span class="k">WORKDIR</span><span class="s"> /home/${NB_USER}/work</span>

</code></pre></div></div> <h3 id="build-the-updated-image">Build the updated image</h3> <ul> <li>For general build, use the following command.</li> </ul> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker build <span class="nt">--platform</span> linux/arm64 <span class="nt">--progress</span><span class="o">=</span>plain <span class="nt">-f</span> ./dockerfile-jupyter-pflotran-updated <span class="nt">-t</span> pshuai/jupyter-pflotran-arm64:latest <span class="nb">.</span>
</code></pre></div></div> <ul> <li>For multiplatform build, use the following command.</li> </ul> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker buildx build <span class="nt">--platform</span> linux/amd64,linux/arm64 <span class="nt">--progress</span><span class="o">=</span>plain <span class="nt">-f</span> ./dockerfile-jupyter-pflotran-updated <span class="nt">-t</span> pshuai/jupyter-pflotran-multiplatform:latest <span class="nt">--push</span> <span class="nb">.</span>
</code></pre></div></div> <h2 id="common-issues">Common Issues</h2> <ol> <li>The docker image size is too large. <ul> <li>This may be due to the build cache. You can clean up the cache by running the following command.</li> </ul> </li> </ol> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># this will only install the packages that are necessary for the build</span>
 apt <span class="nb">install</span> <span class="nt">-y</span> <span class="nt">--no-install-recommends</span>

 <span class="c"># remove the cache</span>
 <span class="nb">rm</span> <span class="nt">-Rf</span> petsc-arch/externalpackages
</code></pre></div></div> <ul> <li>The size may increase significantly if you <code class="language-plaintext highlighter-rouge">chown</code> ownership of the files. See the post <a href="https://gabnotes.org/chowning-files-dockerfile-can-take-lot-space/">here</a>.</li> </ul> <h2 id="references">References</h2> <ul> <li><a href="https://docs.docker.com/">Docker Documentation</a></li> <li><a href="https://docs.docker.com/build/building/multi-platform/">Docker Multi-platform builds</a></li> </ul>]]></content><author><name></name></author><category term="tutorial"/><category term="Docker"/><category term="PFLOTRAN"/><summary type="html"><![CDATA[A quick tutorial on how to build a Docker image for running PFLOTRAN and JupyterLab.]]></summary></entry><entry><title type="html">A Quick Intro to Git and GitHub</title><link href="https://hydroaggie.github.io/blog/2023/How-to-Git/" rel="alternate" type="text/html" title="A Quick Intro to Git and GitHub"/><published>2023-11-03T00:00:00+00:00</published><updated>2023-11-03T00:00:00+00:00</updated><id>https://hydroaggie.github.io/blog/2023/How-to-Git</id><content type="html" xml:base="https://hydroaggie.github.io/blog/2023/How-to-Git/"><![CDATA[<p>Redirecting to pdf</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Slides of a quick introduction to Git]]></summary></entry><entry><title type="html">A simple word cloud from Google Scholar</title><link href="https://hydroaggie.github.io/blog/2023/Make-word-cloud/" rel="alternate" type="text/html" title="A simple word cloud from Google Scholar"/><published>2023-10-19T00:00:00+00:00</published><updated>2023-10-19T00:00:00+00:00</updated><id>https://hydroaggie.github.io/blog/2023/Make-word-cloud</id><content type="html" xml:base="https://hydroaggie.github.io/blog/2023/Make-word-cloud/"><![CDATA[<p>I recently discovered this Rshiny page for making a word cloud from any Google Scholar page.</p> <h2 id="steps">Steps</h2> <ol> <li>Go to this <a href="https://shiny.rcg.sfu.ca/u/rdmorin/scholar_googler/">website</a></li> <li>Enter your Google Scholar ID</li> <li>Click <code class="language-plaintext highlighter-rouge">Cloud Me</code></li> <li>A word cloud is generated on the right. You can further tweak the shape and other details using the options on the left.</li> </ol> <h2 id="my-word-cloud">My word cloud</h2> <p>Here is the word cloud from my <a href="https://scholar.google.com/citations?user=Md_6je0AAAAJ">Google Scholar</a> page. Hydrologic, river, exchange are keywords in my research. As a groundwater hydrologist, I am surprised to see that groundwater is not one of the big words. I think the website only grabs words from the paper titles, which may not provide the whole picture of my research.</p> <div class="row mt-3"> <div class="col-sm mt-3 mt-md-0"> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/blog/GoogleScholar_wordcloud-480.webp 480w,/assets/img/blog/GoogleScholar_wordcloud-800.webp 800w,/assets/img/blog/GoogleScholar_wordcloud-1400.webp 1400w," type="image/webp" sizes="95vw"/> <img src="/assets/img/blog/GoogleScholar_wordcloud.png" class="img-fluid rounded z-depth-1" width="100%" height="auto" data-zoomable="" loading="eager" onerror="this.onerror=null; $('.responsive-img-srcset').remove();"/> </picture> </figure> </div> </div> <div class="caption"> My Google Scholar word cloud </div>]]></content><author><name></name></author><category term="tutorial"/><category term="word-cloud"/><summary type="html"><![CDATA[Documentation on how to create a word cloud using your Google Scholar profile]]></summary></entry><entry><title type="html">A Quick Intro to Note-taking using Markdown</title><link href="https://hydroaggie.github.io/blog/2023/Quick-intro-to-Markdown/" rel="alternate" type="text/html" title="A Quick Intro to Note-taking using Markdown"/><published>2023-10-06T00:00:00+00:00</published><updated>2023-10-06T00:00:00+00:00</updated><id>https://hydroaggie.github.io/blog/2023/Quick-intro-to-Markdown</id><content type="html" xml:base="https://hydroaggie.github.io/blog/2023/Quick-intro-to-Markdown/"><![CDATA[<p>Redirecting to another page.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Slides of a quick introduction to note-taking using Markdown and Obsidian]]></summary></entry><entry><title type="html">A Zotero to Obsidian Workflow</title><link href="https://hydroaggie.github.io/blog/2023/A-Zotero-to-Obsidian-Workflow/" rel="alternate" type="text/html" title="A Zotero to Obsidian Workflow"/><published>2023-09-26T00:00:00+00:00</published><updated>2023-09-26T00:00:00+00:00</updated><id>https://hydroaggie.github.io/blog/2023/A-Zotero-to-Obsidian-Workflow</id><content type="html" xml:base="https://hydroaggie.github.io/blog/2023/A-Zotero-to-Obsidian-Workflow/"><![CDATA[<p>I have started using <a href="https://www.zotero.org/">Zotero</a> as my primary literature manager after using Mendeley for many years (the only thing I miss from Mendeley is the search function). I like the flexibility and rich function of Zotero, which offers a wide selection of plugins. I also like to use the highlights and comments as I read papers inside Zotero.</p> <p>This year I started a new note-taking app, <a href="https://obsidian.md/">Obsidian</a>, which I really like. If you don’t know what Obsidian is, check out this nice <a href="https://waterprogramming.wordpress.com/2022/10/21/markdown-based-scientific-and-computational-note-taking-with-obsidian/">article</a> by Water Programming. Obsidian becomes my all-in-one place for my notes including meeting, research, and daily notes. Since I have been making reading notes in Zotero, I started thinking if it is possible to port my literature notes into Obsidian. I did a bit search online, and found many people have already figured out different ways to achieve this. This tutorial combines the contents from <a href="https://forum.obsidian.md/t/zotero-zotfile-mdnotes-obsidian-dataview-workflow/15536">this Obsidian post</a> and <a href="https://medium.com/@alexandraphelan/an-updated-academic-workflow-zotero-obsidian-cffef080addd">this Medium article</a> on the Zotero-Obsidian workflow with some customization.</p> <h2 id="pre-requisites">Pre-requisites:</h2> <ul> <li>Zotero (v6.0+)</li> <li>Obsidian (v1.4+)</li> <li>Obsidian plugins: <a href="https://github.com/mgmeyers/obsidian-zotero-integration">Zotero Integration</a>, Templater, Dataview</li> <li>Zotero plugins: <a href="https://retorque.re/zotero-better-bibtex/installation/">Better BibTeX for Zotero</a>, Zotfile,</li> <li>(Optional) Zotero Browser Extension for Chrome/Firefox. This may be useful for downloading papers to Zotero.</li> </ul> <h2 id="setup">Setup</h2> <h3 id="install-obsidian-plugins">Install Obsidian plugins</h3> <p>For this workflow to work, you will need to install <code class="language-plaintext highlighter-rouge">Zotero Integration, Templater, Dataview</code> plugins.</p> <p>It may be difficult to find where the plugins are for the first time.</p> <ul> <li>Click the settings icon (ie. ) in the lower left corner of the app.</li> <li>Click <code class="language-plaintext highlighter-rouge">Community plugins</code> on the left panel and select <code class="language-plaintext highlighter-rouge">browse</code>. This will open window with a list of plugins.</li> <li>Search for the plugin (e.g., <code class="language-plaintext highlighter-rouge">Zotero Integration</code>), click <code class="language-plaintext highlighter-rouge">install</code></li> <li>Once installed, click <code class="language-plaintext highlighter-rouge">enable</code>. <strong>This step is necessary to activate the plugin</strong></li> </ul> <p>Once you have all the plugins installed, you need to change the settings for each.</p> <h4 id="zotero-integration-settings">Zotero Integration Settings</h4> <p>Change settings in the Zotero Integration plugin.</p> <ul> <li>Go to <code class="language-plaintext highlighter-rouge">Settings --&gt; Community plugins --&gt; Zotero Integration</code></li> <li>Set <code class="language-plaintext highlighter-rouge">Zotero</code> as the Database</li> <li>Set <code class="language-plaintext highlighter-rouge">Note Import Location</code>. This is where the notes will be stored in Obsidian. I use <code class="language-plaintext highlighter-rouge">literature</code> folder in my vault.</li> <li>Under <code class="language-plaintext highlighter-rouge">Import Formats</code>, click <code class="language-plaintext highlighter-rouge">Add Import Format</code> and add <code class="language-plaintext highlighter-rouge">Output Path</code> for notes and <code class="language-plaintext highlighter-rouge">Image Output Path</code>. Choose <code class="language-plaintext highlighter-rouge">Template File</code> as the template file for Zotero notes. I will provide a template below. Choose the <code class="language-plaintext highlighter-rouge">Bibliography Style</code>. I use <code class="language-plaintext highlighter-rouge">APA</code> style.</li> </ul> <h3 id="install-zotero-plugins">Install Zotero plugins</h3> <p>You may need the following plugins: It’s a bit inconvenient to install Zotero plugins.</p> <ul> <li>Download the <code class="language-plaintext highlighter-rouge">.xpi</code> file for each plugin (e.g., Go to xx)</li> <li>Open Zotero, go to <code class="language-plaintext highlighter-rouge">Tools --&gt; Add-ons</code></li> <li>Click settings icon on the upper right, select <code class="language-plaintext highlighter-rouge">Install Add-on from File...</code></li> <li>Locate the downloaded <code class="language-plaintext highlighter-rouge">.xpi</code> file, click <code class="language-plaintext highlighter-rouge">open</code>, and select <code class="language-plaintext highlighter-rouge">install</code></li> </ul> <h4 id="better-bibtex-for-zotero">Better BibTeX for Zotero</h4> <p>This plugin is useful for creating citation keys (e.g., <code class="language-plaintext highlighter-rouge">author_year</code>) for papers.</p> <ul> <li>The citation key is used as note title in Obsidian. To change the citation keys <ul> <li>Go to <code class="language-plaintext highlighter-rouge">Zotero --&gt; Settings --&gt; Advanced --&gt; Advanced Configuration --&gt; Config Editor</code>, search for <code class="language-plaintext highlighter-rouge">better-bibtex.citekeyFormat</code>. Double click to edit the format. The default is <code class="language-plaintext highlighter-rouge">​auth.lower + shorttitle(3,3) + year</code>. I used <code class="language-plaintext highlighter-rouge">auth.capitalize+ year.postfix('\_') + journal</code> (e.g., <code class="language-plaintext highlighter-rouge">Tashie2022_WaterResour.Res.</code>). More formatting options are available <a href="https://retorque.re/zotero-better-bibtex/citing/">here</a></li> </ul> </li> </ul> <h3 id="create-a-template-for-zotero-integration">Create a template for Zotero Integration</h3> <p>To add a template, create a markdown file named <code class="language-plaintext highlighter-rouge">zotero note template.md</code>. You can also put it under a folder (e.g., <code class="language-plaintext highlighter-rouge">templates</code>).</p> <p>I started with the template provided in <a href="https://medium.com/@alexandraphelan/an-updated-academic-workflow-zotero-obsidian-cffef080addd">this</a> post. I like the different callouts used for citation, abstract, and etc. However, I don’t like the look of the annotations and the images are not embeded in the notes.</p> <p>I came across <a href="https://forum.obsidian.md/t/zotero-integration-import-templates/36310">this post</a> in the Obsidian Forum, which color-codes the highlights and provides image embeding in the annotation. There is one little problem with the color style in the CSS snippet. The colors do not match the ones used in Zotero (see <code class="language-plaintext highlighter-rouge">Variables</code> in <a href="https://www.zotero.org/support/note_templates">ref</a>). I have updated the CSS snippet and provided below.</p> <p>In the end, I combined those two templates and came up with a customized one(see code block below) that I really like.</p> <p>Here is the color code for highlights:</p> <table> <thead> <tr> <th style="text-align: left">Color</th> <th style="text-align: center">Meaning</th> </tr> </thead> <tbody> <tr> <td style="text-align: left"><span style="color:yellow;"> yellow</span></td> <td style="text-align: center"><span style="color:yellow;"> Relavent/important. The default color.</span></td> </tr> <tr> <td style="text-align: left"><span style="color:green;"> green </span></td> <td style="text-align: center"><span style="color:green;"> Follow up and read the cited papers. </span></td> </tr> <tr> <td style="text-align: left"><span style="color:red;"> red </span></td> <td style="text-align: center"><span style="color:red;"> Disagree with the author. </span></td> </tr> <tr> <td style="text-align: left"><span style="color:magenta;"> magenta </span></td> <td style="text-align: center"><span style="color:magenta;"> The author critiques previous work or points out knowledge gaps. </span></td> </tr> <tr> <td style="text-align: left"><span style="color:orange;"> orange </span></td> <td style="text-align: center"><span style="color:orange;"> Questions/confusion about the statement </span></td> </tr> </tbody> </table> <p>I will breakdown into different sections:</p> <ul> <li>Cite: Citation of the paper</li> <li>Synthesis: Your personal opinions on this paper.</li> <li>Link: Link to the PDF file on your local PC.</li> <li>Abstract: Abstract of the article.</li> <li>Annotations: All highlights, notes, comments (including box comments), links grouped by color.</li> <li>Metadata: all metadata associated with the paper which are useful for data query using DataView.</li> </ul> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
---
cssclasses:
  - literature-note
category: literaturenote
title: {{title}}
tags:{% for t in tags %}
  - {{t.tag | replace(" ", "-")}}{% endfor %}
citekey: {{citekey}}
status: unread
dateread:
---

&gt; [!Cite]
&gt; {{bibliography}}

{% persist "notes" %}{% if isFirstImport %}
&gt;[!Synthesis]
&gt;**Contribution**:: 
&gt;
&gt;**Related**:: {% for relation in relations | selectattr("citekey") %} [[@{{relation.citekey}}]]{% if not loop.last %}, {% endif%} {% endfor %}
&gt;
{% endif %}{% endpersist %}

&gt; [!Link] 
&gt; {%- for attachment in attachments | filterby("path", "endswith", ".pdf") %}
&gt;  [{{attachment.title}}](file://{{attachment.path | replace(" ", "%20")}})  {%- endfor -%}.

&gt; [!Abstract]-
&gt; {%- if abstractNote %}
&gt; {{abstractNote}}
&gt; {%- endif -%}.


## Annotations

{%- macro colorValueToName(color) -%}
	{%- switch color -%}
		{%- case "#ffd400" -%}
			Relevant / important
		{%- case "#ff6666" -%}
			Disagree
		{%- case "#e56eee" -%}
			Critiques
		{%- case "#a28ae5" -%}
			Questions / confusion
		{%- case "#5fb236" -%}
			TODO / follow up
		{%- default -%}
			Note
	{%- endswitch -%}
{%- endmacro -%}

{%- macro calloutHeader(type) -%}
	{%- switch type -%}
		{%- case "highlight" -%}
			Highlight
		{%- case "strike" -%}
			Strikethrough
		{%- case "underline" -%}
			Underline
		{%- case "image" -%}
			Image
		{%- default -%}
			Note
	{%- endswitch -%}
{%- endmacro %}

{% persist "annotations" %}
{% set annots = annotations | filterby("date", "dateafter", lastImportDate) -%}
{% if annots.length &gt; 0 %}
### Imported on {{importDate | format("YYYY-MM-DD h:mm a")}}

{% for color, annots in annots | groupby("color") -%}
#### {{colorValueToName(color)}}

{% for annot in annots -%}
&gt; [!quote{% if annot.color %}|{{annot.color}}{% endif %}] {{calloutHeader(annot.type)}}
{%- if annot.annotatedText %}
&gt; {{annot.annotatedText | nl2br}}
{%- endif -%}
{%- if annot.imageRelativePath %}
&gt; ![[{{annot.imageRelativePath}}]]
{%- endif %}
{%- if annot.ocrText %}
&gt; {{annot.ocrText}}
{%- endif %}
{%- if annot.comment %}
&gt;
&gt;&gt; {{annot.comment | nl2br}}
{%- endif %}
&gt;
&gt; [Page {{annot.page}}](zotero://open-pdf/library/items/{{annot.attachment.itemKey}}?page={{annot.page}}) [{{annot.date | format("YYYY-MM-DD#h:mm a")}}]

{% endfor -%}
{% endfor -%}
{% endif %}
{% endpersist %}

&gt;[!metadata]-
{% for type, creators in creators | groupby("creatorType") -%}
{%- for creator in creators -%}
&gt; **{{"First" if loop.first}}{{type | capitalize}}**::
{%- if creator.name %} {{creator.name}}  
{%- else %} {{creator.lastName}}, {{creator.firstName}}  
{%- endif %}  
{% endfor %}~ 
{%- endfor %}    
&gt; **Title**:: {{title}}  
&gt; **Year**:: {{date | format("YYYY")}}   
&gt; **Citekey**:: {{citekey}} {%- if itemType %}  
&gt; **itemType**:: {{itemType}}{%- endif %}{%- if itemType == "journalArticle" %}  
&gt; **Journal**:: *{{publicationTitle}}* {%- endif %}{%- if volume %}  
&gt; **Volume**:: {{volume}} {%- endif %}{%- if issue %}  
&gt; **Issue**:: {{issue}} {%- endif %}{%- if itemType == "bookSection" %}  
&gt; **Book**:: {{publicationTitle}} {%- endif %}{%- if publisher %}  
&gt; **Publisher**:: {{publisher}} {%- endif %}{%- if place %}  
&gt; **Location**:: {{place}} {%- endif %}{%- if pages %}   
&gt; **Pages**:: {{pages}} {%- endif %}{%- if DOI %}  
&gt; **DOI**:: {{DOI}} {%- endif %}{%- if ISBN %}  
&gt; **ISBN**:: {{ISBN}} {%- endif %}    


</code></pre></div></div> <h3 id="add-css-snippet">Add CSS snippet</h3> <p>To add the CSS snippet, go to …</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># go to the root directory of your vault (i.e., where notes are stored)</span>
<span class="nb">cd </span>PATH/TO/VAULT/.obsidian/snippets
<span class="c"># create a css file, you can also use text editor to create a file. Make sure the file has .css as extention</span>
vi callouts.css
</code></pre></div></div> <p>Inside the <code class="language-plaintext highlighter-rouge">callouts.css</code> file, paste the updated CSS snippet as follows:</p> <div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">/* Yellow */</span>
<span class="nc">.literature-note</span> <span class="nc">.callout</span><span class="o">[</span><span class="nt">data-callout-metadata</span><span class="o">=</span><span class="s1">"#ffd400"</span><span class="o">]</span> <span class="p">{</span>
  <span class="py">--callout-color</span><span class="p">:</span> <span class="m">255</span><span class="p">,</span> <span class="m">204</span><span class="p">,</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>

<span class="c">/* Red */</span>
<span class="nc">.literature-note</span> <span class="nc">.callout</span><span class="o">[</span><span class="nt">data-callout-metadata</span><span class="o">=</span><span class="s1">"#ff6666"</span><span class="o">]</span> <span class="p">{</span>
  <span class="py">--callout-color</span><span class="p">:</span> <span class="m">255</span><span class="p">,</span> <span class="m">59</span><span class="p">,</span> <span class="m">48</span><span class="p">;</span>
<span class="p">}</span>

<span class="c">/* Orange */</span>
<span class="nc">.literature-note</span> <span class="nc">.callout</span><span class="o">[</span><span class="nt">data-callout-metadata</span><span class="o">=</span><span class="s1">"#f19837"</span><span class="o">]</span> <span class="p">{</span>
  <span class="py">--callout-color</span><span class="p">:</span> <span class="m">255</span><span class="p">,</span> <span class="m">149</span><span class="p">,</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>

<span class="c">/* Green */</span>
<span class="nc">.literature-note</span> <span class="nc">.callout</span><span class="o">[</span><span class="nt">data-callout-metadata</span><span class="o">=</span><span class="s1">"#5fb236"</span><span class="o">]</span> <span class="p">{</span>
  <span class="py">--callout-color</span><span class="p">:</span> <span class="m">40</span><span class="p">,</span> <span class="m">205</span><span class="p">,</span> <span class="m">65</span><span class="p">;</span>
<span class="p">}</span>

<span class="c">/* Blue */</span>
<span class="nc">.literature-note</span> <span class="nc">.callout</span><span class="o">[</span><span class="nt">data-callout-metadata</span><span class="o">=</span><span class="s1">"#2ea8e5"</span><span class="o">]</span> <span class="p">{</span>
  <span class="py">--callout-color</span><span class="p">:</span> <span class="m">0</span><span class="p">,</span> <span class="m">122</span><span class="p">,</span> <span class="m">255</span><span class="p">;</span>
<span class="p">}</span>

<span class="c">/* Purple */</span>
<span class="nc">.literature-note</span> <span class="nc">.callout</span><span class="o">[</span><span class="nt">data-callout-metadata</span><span class="o">=</span><span class="s1">"#a28ae5"</span><span class="o">]</span> <span class="p">{</span>
  <span class="py">--callout-color</span><span class="p">:</span> <span class="m">125</span><span class="p">,</span> <span class="m">84</span><span class="p">,</span> <span class="m">222</span><span class="p">;</span>
<span class="p">}</span>

<span class="c">/* Magenta */</span>
<span class="nc">.literature-note</span> <span class="nc">.callout</span><span class="o">[</span><span class="nt">data-callout-metadata</span><span class="o">=</span><span class="s1">"#e56eee"</span><span class="o">]</span> <span class="p">{</span>
  <span class="py">--callout-color</span><span class="p">:</span> <span class="m">255</span><span class="p">,</span> <span class="m">0</span><span class="p">,</span> <span class="m">255</span><span class="p">;</span>
<span class="p">}</span>

<span class="c">/* Gray */</span>
<span class="nc">.literature-note</span> <span class="nc">.callout</span><span class="o">[</span><span class="nt">data-callout-metadata</span><span class="o">=</span><span class="s1">"#aaaaaa"</span><span class="o">]</span> <span class="p">{</span>
  <span class="py">--callout-color</span><span class="p">:</span> <span class="m">50</span><span class="p">,</span> <span class="m">50</span><span class="p">,</span> <span class="m">50</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div> <p>To enable the CSS snippet</p> <ul> <li>Go to <code class="language-plaintext highlighter-rouge">Settings --&gt; Appearance --&gt; CSS snippets</code></li> <li>Enable the newly installed snippet (i.e., <code class="language-plaintext highlighter-rouge">callouts</code>)</li> </ul> <p>This should automatically color your callouts in the notes.</p> <h2 id="workflow">Workflow</h2> <h3 id="highlight-and-comment">Highlight and comment</h3> <p>Highlight and comment on the paper as you read. Use the color code for different highlight colors. Use box comment for images (this will save images as snapshots in Obsidian).</p> <h3 id="import-the-note-into-obsidian">Import the note into Obsidian</h3> <p>Open command pallett and search for <code class="language-plaintext highlighter-rouge">Zotero: Create Literature Note</code>.Alternative, create a hotkey for that command (e.g., <code class="language-plaintext highlighter-rouge">ctrl + opt + Z</code>).</p> <p>In the pop-up box, type in the author to search for literature. Once found, hit <code class="language-plaintext highlighter-rouge">enter</code>. It will automatically generate a markdown note using the zotero template.</p> <p>Here is a screenshot shows the final markdown file in Obsidian.</p> <div class="row"> <div class="col-sm mt-3 mt-md-0"> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/blog/obsidian_note-480.webp 480w,/assets/img/blog/obsidian_note-800.webp 800w,/assets/img/blog/obsidian_note-1400.webp 1400w," type="image/webp" sizes="95vw"/> <img src="/assets/img/blog/obsidian_note.png" class="img-fluid rounded z-depth-1" width="100%" height="auto" data-zoomable="" loading="eager" onerror="this.onerror=null; $('.responsive-img-srcset').remove();"/> </picture> </figure> </div> </div> <ul> <li>The nice thing about the annotations is that each annotation has a link to the page number in the paper. When clicking on the link, it will bring you back to highlighted page of the PDF in Zotero.</li> <li> <p>All snapshots are embeded under annotations, which make it extremely useful for storing key figures.</p> </li> <li>Add additional notes. You may add additional notes under <code class="language-plaintext highlighter-rouge">Synthesis</code> which may include the main contribution of the paper, the impression of the paper and other notes. <strong>Any edits added outside of <code class="language-plaintext highlighter-rouge">persist</code> blocks (i.e., outside of Synthesis and Annotations) will be overridden when the same note is imported again.</strong></li> </ul> <h3 id="create-table-using-dataview">Create table using Dataview</h3> <p>Once you have a collection of notes, you can create a DataView query which lists all papers and their key information in a table. This may be helpful for writting literature review.</p> <h1 id="advanced-tips">Advanced Tips</h1> <ul> <li>If the title of the paper contains colon (<code class="language-plaintext highlighter-rouge">:</code>), it will mess up the header formatting in the obsidian notes. The workaround is to replace it with something like <code class="language-plaintext highlighter-rouge">-</code>.</li> <li>If you want to add more information in the template and are wondering which keywords to use, you can use <code class="language-plaintext highlighter-rouge">Zotero Data Explorer</code> to inspect all available keywords. In Obsidian, open command palallet and search for <code class="language-plaintext highlighter-rouge">Zotero Data Explorer</code>. Once opened, choose <code class="language-plaintext highlighter-rouge">Prompt For Selection</code> and the associated paper, you will see all meta information.</li> <li>The annotations do not have internal links. However, you can add internal links in comments. Simply added comments after the highlights and keywords with internal links (e.g., <code class="language-plaintext highlighter-rouge">[[keyword]]</code>)</li> <li>Obsidian does not auto-sync the literature notes. If new annotations are made in Zotero, the user has to manually pull updated by importing the same literature note again (refer to this <a href="https://forums.zotero.org/discussion/comment/399431/#Comment_399431">discussion</a>).</li> <li>The <code class="language-plaintext highlighter-rouge">persist</code> tag prevents content from being overwritten. Any notes made in between the <code class="language-plaintext highlighter-rouge">persist</code> tag will be preserved. In the example below, the notes made in the <code class="language-plaintext highlighter-rouge">notes</code> section will be preserved. Thus, additional new notes can be added in the <code class="language-plaintext highlighter-rouge">notes</code> section without being overwritten.</li> </ul> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
{% persist "notes" %}
{% endpersist %}

</code></pre></div></div> <h1 id="references">References</h1> <ul> <li>https://forum.obsidian.md/t/zotero-integration-import-templates/36310</li> <li>https://forum.obsidian.md/t/zotero-zotfile-mdnotes-obsidian-dataview-workflow/15536</li> <li>https://medium.com/@alexandraphelan/an-updated-academic-workflow-zotero-obsidian-cffef080addd</li> </ul>]]></content><author><name></name></author><category term="tutorial"/><category term="Zotero"/><category term="Obsidian"/><category term="Workflow"/><category term="note-taking"/><summary type="html"><![CDATA[A workflow on how to export notes from Zotero to Obsidian]]></summary></entry></feed>