<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.5">Jekyll</generator><link href="https://jackyko1991.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://jackyko1991.github.io/" rel="alternate" type="text/html" /><updated>2024-04-16T16:41:56+00:00</updated><id>https://jackyko1991.github.io/feed.xml</id><title type="html">jackyko1991.github.io</title><subtitle>Biomedical Image Computation 101</subtitle><author><name>Jacky Ka Long Ko</name></author><entry><title type="html">C++ Interface of The Vascular Modeling Toolkit (VMTK)</title><link href="https://jackyko1991.github.io/journal/VMTK-cpp.html" rel="alternate" type="text/html" title="C++ Interface of The Vascular Modeling Toolkit (VMTK)" /><published>2020-12-17T00:00:00+00:00</published><updated>2020-12-17T00:00:00+00:00</updated><id>https://jackyko1991.github.io/journal/VMTK-cpp</id><content type="html" xml:base="https://jackyko1991.github.io/journal/VMTK-cpp.html"><![CDATA[<p><strong>The Vascular Modeling Toolkit (VMTK)</strong> is library collection for 3D reconstruction, geometric analysis, mesh generation and surface data analysis for image-based modeling of blood vessels. The toolkit is developed by Orobix srl whicch can run standalone with VMTK scripts, Python or C++ library, or as an extension to the medical image processing platform 3D Slicer.</p>

<p>The standalone and Python (Pype) method is described in detail in the <a href="http://www.vmtk.org/tutorials/">tutorial section of VMTK official site</a>. Here we provide the instruction for C++ users to integrate VMTK with CMake medical image processing toolchain.</p>

<h2 id="compile-c-interface-from-source">Compile C++ Interface from Source</h2>
<p>For developers interested to develop vascular modeling toolkit with CMake medical image processing toolchain, you should first get familiar with <a href="./2020-12-16-CMake-Medical-Image-Toolchain.md">CMake and the Qt-VTK-ITK build</a> procedures.</p>

<h3 id="cmake-configuration">CMake Configuration</h3>
<p>VMTK provide SuperBuild options for standalone build. Here we would prefer to use our own VTK-ITK toolchain for greater control on dependencies.</p>

<h4 id="itk-configuration">ITK Configuration</h4>
<p>Make sure ITK is built with <code class="language-plaintext highlighter-rouge">Module_ITKVtkGlue:BOOL=ON</code> to have ITK-VTK bind. Following options are necessary for VMTK dependency or else built error will appear:</p>

<div class="language-cmake highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Module_ITKReview:BOOL=ON
ITK_USE_SYSTEM_DOUBLECONVERSION=ON
</code></pre></div></div>

<h4 id="vmtk-configuration">VMTK Configuration</h4>

<div class="language-cmake highlighter-rouge"><div class="highlight"><pre class="highlight"><code>BUILD_DOCUMENTATION:BOOL=OFF
BUILD_SHARED_LIBS:BOOL=ON
VTK_VMTK_WRAP_PYTHON:BOOL=OFF

<span class="c1"># Use system VTK and ITK</span>
VMTK_USE_SUPERBUILD:BOOL=OFF
USE_SYSTEM_VTK:BOOL=ON
USE_SYSTEM_ITK:BOOL=ON
</code></pre></div></div>

<h2 id="vmtk-in-c-and-python">VMTK in C++ and Python</h2>
<p>You should first get yourself familiar with VTK coding in C++. VMTK works very similar to VTK smartpointer syntax (<a href="http://www.vtk.org/Wiki/VTK/Examples/Cxx">VTK C++ Example</a>). Once you understand the working principle of VTK, you will get used to VMTK.</p>

<h3 id="vmtkscripts">vmtkScripts</h3>
<p>VMTK work as standalone software with PypeS script. The VMTK PypeS script are available on the <a href="https://github.com/vmtk/vmtk/tree/master/vmtkScripts">Github repo</a> and you may checkout the basic tutorial <a href="http://www.vmtk.org/tutorials/PypesBasic.html">here</a>.</p>

<h3 id="change-from-python-to-c">Change from Python to C++</h3>
<p>As a basic illustration on converting vmtkScripts to C++ development, we use the example of centerline extraction filter (https://github.com/vmtk/vmtk/blob/master/vmtkScripts/vmtkcenterlines.py).</p>

<p>What we most concern is the <code class="language-plaintext highlighter-rouge">Execute</code> function, where PypeS actually call VMTK functions. PypeS glue VTK and VMTK functions in Python. The function name of VTK and VMTK are the same in both Python and C++ interface. To calculate polydata centerline, the class <code class="language-plaintext highlighter-rouge">vtkvmtkPolyDataCenterlines</code> is the core part to do the work. The class documentation (http://www.vmtk.org/doc/html/classvtkvmtkPolyDataCenterlines.html) does not provide detail description of like VTK. Therefore we need to refer the class functions from python examples.</p>

<p>Follow illustrate the class in both languages:</p>

<h4 id="python">Python</h4>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">vmtk</span> <span class="kn">import</span> <span class="n">vtkvmtk</span>

<span class="n">centerlineFilter</span> <span class="o">=</span> <span class="n">vtkvmtk</span><span class="p">.</span><span class="n">vtkvmtkPolyDataCenterlines</span><span class="p">()</span>
<span class="n">centerlineFilter</span><span class="p">.</span><span class="n">SetInputData</span><span class="p">(</span><span class="n">centerlineInputSurface</span><span class="p">)</span>
<span class="n">centerlineFilter</span><span class="p">.</span><span class="n">SetSourceSeedIds</span><span class="p">(</span><span class="n">inletSeedIds</span><span class="p">)</span>
<span class="n">centerlineFilter</span><span class="p">.</span><span class="n">SetTargetSeedIds</span><span class="p">(</span><span class="n">outletSeedIds</span><span class="p">)</span>
<span class="n">centerlineFilter</span><span class="p">.</span><span class="n">SetRadiusArrayName</span><span class="p">(</span><span class="s">"Radius"</span><span class="p">)</span>
<span class="n">centerlineFilter</span><span class="p">.</span><span class="n">SetEdgeArrayName</span><span class="p">(</span><span class="s">"Edge"</span><span class="p">)</span>
<span class="n">centerlineFilter</span><span class="p">.</span><span class="n">SetEdgePCoordArrayName</span><span class="p">(</span><span class="s">"PCoord"</span><span class="p">)</span>
<span class="n">centerlineFilter</span><span class="p">.</span><span class="n">SetAppendEndPointsToCenterlines</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span>
<span class="n">centerlineFilter</span><span class="p">.</span><span class="n">SetCenterlineResampling</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span>
<span class="n">centerlineFilter</span><span class="p">.</span><span class="n">SetResamplingStepLength</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="n">centerlineFilter</span><span class="p">.</span><span class="n">Update</span><span class="p">()</span>
</code></pre></div></div>

<h4 id="c">C++</h4>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;vtkvmtkPolyDataCenterlines.h&gt;</span><span class="cp">
</span>
<span class="n">vtkSmartPointer</span><span class="o">&lt;</span><span class="n">vtkvmtkPolyDataCenterlines</span><span class="o">&gt;</span> <span class="n">centerlineFilter</span> <span class="o">=</span> <span class="n">vtkSmartPointer</span><span class="o">&lt;</span><span class="n">vtkvmtkPolyDataCenterlines</span><span class="o">&gt;::</span><span class="n">New</span><span class="p">();</span>
<span class="n">centerlineFilter</span><span class="o">-&gt;</span><span class="n">SetInputData</span><span class="p">(</span><span class="n">centerlineInputSurface</span><span class="p">);</span>
<span class="n">centerlineFilter</span><span class="o">-&gt;</span><span class="n">SetSourceSeedIds</span><span class="p">(</span><span class="n">inletSeedIds</span><span class="p">);</span>
<span class="n">centerlineFilter</span><span class="o">-&gt;</span><span class="n">SetTargetSeedIds</span><span class="p">(</span><span class="n">outletSeedIds</span><span class="p">);</span>
<span class="n">centerlineFilter</span><span class="o">-&gt;</span><span class="n">SetAppendEndPointsToCenterlines</span><span class="p">(</span><span class="nb">true</span><span class="p">);</span>
<span class="n">centerlineFilter</span><span class="o">-&gt;</span><span class="n">SetCenterlineResampling</span><span class="p">(</span><span class="nb">true</span><span class="p">);</span>
<span class="n">centerlineFilter</span><span class="o">-&gt;</span><span class="n">SetResamplingStepLength</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="n">centerlineFilter</span><span class="o">-&gt;</span><span class="n">SetRadiusArrayName</span><span class="p">(</span><span class="s">"Radius"</span><span class="p">);</span>
<span class="n">centerlineFilter</span><span class="o">-&gt;</span><span class="n">SetEdgeArrayName</span><span class="p">(</span><span class="s">"Edge"</span><span class="p">);</span>
<span class="n">centerlineFilter</span><span class="o">-&gt;</span><span class="n">SetEdgePCoordArrayName</span><span class="p">(</span><span class="s">"PCoord"</span><span class="p">);</span>
<span class="n">centerlineFilter</span><span class="o">-&gt;</span><span class="n">Update</span><span class="p">();</span>
</code></pre></div></div>

<p>The full VMTK class list can be checked <a href="http://www.vmtk.org/doc/html/annotated.html">here</a>.</p>

<h2 id="associate-software">Associate Software</h2>
<h3 id="vmtk-slicer-module"><a href="https://www.slicer.org/wiki/Slicer4:VMTK">VMTK Slicer Module</a></h3>
<p>VMTK is available through the extension manager for 3D Slicer from version 4.6.2. Main difference to the Slicer3 version is that now all VMTK modules come as one extension bundle.</p>

<p><a href="https://www.youtube.com/watch?v=caEuwJ7pCWs"><img src="https://img.youtube.com/vi/caEuwJ7pCWs/0.jpg" alt="VMTK Slicer Module" /></a></p>

<h3 id="vmtklab"><a href="http://vmtklab.orobix.com/">VMTKLab</a></h3>
<p>VMTKLab is a workflow oriented application for image-based modeling and computational hemodynamics on the cloud powered by Rescale.</p>

<p><img src="../assets/img/2020-12-17-VMTK/vmtklab.png" alt="alt text" title="VMTKLab" /></p>

<h3 id="vessel-centerline-extraction"><a href="https://github.com/jackyko1991/Vessel-Centerline-Extraction">Vessel Centerline Extraction</a></h3>
<p>An interactive CLI software to extract vessel centerline.</p>

<p><img src="https://github.com/jackyko1991/Vessel-Centerline-Extraction/raw/master/doc/img/result_large.jpg" alt="alt text" title="Vessel Centerline Extraction" /></p>

<h3 id="vessel-clipper"><a href="https://github.com/jackyko1991/Vessel-Clipper">Vessel Clipper</a></h3>
<p>Clip vessel surface with user input centerlines. This software is a GUI version of the Vessel Centerline Extraction. Extra functions like surface clipping, domain defining are also included for CFD and morphological analysis purposes.</p>

<p>An interactive CLI software to extract vessel centerline.
<img src="https://github.com/jackyko1991/Vessel-Clipper/raw/main/Doc/img/screencap.png" alt="alt text" title="Vessel Clipper" /></p>

<h2 id="references">References</h2>
<ul>
  <li><a href="http://www.vmtk.org/">VMTK official site</a></li>
  <li><a href="https://github.com/vmtk/vmtk">VMTK Github</a></li>
  <li><a href="http://www.vmtk.org/doc/html/annotated.html">VMTK class references</a></li>
</ul>]]></content><author><name>Jacky Ko</name></author><category term="journal" /><category term="documentation" /><category term="cmake" /><category term="vmtk" /><summary type="html"><![CDATA[The Vascular Modeling Toolkit (VMTK) is library collection for 3D reconstruction, geometric analysis, mesh generation and surface data analysis for image-based modeling of blood vessels. The toolkit is developed by Orobix srl whicch can run standalone with VMTK scripts, Python or C++ library, or as an extension to the medical image processing platform 3D Slicer.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://jackyko1991.github.io/2020-12-17-VMTK/home_centerlines.png" /><media:content medium="image" url="https://jackyko1991.github.io/2020-12-17-VMTK/home_centerlines.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">CMake Medical Image Toolchain (Qt, VTK, ITK, OpenCV)</title><link href="https://jackyko1991.github.io/journal/CMake-Medical-Image-Toolchain.html" rel="alternate" type="text/html" title="CMake Medical Image Toolchain (Qt, VTK, ITK, OpenCV)" /><published>2020-12-16T00:00:00+00:00</published><updated>2020-12-16T00:00:00+00:00</updated><id>https://jackyko1991.github.io/journal/CMake-Medical-Image-Toolchain</id><content type="html" xml:base="https://jackyko1991.github.io/journal/CMake-Medical-Image-Toolchain.html"><![CDATA[<p>To develop desktop medical image software, several essential C++ libraries are recommended for GUI design, graphical rendering and image processing. Here we will provide a detailed instruction on the configuration and compilation of the toolchain.</p>

<p>The toolchain we recommended is cross platform applicable (Windows, MacOS, Linux). The procedure works almost the same on different OS. Also the suggested library packages also provide Python interface for users who are not familiar with C++ coding.</p>

<h2 id="dependencies">Dependencies</h2>
<p><strong>Beware of software version and build sequence. Wrong version may cause compilation error.</strong></p>

<ul>
  <li><a href="https://cmake.org/">CMake</a></li>
  <li><a href="https://www.qt.io/">Qt 5.10.1</a></li>
  <li><a href="https://vtk.org/">VTK 8.2.0</a></li>
  <li><a href="https://opencv.org/">OpenCV 3.4</a></li>
  <li><a href="https://itk.org/">ITK 4.13.3</a></li>
</ul>

<p>If trying to build with <code class="language-plaintext highlighter-rouge">Qt-5.12</code> and <code class="language-plaintext highlighter-rouge">Microsoft Visual Studio 2019</code>, then build will fail with the error <code class="language-plaintext highlighter-rouge">error LNK2019: unresolved external symbol "__declspec(dllimport) public: __cdecl QLinkedListData::QLinkedListData(void)"</code>. The solution is to either change the toolset version to an earlier one (e.g., Visual Studio 2015) or upgrade Qt (e.g., use Qt-5.15 with Visual Studio 2019).</p>

<p>It is known that newer version of ITK and VTK is not compatible with VMTK 1.4.</p>

<p>Since the libraries relies on one another, sequence of build is also essential to bind the toolchain. Recommended flow is <code class="language-plaintext highlighter-rouge">Qt</code>-&gt;<code class="language-plaintext highlighter-rouge">VTK</code>-&gt;<code class="language-plaintext highlighter-rouge">OpenCV</code>-&gt;<code class="language-plaintext highlighter-rouge">DCMTK(optnional)</code>-&gt;<code class="language-plaintext highlighter-rouge">ITK</code>-&gt;<code class="language-plaintext highlighter-rouge">others</code></p>

<h3 id="associate-python-versions">Associate Python Versions</h3>
<p>For users who would like to develop with Python interface, <a href="https://www.anaconda.com/">Anaconda</a> would include most of the dependent libraries like pyqt and vtk. You may install other necessary packages like OpenCV or ITK via pip or conda.</p>

<table>
  <thead>
    <tr>
      <th> </th>
      <th>C++</th>
      <th>Python</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>GUI</td>
      <td>Qt</td>
      <td>pyqt</td>
    </tr>
    <tr>
      <td>Graphical Rendering</td>
      <td>VTK</td>
      <td>vtk</td>
    </tr>
    <tr>
      <td>Image Processing (2D/3D/N-D)</td>
      <td>ITK</td>
      <td>SimpleITK</td>
    </tr>
    <tr>
      <td>Image Processing (2D)</td>
      <td>OpenCV</td>
      <td>OpenCV</td>
    </tr>
  </tbody>
</table>

<p>Note that SimpleITK is a lite version of ITK that provides convenient manipulation methods for Python users. ITK also provide Python interface yet is not a popular choice for its relative complex syntax.</p>

<h2 id="install-process">Install Process</h2>
<p>Here we will demonstrate the install procedures for MSVC 2015. For Unix you may follow the CMake terminal build guild.</p>

<p>We recommend to build the toolchain with following folder hierarchy:</p>

<ul>
  <li>Style 1:
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  .
  ├── source
  │   ├── qt-installer.exe
  │   ├── vtk
  │   ├── itk
  │   └── ...
  ├── build
  │   ├── qt
  │   ├── vtk
  │   ├── itk
  │   └── ...
</code></pre></div>    </div>
  </li>
  <li>Style 2:
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  .
  ├── qt
  ├── vtk
  │   ├── build
  │   ├── &lt;source-code&gt;
  │   └── ...
  ├── itk
  │   ├── build
  │   ├── &lt;source-code&gt;
  │   └── ...
  ├── ...
</code></pre></div>    </div>
  </li>
</ul>

<h3 id="qt">Qt</h3>
<ol>
  <li>Download <a href="https://www.qt.io/download-open-source">Open Source Qt installer</a> from official site</li>
  <li>Follow the install instruction with the correct compiler version.</li>
</ol>

<p><strong>Note</strong>: Qt does not provide 64bit MinGW pre-compiled version.</p>

<h3 id="vtk">VTK</h3>

<ol>
  <li>Clone the source code
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> git clone <span class="nt">-b</span> v8.2.0  https://github.com/Kitware/VTK.git
</code></pre></div>    </div>
  </li>
  <li>
    <p>Open CMake and choose the source code directory and binary build directory. Here we choose <code class="language-plaintext highlighter-rouge">Style 1</code> folder structure.</p>

    <p><img src="../assets/img/2020-12-16-CMake-Medical-Image-Toolchain/cmake-cap-screen.png" alt="alt text" title="CMake source and binary" /></p>
  </li>
  <li>
    <p>Press <code class="language-plaintext highlighter-rouge">Configure</code> and choose <code class="language-plaintext highlighter-rouge">Visual Studio 14 2015 Win64</code> for 64bit build. Wait until first time configuration complete. This step may take around 10 min.</p>

    <p><img src="../assets/img/2020-12-16-CMake-Medical-Image-Toolchain/cmake-msvc.png" alt="alt text" title="MSVC generator" /></p>
  </li>
  <li>Change the following build options. Then press <code class="language-plaintext highlighter-rouge">Configure</code> again to take effective. Some options like <code class="language-plaintext highlighter-rouge">Qt5_DIR</code> and <code class="language-plaintext highlighter-rouge">VTK_QT_VERSION</code> will only appear after <code class="language-plaintext highlighter-rouge">VTK_Group_Qt</code> is checked and configured. You may need to configure several times before all the necessary values are set.
    <div class="language-cmake highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="c1"># speed up the build</span>
 BUILD_DOCUMENTATION:BOOL=OFF 
 BUILD_EXAMPLES:BOOL=OFF
 BUILD_TESTING:BOOL=OFF 
 <span class="c1"># must check shared library build to export for future use</span>
 BUILD_SHARED_LIBS:BOOL=ON
 <span class="c1"># OpenGL stuff</span>
 Module_vtkImagingOpenGL2:BOOL=ON
 Module_vtkIOExportOpenGL2:BOOL=ON
 Module_vtkRenderingLICOpenGL2:BOOL=ON
 <span class="c1">#</span>
 VTK_QT_VERSION:STRING=5
 VTK_Group_Qt:BOOL=ON
 Module_vtkGUISupportQt:BOOL=ON
 Module_vtkGUISupportQtOpenGL:BOOL=ON
 Module_vtkGUISupportQtSQL:BOOL=ON
 Module_vtkGUISupportQtWebkit:BOOL=OFF
 Qt5_DIR:PATH=<span class="si">${</span><span class="nv">Qt5_DIR</span><span class="si">}</span>
 Qt5Core_DIR:PATH=<span class="si">${</span><span class="nv">Qt5_DIR</span><span class="si">}</span>/Core
 Qt5Gui_DIR:PATH=<span class="si">${</span><span class="nv">Qt5_DIR</span><span class="si">}</span>/Gui
 Qt5OpenGL_DIR:PATH=<span class="si">${</span><span class="nv">Qt5_DIR</span><span class="si">}</span>/OpenGL
 Qt5Sql_DIR:PATH=<span class="si">${</span><span class="nv">Qt5_DIR</span><span class="si">}</span>/Sql
 Qt5UiPlugin_DIR:PATH=<span class="si">${</span><span class="nv">Qt5_DIR</span><span class="si">}</span>/UiPlugin
 Qt5Widgets_DIR:PATH=<span class="si">${</span><span class="nv">Qt5_DIR</span><span class="si">}</span>/Widgets
</code></pre></div>    </div>

    <p><img src="../assets/img/2020-12-16-CMake-Medical-Image-Toolchain/cmake-vtk-qt.png" alt="alt text" title="CMake VTK Qt" /></p>

    <p>Error box will popup after choosing <code class="language-plaintext highlighter-rouge">VTK_Group_Qt</code>. You need to provide the correct path to make the configuration success.</p>

    <p><code class="language-plaintext highlighter-rouge">${Qt5_DIR}</code> is located at <code class="language-plaintext highlighter-rouge">&lt;qt-install-directory&gt;/5.10.1/msvc2015_64/lib/cmake</code> if you are using Qt 5.10.1 and MSVC 2015.</p>

    <p>The new values are highlighted in red. If the configuration is complete you will see <code class="language-plaintext highlighter-rouge">Configuring done</code> at the lower part output, or else error messages will be displayed.</p>

    <p><img src="../assets/img/2020-12-16-CMake-Medical-Image-Toolchain/cmake-vtk-config-ok.png" alt="alt text" title="CMake configuration success" /></p>
  </li>
  <li>Click <code class="language-plaintext highlighter-rouge">Generate</code> for C++ build.</li>
  <li>Double click the resulting <code class="language-plaintext highlighter-rouge">.sln</code> file in the binary build folder and choose build version <code class="language-plaintext highlighter-rouge">Debug</code> and <code class="language-plaintext highlighter-rouge">x64</code>.
 <img src="../assets/img/2020-12-14-CMake-Intro/cmake-vs-configs.png" alt="alt text" title="MSVC Build Type" /></li>
  <li>Press <code class="language-plaintext highlighter-rouge">Build</code> -&gt; <code class="language-plaintext highlighter-rouge">Build Solution</code> and wait until all build success.
 <img src="../assets/img/2020-12-16-CMake-Medical-Image-Toolchain/msvc-success.png" alt="alt text" title="MSVC Build Type" /></li>
  <li>Choose <code class="language-plaintext highlighter-rouge">Release</code> build type and redo step 7 again.</li>
  <li>For Unix Makefile (Linux/Unix) users, after step 5 you can use <code class="language-plaintext highlighter-rouge">make</code> command to build the library. Similar build method applies for XCode.</li>
</ol>

<h3 id="opencv">OpenCV</h3>
<ol>
  <li>Clone the source code
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> git clone <span class="nt">-b</span> v3.4  https://github.com/opencv/opencv
</code></pre></div>    </div>
  </li>
  <li>
    <p>Open CMake and choose the source code directory and binary build directory. Here we choose <code class="language-plaintext highlighter-rouge">Style 1</code> folder structure.</p>
  </li>
  <li>
    <p>Press <code class="language-plaintext highlighter-rouge">Configure</code> and choose <code class="language-plaintext highlighter-rouge">Visual Studio 14 2015 Win64</code> for 64bit build. Wait until first time configuration complete. This step may take around 10 min.</p>
  </li>
  <li>
    <p>Change the following build options. Then press <code class="language-plaintext highlighter-rouge">Configure</code> again to take effective.</p>

    <div class="language-cmake highlighter-rouge"><div class="highlight"><pre class="highlight"><code> BUILD_DOCS:BOOL=OFF
 BUILD_EXAMPLES:BOOL=OFF
 BUILD_TESTS:BOOL=OFF
 BUILD_SHARED_LIBS:BOOL=ON
 BUILD_WITH_STATIC_CRT:BOOL=ON
 BUILD_opencv_java:BOOL=OFF
 BUILD_opencv_python3:BOOL=OFF
 WITH_MATLAB:BOOL=OFF
    
 <span class="c1"># Choose ON if you need OpenCV with CUDA acceleration</span>
 WITH_CUDA:BOOL=OFF
</code></pre></div>    </div>
  </li>
</ol>

<h3 id="itk">ITK</h3>
<ol>
  <li>Clone the source code
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> git clone <span class="nt">-b</span> v4.13.3  https://github.com/Kitware/ITK.git
</code></pre></div>    </div>
  </li>
  <li>
    <p>Open CMake and choose the source code directory and binary build directory. Here we choose <code class="language-plaintext highlighter-rouge">Style 1</code> folder structure.</p>
  </li>
  <li>
    <p>Press <code class="language-plaintext highlighter-rouge">Configure</code> and choose <code class="language-plaintext highlighter-rouge">Visual Studio 14 2015 Win64</code> for 64bit build. Wait until first time configuration complete. This step may take around 10 min.</p>
  </li>
  <li>Change the following build options. Then press <code class="language-plaintext highlighter-rouge">Configure</code> again to take effective.
    <div class="language-cmake highlighter-rouge"><div class="highlight"><pre class="highlight"><code> BUILD_DOCUMENTATION:BOOL=OFF
 BUILD_EXAMPLES:BOOL=OFF
 BUILD_SHARED_LIBS:BOOL=ON
 BUILD_TESTING:BOOL=OFF

 <span class="c1"># VTK</span>
 Module_ITKVtkGlue:BOOL=ON
 VTK_DIR:PATH=<span class="si">${</span><span class="nv">CMAKE_BINARY_DIR</span><span class="si">}</span>/VTK-build

 <span class="c1"># OpenCV</span>
 Module_ITKVideoBridgeOpenCV:BOOL=ON
 OpenCV_DIR:PATH=<span class="si">${</span><span class="nv">CMAKE_BINARY_DIR</span><span class="si">}</span>/OpenCV-build

 <span class="c1"># VMTK requires class in ITKReview</span>
 Module_ITKReview:BOOL=ON
 ITK_USE_SYSTEM_DOUBLECONVERSION=ON
</code></pre></div>    </div>
  </li>
  <li>Generate the solution and build</li>
</ol>

<h2 id="other-medical-image-libraries">Other Medical Image Libraries</h2>
<p>You can extend the toolchain with other medical image related libraries</p>

<h3 id="common-toolkit-ctk"><a href="https://github.com/commontk/CTK">Common Toolkit (CTK)</a></h3>
<p>A set of common support code for medical imaging, surgical navigation, and related purposes.</p>
<div class="language-cmake highlighter-rouge"><div class="highlight"><pre class="highlight"><code>BUILD_DOCUMENTATION:BOOL=OFF
CTK_BUILD_EXAMPLES:BOOL=OFF
CTK_BUILD_SHARED_LIBS:BOOL=ON
BUILD_TESTING:BOOL=OFF
CTK_ENABLE_DICOM:BOOL=ON
CTK_LIB_DICOM/Core:BOOL=ON
CTK_LIB_DICOM/Widgets:BOOL=ON
CTK_QT_VERSION:STRING=5
Qt5_DIR:PATH=<span class="si">${</span><span class="nv">Qt5_DIR</span><span class="si">}</span>
</code></pre></div></div>

<h3 id="dcmtk"><a href="https://github.com/DCMTK/dcmtk">DCMTK</a></h3>
<p>DCMTK is a collection of libraries and applications implementing large parts the DICOM standard. It includes software for examining, constructing and converting DICOM image files, handling offline media, sending and receiving images over a network connection, as well as demonstrative image storage and worklist servers. DCMTK is is written in a mixture of ANSI C and C++. It comes in complete source code and is made available as “open source” software.</p>
<div class="language-cmake highlighter-rouge"><div class="highlight"><pre class="highlight"><code> CMAKE_INSTALL_PREFIX:PATH=<span class="si">${</span><span class="nv">DCMTK_INSTALL_DIR</span><span class="si">}</span>
</code></pre></div></div>

<h3 id="vascular-modeling-toolkit-vmtk"><a href="https://github.com/vmtk/vmtk">Vascular Modeling Toolkit (VMTK)</a></h3>
<p><img src="../assets/img/2020-12-16-CMake-Medical-Image-Toolchain/vmtk.png" alt="alt text" title="VMTK" /></p>

<p>The Vascular Modeling Toolkit is a collection of libraries and tools for 3D reconstruction, geometric analysis, mesh generation and surface data analysis for image-based modeling of blood vessels.</p>

<h3 id="image-guided-surgery-software-toolkit-igstk"><a href="https://github.com/Kitware/IGSTK">Image Guided Surgery Software Toolkit (IGSTK)</a></h3>
<p>The Image-Guided Surgery Toolkit (IGSTK) is a framework that integrates a set of high-level components with low-level open source software libraries and application programming interfaces (APIs) from hardware vendors. In addition to its interface to common tracking hardware (e.g., Aurora from Northern Digital Inc.), IGSTK has a GUI.</p>

<h3 id="tubetk"><a href="https://github.com/InsightSoftwareConsortium/ITKTubeTK">TubeTK</a></h3>
<p>TubeTK is an open-source toolkit for the segmentation, registration, and analysis of tubes and surfaces in images.</p>

<p>Tubes and surfaces, as generalized 1D and 2D manifolds in N-dimensional images, are essential components in a variety of image analysis tasks. Instances of tubular structures in images include blood vessels in magnetic resonance angiograms and b-mode ultrasound images, wires in microscopy images of integrated circuits, roads in aerial photographs, and nerves in confocal microscopy.</p>

<h2 id="references">References</h2>
<ul>
  <li><a href="http://guitarcplusplus.blogspot.com/2013/02/itk-vtk-qt-on-window-7-64bit-and-visual.html">ITK + VTK + QT on Window 7 64bit and Visual Studio 2010 Pro 32bit project</a></li>
</ul>]]></content><author><name>Jacky Ko</name></author><category term="journal" /><category term="documentation" /><category term="cmake" /><category term="itk" /><category term="vtk" /><category term="opencv" /><category term="qt" /><summary type="html"><![CDATA[To develop desktop medical image software, several essential C++ libraries are recommended for GUI design, graphical rendering and image processing. Here we will provide a detailed instruction on the configuration and compilation of the toolchain.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://jackyko1991.github.io/2020-12-16-CMake-Medical-Image-Toolchain/full_VisibleWoman.jpg" /><media:content medium="image" url="https://jackyko1991.github.io/2020-12-16-CMake-Medical-Image-Toolchain/full_VisibleWoman.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">CMake Introduction</title><link href="https://jackyko1991.github.io/journal/CMake-Intro.html" rel="alternate" type="text/html" title="CMake Introduction" /><published>2020-12-14T00:00:00+00:00</published><updated>2020-12-14T00:00:00+00:00</updated><id>https://jackyko1991.github.io/journal/CMake-Intro</id><content type="html" xml:base="https://jackyko1991.github.io/journal/CMake-Intro.html"><![CDATA[<p><strong>CMake</strong> is a cross-platform open-source software for C++ dependency management. The software generate adequate build system according to different compilers and OS. It supports hierarchial folder structures and multiple third party libraries. The software is used in conjunction with native build environments such as Make, Qt Creator, Ninja, Android Studio, Apple’s Xcode, and Microsoft Visual Studio. In short, CMake could generate compiler and workspace specific C/C++ build system with a single <code class="language-plaintext highlighter-rouge">CMakeLists.txt</code> file.</p>

<h2 id="hello-world">Hello World</h2>
<p>The following source code files (assumed to be put into src/ folder) demonstrate compilation of basic hello world program called hello written in C++.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// src/Hello_world.cc</span>
<span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Hello, world!</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<pre><code class="language-CMake"># src/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)

# set the project name
project("Hello World")

# executable to compile
add_executable(hello "Hello_world.cc")
</code></pre>

<p>In order for CMake to work you have to run the following bash script (placed next to the src/ folder assuming that you are working under Linux-based OS and have all necessary dependencies installed):</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/usr/bin/env bash</span>
<span class="c"># Place this file next to src/ folder</span>
cmake <span class="nt">-S</span> src/ <span class="nt">-B</span> build/ <span class="c"># Generates building files into build/ folder</span>
cmake <span class="nt">--build</span> build/    <span class="c"># Actually builds executable</span>
build/hello             <span class="c"># =&gt; Hello, world! - output from compiled program</span>
</code></pre></div></div>

<p>For a detailed tutorial of <code class="language-plaintext highlighter-rouge">CMakeLists.txt</code>, refers to derekmolloy.ie: http://derekmolloy.ie/hello-world-introductions-to-cmake/.</p>

<h2 id="cmake-basic-workflow">CMake Basic Workflow</h2>
<ol>
  <li>Edit <code class="language-plaintext highlighter-rouge">CMakeLists.txt</code>: CMake will configure the build system with user provided <code class="language-plaintext highlighter-rouge">CMakeLists.txt</code>.</li>
  <li>Generate Build Dependencies: CMake will generate necessary build files according to different platforms and compilers (-G <generator>). For example you may choose to output `Makefile` under Linux/Unix/MinGW , `*.sln` with MSVC in Windows, or `*.xcodeproj` with XCode in MacOS.</generator></li>
</ol>

<h2 id="different-interfaces-of-cmake-build">Different Interfaces of CMake Build</h2>
<p>CMake comes with 3 different binaries for different interface build:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">cmake</code>: Command line interface.</li>
  <li><code class="language-plaintext highlighter-rouge">cmake-gui</code>: Graphical user interface of cmake.</li>
  <li><code class="language-plaintext highlighter-rouge">ccmake</code>: Console equivalent of <code class="language-plaintext highlighter-rouge">cmake-gui</code>. Not available in Windows distribution.</li>
</ul>

<p>The three software can cross use after configuration. i.e. You may use <code class="language-plaintext highlighter-rouge">cmake</code> method to generate the initial build configuration files, then edit the dependencies with <code class="language-plaintext highlighter-rouge">cmake-gui</code> or <code class="language-plaintext highlighter-rouge">ccmake</code> interface for convenience.</p>

<h3 id="command-line-cmake">Command Line (cmake)</h3>
<p>To configure and generate CMake build system under command line mode, type the following command in Terminal:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cmake &lt;src_dir&gt; <span class="nt">--build</span> &lt;build_dir&gt; <span class="nt">-G</span> &lt;generator&gt;
</code></pre></div></div>

<ul>
  <li><code class="language-plaintext highlighter-rouge">&lt;src_dir&gt;</code> refers to the folder containing root <code class="language-plaintext highlighter-rouge">CMakeList.txt</code> file.</li>
  <li><code class="language-plaintext highlighter-rouge">&lt;build_dir&gt;</code> specifies the binary build directory.</li>
  <li><code class="language-plaintext highlighter-rouge">&lt;generator&gt;</code> specifies the build system to be used, e.g. <code class="language-plaintext highlighter-rouge">"Visual Studio 14 2015 Win64"</code>, <code class="language-plaintext highlighter-rouge">"Unix Makefiles"</code></li>
</ul>

<p>Another commonly used CLI method for Linux/Unix system:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cd</span> &lt;src_dir&gt;    <span class="c"># move to source code directory</span>
<span class="nb">mkdir </span>build     <span class="c"># create build directory</span>
<span class="nb">cd </span>build        <span class="c"># move into build directory</span>
cmake ..        <span class="c"># run cmake configuration and generation build files</span>
make            <span class="c"># compile the code</span>
<span class="nb">install</span>         <span class="c"># install the build files (optional)</span>
</code></pre></div></div>
<h3 id="graphical-user-interface-cmake-gui">Graphical User Interface (cmake-gui)</h3>
<ol>
  <li>
    <p>Double click on <code class="language-plaintext highlighter-rouge">cmake-gui</code></p>

    <p><img src="../assets/img/2020-12-14-CMake-Intro/cmake-gui.png" alt="alt text" title="CMake GUI" /></p>
    <ol>
      <li>Similar to <code class="language-plaintext highlighter-rouge">cmake</code>, you need to provide source code location and desired build directory.</li>
      <li>Click <code class="language-plaintext highlighter-rouge">Configure</code></li>
    </ol>
  </li>
  <li>
    <p>Choose the generator that suitable for your compiler</p>

    <p><img src="../assets/img/2020-12-14-CMake-Intro/cmake-choose-generator.png" alt="alt text" title="CMake Generator" /></p>
  </li>
  <li>
    <p>After the initial configure step, the GUI will show you a list of cache variables, similar to the list you see when you run <code class="language-plaintext highlighter-rouge">cmake -L -N</code> from the command line.</p>

    <p><img src="../assets/img/2020-12-14-CMake-Intro/cmake-gui-options.png" alt="alt text" title="CMake Configure" /></p>

    <p>New cache variables are highlighted in red. (In this case, that’s all of them.) If you click <code class="language-plaintext highlighter-rouge">Configure</code> again, the red highlights will disappear, since the variables are no longer considered new.</p>

    <p>Change the variables when necessary. This step is usually essential for projects that depends on third party libraries.</p>

    <p>Once you’ve customized the cache variables, click <code class="language-plaintext highlighter-rouge">Generate</code>. This will generate the build pipeline in the binary folder. You can then use it to build your project.</p>
  </li>
</ol>

<h3 id="console-gui-ccmake">Console GUI (ccmake)</h3>
<p><code class="language-plaintext highlighter-rouge">ccmake</code> is the console equivalent to <code class="language-plaintext highlighter-rouge">cmake-gui</code>. Like the GUI, it lets you set cache variables interactively. When CLI is handy to manage cmake configurations or running CMake in remote machine, ccmake will show it’s superiority over the two other methods</p>

<p><code class="language-plaintext highlighter-rouge">ccmake</code> is run with terminal similar to <code class="language-plaintext highlighter-rouge">cmake</code></p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cd</span> &lt;src_dir&gt;    <span class="c"># move to source code directory</span>
<span class="nb">mkdir </span>build     <span class="c"># create build directory</span>
<span class="nb">cd </span>build        <span class="c"># move into build directory</span>
ccmake ..       <span class="c"># run ccmake configuration and generation build files</span>
</code></pre></div></div>

<p><img src="../assets/img/2020-12-14-CMake-Intro/ccmake-grab.png" alt="alt text" title="ccmake" /></p>

<ul>
  <li>Press <code class="language-plaintext highlighter-rouge">c</code> to start configuration</li>
  <li>Press <code class="language-plaintext highlighter-rouge">t</code> to toggle advance mode</li>
  <li>Use keyboard arrow keys to navigation around, with <code class="language-plaintext highlighter-rouge">Enter</code> key to change the values.</li>
  <li>Path autocomplete is available with <code class="language-plaintext highlighter-rouge">Tab</code> key</li>
  <li>After configuration, press <code class="language-plaintext highlighter-rouge">c</code> to re-configure again and <code class="language-plaintext highlighter-rouge">g</code> to generate the build files. ccmake will close after generation</li>
</ul>

<p>To build the binary:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cd</span> ../build <span class="c"># navigate to build directory</span>
make        <span class="c"># compile the binary</span>
<span class="nb">install</span>     <span class="c"># install the build files (optional)</span>
</code></pre></div></div>

<h2 id="cmake-on-different-platforms">CMake on Different Platforms</h2>
<h3 id="unix-makefiles-unix">Unix Makefiles (Unix)</h3>
<p>CMake generates a Unix makefile by default when run from the command line in a Unix-like environment. Of course, you can generate makefiles explicitly using the <code class="language-plaintext highlighter-rouge">-G</code> option. When generating a makefile, you should also define the <code class="language-plaintext highlighter-rouge">CMAKE_BUILD_TYPE</code> variable. Assuming the source folder is the parent:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cmake <span class="nt">-G</span> <span class="s2">"Unix Makefiles"</span> <span class="nt">-DCMAKE_BUILD_TYPE</span><span class="o">=</span>Debug ..
</code></pre></div></div>

<p>You should define the <code class="language-plaintext highlighter-rouge">CMAKE_BUILD_TYPE</code> variable because makefiles generated by CMake are single-configuration. Unlike a Visual Studio solution, you can’t use the same makefile to build multiple configurations such as <code class="language-plaintext highlighter-rouge">Debug</code> and <code class="language-plaintext highlighter-rouge">Release</code>. A single makefile is capable of building exactly one build type. By default, the available types are <code class="language-plaintext highlighter-rouge">Debug</code>, <code class="language-plaintext highlighter-rouge">MinSizeRel</code>, <code class="language-plaintext highlighter-rouge">RelWithDebInfo</code> and <code class="language-plaintext highlighter-rouge">Release</code>. Watch out – if you forget to define <code class="language-plaintext highlighter-rouge">CMAKE_BUILD_TYPE</code>, you’ll probably get an unoptimized build without debug information, which is useless. To change to a different build type, you must re-run CMake and generate a new makefile.</p>

<p>Once the makefile exists, you can actually build your project by running make. By default, make will build every target that was defined by <code class="language-plaintext highlighter-rouge">CMakeLists.txt</code>.</p>

<ul>
  <li>Compile all targets by default:
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  make
</code></pre></div>    </div>
  </li>
  <li>Compile specific target:
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  make &lt;target&gt;
</code></pre></div>    </div>
  </li>
  <li>Parallel compile:
  You can also parallelize the build by passing <code class="language-plaintext highlighter-rouge">-j 4</code>(4 refers to 4 cores, you may use a higher number if the machine is available) to <code class="language-plaintext highlighter-rouge">make</code>.
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  make <span class="nt">-j</span> &lt;num_of_threads&gt;
</code></pre></div>    </div>
  </li>
</ul>

<p>The makefile generated by CMake detects header file dependencies automatically, so editing a single header file won’t necessarily rebuild the entire project.</p>

<h3 id="microsoft-visual-studio-windows">Microsoft Visual Studio (Windows)</h3>
<p>We’ll generate a Visual Studio <code class="language-plaintext highlighter-rouge">.sln</code> file from the CMake command line. If you have several versions of Visual Studio installed, you’ll want to tell cmake which version to use. Again, assuming that the source folder is the parent:</p>

<div class="language-bat highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">cmake</span> <span class="na">-G </span><span class="s2">"Visual Studio 14 Win64"</span> ..
</code></pre></div></div>

<p>The command will generate a Visual Studio <code class="language-plaintext highlighter-rouge">.sln</code> file for a <strong><em>32-bit</em></strong> build. There are no multiplatform <code class="language-plaintext highlighter-rouge">.sln</code> files using CMake, so for a <strong><em>64-bit</em></strong> build, you must specify the 64-bit generator:</p>

<div class="language-bat highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">cmake</span> <span class="na">-G </span><span class="s2">"Visual Studio 15 2017"</span> ..
<span class="kd">cmake</span> <span class="na">-G </span><span class="s2">"Visual Studio 15 2017 Win64"</span> ..

<span class="kd">cmake</span> <span class="na">-G </span><span class="s2">"Visual Studio 12"</span> ..
<span class="kd">cmake</span> <span class="na">-G </span><span class="s2">"Visual Studio 12 Win64"</span> ..
<span class="kd">cmake</span> <span class="na">-G </span><span class="s2">"Visual Studio 12 2013"</span> ..
<span class="kd">cmake</span> <span class="na">-G </span><span class="s2">"Visual Studio 12 2013 Win64"</span> ..

<span class="kd">cmake</span> <span class="na">-G </span><span class="s2">"Visual Studio 14"</span> ..
<span class="kd">cmake</span> <span class="na">-G </span><span class="s2">"Visual Studio 14 Win64"</span> ..
<span class="kd">cmake</span> <span class="na">-G </span><span class="s2">"Visual Studio 14 2015"</span> ..
<span class="kd">cmake</span> <span class="na">-G </span><span class="s2">"Visual Studio 14 2015 Win64"</span> ..
</code></pre></div></div>
<p>Double click the resulting <code class="language-plaintext highlighter-rouge">.sln</code> file in Visual Studio, go to the <code class="language-plaintext highlighter-rouge">Solution Explorer</code> panel, right-click the target you want to run, then choose <code class="language-plaintext highlighter-rouge">Set as Startup Project</code>. Build and run as you normally would.</p>

<p><img src="../assets/img/2020-12-14-CMake-Intro/cmake-sln-explorer.png" alt="alt text" title="Set as Startup Project" /></p>

<p>Note that CMake adds two additional targets to the solution: <code class="language-plaintext highlighter-rouge">ALL_BUILD</code> and <code class="language-plaintext highlighter-rouge">ZERO_CHECK</code>. <code class="language-plaintext highlighter-rouge">ZERO_CHECK</code> automatically re-runs CMake when it detects a change to CMakeLists.txt. <code class="language-plaintext highlighter-rouge">ALL_BUILD</code> usually builds all other targets, making it somewhat redundant in Visual Studio. If you’re used to setting up your solutions a certain way, it might seem annoying to have these extra targets in your <code class="language-plaintext highlighter-rouge">.sln</code> file, but you get used to it. CMake lets you organize targets and source files into folders, but I didn’t demonstrate that in the CMakeDemo sample.</p>

<p><img src="../assets/img/2020-12-14-CMake-Intro/cmake-vs-configs.png" alt="alt text" title="MSVC Build Type" /></p>

<p>Like any Visual Studio solution, you can change build type at any time from the Solution Configuration drop-down list. The CMakeDemo sample uses CMake’s default set of build types. <code class="language-plaintext highlighter-rouge">Release</code> configuration doesn’t produce any debug information yet a much faster runtime than <code class="language-plaintext highlighter-rouge">Debug</code>. If your program consist of large size file i/o or complex computation process, <code class="language-plaintext highlighter-rouge">Release</code> version will provide a much swift and fast executable than <code class="language-plaintext highlighter-rouge">Debug</code> one.</p>

<h3 id="ninja-windowsunix">Ninja (Windows/Unix)</h3>
<p>CMake also exposes a Ninja generator. Ninja is similar to make, but faster. It generates a build.ninjafile, which is similar to a Makefile. The Ninja generator is also single-configuration. Ninja’s <code class="language-plaintext highlighter-rouge">-j</code> option auto detects the number of available CPUs.</p>

<h3 id="other-compilers-xcode-qt-creator">Other Compilers (Xcode Qt Creator）</h3>

<h2 id="other-cmake-features">Other CMake Features</h2>
<ul>
  <li>You can perform a build from the command line, regardless of the generator used: cmake –build . –target CMakeDemo –config Debug</li>
  <li>You can create build pipelines that cross-compile for other environments with the help of the CMAKE_TOOLCHAIN_FILE variable.</li>
  <li>You can generate a compile_commands.json file that can be fed to Clang’s LibTooling library.</li>
</ul>

<h2 id="recommended-ide-for-cmake">Recommended IDE for CMake</h2>
<ul>
  <li>Microsoft Visual Studio
    <ul>
      <li>Platform: Windows</li>
      <li>Complier: MVSC</li>
    </ul>
  </li>
  <li>Qt Creator
    <ul>
      <li>Platform: Windows, Linux, MacOS</li>
      <li>Complier: MSVC, GCC, MinGW</li>
    </ul>
  </li>
  <li>CLion (Cross Platform)
    <ul>
      <li>Platform: Windows, Linux, MacOS</li>
      <li>Complier: GCC, MinGW</li>
    </ul>
  </li>
</ul>

<h2 id="references">References</h2>
<ul>
  <li><a href="https://cmake.org/">CMake Official Site</a></li>
  <li><a href="https://en.wikipedia.org/wiki/CMake">CMake Wiki Page</a></li>
  <li><a href="https://github.com/Kitware/CMake">CMake Github Page</a></li>
  <li><a href="http://derekmolloy.ie/hello-world-introductions-to-cmake/">Introduction to CMake by Example</a></li>
  <li><a href="https://www.jetbrains.com/help/clion/quick-cmake-tutorial.html">Quick CMake tutorial with CLion</a></li>
</ul>]]></content><author><name>Jacky Ko</name></author><category term="journal" /><category term="documentation" /><category term="cmake" /><summary type="html"><![CDATA[CMake is a cross-platform open-source software for C++ dependency management. The software generate adequate build system according to different compilers and OS. It supports hierarchial folder structures and multiple third party libraries. The software is used in conjunction with native build environments such as Make, Qt Creator, Ninja, Android Studio, Apple’s Xcode, and Microsoft Visual Studio. In short, CMake could generate compiler and workspace specific C/C++ build system with a single CMakeLists.txt file.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://jackyko1991.github.io/2020-12-14-CMake-Intro/cmake.png" /><media:content medium="image" url="https://jackyko1991.github.io/2020-12-14-CMake-Intro/cmake.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">HPC Cluster Setup Part 3 - Slurm Installation</title><link href="https://jackyko1991.github.io/journal/Cluster-Setup-3.html" rel="alternate" type="text/html" title="HPC Cluster Setup Part 3 - Slurm Installation" /><published>2019-09-20T00:00:00+00:00</published><updated>2019-09-20T00:00:00+00:00</updated><id>https://jackyko1991.github.io/journal/Cluster-Setup-3</id><content type="html" xml:base="https://jackyko1991.github.io/journal/Cluster-Setup-3.html"><![CDATA[<p><strong>Slurm</strong> (Simple Linux Utility for Resource Management) is a free and open source job scheduler for Linux and Unix kernel supercomputer and clusters. The software is currently used as the workload manager on about 60% of the Top 500 supercomputers.</p>

<p>You may get deeper look at Slurm through the official <a href="https://slurm.schedmd.com/documentation.html">documentations</a> and <a href="https://slurm.schedmd.com/tutorials.html">tutorials</a>. Here we only provide a minimal tutorial on GPU cluster setup.</p>

<p>Computation jobs in HPC clusters are run in sequential orders with a specialized scheduling scheme. A scheduler receive user job submissions and arrange job executions in accordance to the priority level. When requested computational resources are available the submitted jobs will be processed in order to fully utilize computation hardwares.</p>

<h2 id="slurm-architecture">Slurm Architecture</h2>
<p><img src="../assets/img/2019-09-20-Cluster-Setup-Part-3/arch.gif" alt="alt text" title="Slurm architecture" /></p>

<p>Slurm is run through Linux daemons for different services:</p>

<ol>
  <li><strong>slurmctld</strong> (Slurm controller daemon)
    <ul>
      <li>To monitor resources and work</li>
      <li>Can setup backup controller at multiple nodes for high availability cluster</li>
      <li>Works at head node</li>
    </ul>
  </li>
  <li><strong>slurmd</strong> (Slurm worker daemon)
    <ul>
      <li>Works at compute nodes</li>
      <li>Waits and executes works assigned by <strong>slurmctld</strong> and return computation status</li>
    </ul>
  </li>
  <li><strong>slurmdbd</strong> (Slurm database daemon, optional)
    <ul>
      <li>Record accounting information into database</li>
      <li>Necessary when users need to set resources limits</li>
    </ul>
  </li>
</ol>

<p>Slurm commands will be explained after the installation.</p>

<h2 id="slurm-installation">Slurm Installation</h2>
<h3 id="head-node-configuration">Head Node Configuration</h3>
<ol>
  <li>Login to the head node</li>
  <li>To make the resolution of worker nodes in the cluster clearer, we may give local hostnames in respect to their IP addresses:
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">sudo </span>vim /etc/hosts
</code></pre></div>    </div>
    <p>Add the associate lines:</p>
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> &lt;ip addr of node02&gt;      node02
 &lt;ip addr of node03&gt;      node03
</code></pre></div>    </div>
  </li>
  <li>Install the Slurm controller package:
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">sudo </span>apt-get <span class="nb">install </span>slurm-wlm <span class="nt">-y</span>
</code></pre></div>    </div>
  </li>
  <li>Copy and edit the default Slurm configuration file:
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">cd</span> /etc/slurm-llnl
 <span class="nb">cp</span> /usr/share/doc/slurm-client/examples/slurm.conf.simple.gz <span class="nb">.</span>
 <span class="nb">gzip</span> <span class="nt">-d</span> slurm.conf.simple.gz
 <span class="nb">sudo mv </span>slurm.conf.simple slurm.conf
 <span class="nb">sudo </span>vim slurm.conf
</code></pre></div>    </div>
  </li>
  <li>Set the controller node info, edit the <code class="language-plaintext highlighter-rouge">slurm.conf</code> file:
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> SlurmctldHost=node01(&lt;ip addr of node01&gt;)
 # e.g.: node01(192.168.1.14)
</code></pre></div>    </div>
  </li>
  <li>Customize the scheduler algorithm
 HPC cluster jobs can be allocated in different ways. Here we will use the basic “consumable resources” approach. This refers to that each node has a list of consumable resources, including CPU cores, memory and GPUs. The request will be allocated according to default settings unless user specifications. You may edit the <code class="language-plaintext highlighter-rouge">SelectType</code> field as following:
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> SelectType=select/cons_res
 SelectTypeParameters=CR_Core_Memory,CR_CORE_DEFAULT_DIST_BLOCK,CR_ONE_TASK_PER_CORE
</code></pre></div>    </div>
  </li>
  <li>Set the cluster name
 You may give an arbitrary name to your new cluster at <code class="language-plaintext highlighter-rouge">ClusterName</code> under <code class="language-plaintext highlighter-rouge">LOGGING AND ACCOUNTING</code> section:
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> ClusterName=mycluster
</code></pre></div>    </div>
  </li>
  <li>Set the worker nodes
 We need to tell Slurm which computers in the network is used as computational nodes. Near the end of the file, the default file has an example entry for a single worker node. Change it to the one satisfy our setup:
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> # here the head node (node01) also act as a worker node
 NodeName=node01 NodeAddr=&lt;ip addr node01&gt; CPUs=40 Sockets=2 CoresPerSocket=20 ThreadsPerCore=1 RealMemory=515896 State=UNKNOWN 
 NodeName=node02 NodeAddr=&lt;ip addr node02&gt; CPUs=40 Sockets=2 CoresPerSocket=20 ThreadsPerCore=1 RealMemory=515896 State=UNKNOWN 
 NodeName=node03 NodeAddr=&lt;ip addr node03&gt; CPUs=40 Sockets=2 CoresPerSocket=20 ThreadsPerCore=1 RealMemory=515896 State=UNKNOWN 
</code></pre></div>    </div>
    <p>Here we have identical nodes with dual CPU sockets. Each CPU are running with 20 cores without hyper-threading. RAM size is 515896MB.</p>

    <p><em>Kindly reminder: You may reserve a portion of computation resources in head node to prevent worker tasks jamming Slurm controller services, i.e. set CPUs to 36 and reduce the RAM size in the ‘slurm.conf’ file</em></p>
  </li>
  <li>
    <p>Create a partition</p>

    <p><img src="../assets/img/2019-09-20-Cluster-Setup-Part-3/entities.gif" alt="alt text" title="Slurm cluster entites" /></p>

    <p>Partitions in Slurm group worker nodes into logical sets. Jobs and resources can be assigned by user to specific partitions with each partition running with different priority rules. This encourages different hardware owners to participate in a single cluster by sharing peripheral devices including controller and storage services.</p>

    <p>At the last line of <code class="language-plaintext highlighter-rouge">slurm.conf</code>, define the partition:</p>
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> PartitionName=partition1 Nodes=node[01-03] Default=YES MaxTime=INFINITE State=UP
</code></pre></div>    </div>

    <p>If you want to set a maximum job running time under partition level, you may set <code class="language-plaintext highlighter-rouge">MaxTime=&lt;min, hr:min:00, days-hr:min:00, or days-hr&gt;</code>, e.g. <code class="language-plaintext highlighter-rouge">MaxTime=60</code> for 60mins and <code class="language-plaintext highlighter-rouge">MaxTime=2-12:00:00</code> for 2 days 12 hours run.</p>
  </li>
  <li>Configure cgroups:
Slurm supports Linux <a href="https://en.wikipedia.org/wiki/Cgroups">cgroups</a> kernel isolation, which will restrict the access to system resources. To tell Slurm which resources are allowed access:
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo vim /etc/slurm-llnl.cgroup.conf
</code></pre></div>    </div>

    <p>Paste the following:</p>
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>CgroupMountpoint="/sys/fs/cgroup"
CgroupAutomount=yes
CgroupReleaseAgentDir="/etc/slurm-llnl/cgroup"
AllowedDevicesFile="/etc/slurm-llnl/cgroup_allowed_devices_file.conf"
ConstrainCores=yes
TaskAffinity=no
ConstrainRAMSpace=yes
ConstrainSwapSpace=no
ConstrainDevices=yes
AllowedRamSpace=100
AllowedSwapSpace=0
MaxRAMPercent=100
MaxSwapPercent=100
MinRAMSpace=30
</code></pre></div>    </div>

    <p>Then you need to whitelist the system devices by creating the file <code class="language-plaintext highlighter-rouge">/etc/slurm-llnl/cgroup_allowed_devices_file.conf</code>:</p>
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/dev/null
/dev/urandom
/dev/zero
/dev/sda*
/dev/cpu/*/*
/dev/pts/*
/clusterfs*
</code></pre></div>    </div>

    <p>To enable memory cgroups for restricting memory allocation by jobs you need to modify the Linux kernel upon bootup:</p>
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>vim /etc/default/grub
</code></pre></div>    </div>

    <p>Chnage the GRUB commandline to:</p>
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1"
</code></pre></div>    </div>

    <p>Update GRUB and reboot:</p>
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo update-grub
sudo reboot
</code></pre></div>    </div>
  </li>
  <li>Copy the configuration files to NFS
To apply settings to all nodes across the cluster, copy the slurm configuration files and Munge keys to the shared drive:
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo cp </span>slurm.conf cgroup.conf cgroup_allowed_devices_file.conf /clusterfs
<span class="nb">sudo cp</span> /etc/munge/munge.key /clusterfs
</code></pre></div>    </div>

    <blockquote>
      <p>Munge acts like key-based SSH for Slurm to communicate among nodes. It generates a private key to be used on all nodes while inter-node signals are encrypted with timestamps. Receiving signals will be decrypted with the identical key. Therefore both time synchronization and <code class="language-plaintext highlighter-rouge">munge.key</code> are important for Slurm to work properly.</p>
    </blockquote>
  </li>
  <li>Start Slurm services
Restart Munge:
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>systemctl <span class="nb">enable </span>munge
<span class="nb">sudo </span>systemctl start munge
</code></pre></div>    </div>

    <p>Restart Slurm worker daemon:</p>
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>systemctl <span class="nb">enable </span>slurmd
<span class="nb">sudo </span>systemctl start slurmd
</code></pre></div>    </div>

    <p>Restart Slurm controller daemon:</p>
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>systemctl <span class="nb">enable </span>slurmctld
<span class="nb">sudo </span>systemctl start slurmctld
</code></pre></div>    </div>
  </li>
</ol>

<h3 id="worker-node-configuration">Worker node configuration</h3>
<p>Repeat this part for all worker nodes except for head node</p>

<ol>
  <li>Install Slurm client
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">sudo </span>apt-get <span class="nb">install </span>slurmd slurm-client <span class="nt">-y</span>
</code></pre></div>    </div>
  </li>
  <li>Update <code class="language-plaintext highlighter-rouge">/etc/hosts</code> to resolve other nodes on the worker node, for example on <code class="language-plaintext highlighter-rouge">node02</code>:
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> &lt;ip addr&gt;    node01
 &lt;ip addr&gt;    node03
</code></pre></div>    </div>
  </li>
  <li>Copy the configuration files from shared drives
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">sudo cp</span> /clusterfs/munge.key /etc/munge/munge.key
 <span class="nb">sudo cp</span> /clusterfs/slurm.conf /etc/slurm-llnl/slurm.conf
 <span class="nb">sudo cp</span> /clusterfs/cgroup<span class="k">*</span> /etc/slurm-llnl
</code></pre></div>    </div>
  </li>
  <li>Start Munge
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">sudo </span>systemctl <span class="nb">enable </span>munge
 <span class="nb">sudo </span>systemctl start munge
</code></pre></div>    </div>
  </li>
  <li>Test Munge
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> ssh &lt;username&gt;@node01 munge <span class="nt">-n</span> | unmunge
</code></pre></div>    </div>
    <p>You will receive result similar to the following:</p>
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> STATUS:           Success (0)
 ENCODE_HOST:      node01
 ENCODE_TIME:      2018-11-15 15:48:56 -0600 (1542318536)
 DECODE_TIME:      2018-11-15 15:48:56 -0600 (1542318536)
 TTL:              300
 CIPHER:           aes128 (4)
 MAC:              sha1 (3)
 ZIP:              none (0)
 UID:              pi
 GID:              pi
 LENGTH:           0
</code></pre></div>    </div>
    <p>Check <code class="language-plaintext highlighter-rouge">/etc/munge/munge.key</code> are the same across nodes if you get error.</p>
  </li>
  <li>Start Slurm worker daemon
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">sudo </span>systemctl <span class="nb">enable </span>slurmd
 <span class="nb">sudo </span>systemctl start slurmd
</code></pre></div>    </div>
  </li>
</ol>

<h3 id="check-slurm-work-properly">Check Slurm Work properly</h3>
<p>Login</p>

<h2 id="references">References</h2>
<p><a href="https://medium.com/@glmdev/building-a-raspberry-pi-cluster-784f0df9afbd">Building a Raspberry Pi Cluster</a>
<a href="https://slurm.schedmd.com/documentation.html">Slurm documentation</a>
<a href="https://github.com/mknoxnv/ubuntu-slurm">Ubuntu Slurm</a></p>]]></content><author><name>Jacky Ko</name></author><category term="journal" /><category term="documentation" /><category term="clusters" /><category term="hpc" /><category term="slurm" /><summary type="html"><![CDATA[Slurm (Simple Linux Utility for Resource Management) is a free and open source job scheduler for Linux and Unix kernel supercomputer and clusters. The software is currently used as the workload manager on about 60% of the Top 500 supercomputers.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://jackyko1991.github.io/2019-09-20-Cluster-Setup-Part-3/slurm-better-thumbnail.png" /><media:content medium="image" url="https://jackyko1991.github.io/2019-09-20-Cluster-Setup-Part-3/slurm-better-thumbnail.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">HPC Cluster Setup Part 2 - Hardware, NFS and NIS Setup</title><link href="https://jackyko1991.github.io/journal/Cluster-Setup-2.html" rel="alternate" type="text/html" title="HPC Cluster Setup Part 2 - Hardware, NFS and NIS Setup" /><published>2019-09-13T00:00:00+00:00</published><updated>2019-09-13T00:00:00+00:00</updated><id>https://jackyko1991.github.io/journal/Cluster-Setup-2</id><content type="html" xml:base="https://jackyko1991.github.io/journal/Cluster-Setup-2.html"><![CDATA[<p>To setup a HPC cluster, you should always get the hardware ready first.</p>

<h2 id="step-0-hardware-setup">Step 0: Hardware Setup</h2>
<p>Here we demonstrate the setup of a small cluster unit with 1 head node and 3 child nodes. For simplicity we will the CPU architecture is assume to be x64, though similar setup also works on ARM nodes like Raspberry Pi.</p>

<h3 id="parts-list">Parts list</h3>
<ul>
  <li>x64 architecture computers with Nvidia GPUs x 4 (1 head + 2 child nodes, recommended identical devices, GPUs should support CUDA 8.0 or above)</li>
  <li>Network router with minimum 4 ports x 1 (expandable via switches, 1000Gbps recommended)</li>
</ul>

<p>This setup is scalable to as many nodes as you have, you may also have a separate network attached storage to the system for large data I/O. Here we will use the head node to act as the storage node.</p>

<h2 id="step-1-install-os">Step 1: Install OS</h2>
<p>It would be far easier to have all cluster nodes in same OS. To reduce graphical computation resources, I highly recommend Ubuntu Server for child nodes. If you are comfortable with SSH communications and CLI Linux environment, install Ubuntu Server for head node as well, or else you may choose any Ubuntu Desktops with same distribution number as the child nodes. This is to maintain the same dependency environment across whole cluster and software can be installed simultaneously across all nodes.</p>

<h3 id="choice-of-os">Choice of OS</h3>
<ul>
  <li>GUI head node
    <ul>
      <li><a href="https://ubuntu.com/download/desktop">Ubuntu Desktop 18.04 LTS</a> (install in head node only)</li>
      <li><a href="https://ubuntu.com/download/server">Ubuntu Server 18.04 LTS</a> (install in all child nodes)</li>
    </ul>
  </li>
  <li>CLI head node
    <ul>
      <li><a href="https://ubuntu.com/download/server">Ubuntu Server 18.04 LTS</a> (install in all nodes)</li>
    </ul>
  </li>
</ul>

<p>Both GUI and CLI works the same afterward…as long as all Slurm setups are accomplished under CLI environment…Linux newbies may feel more comfortable with GUI version as long as the file editing can be done without knowledge of CLI editors like Nano or Vim. Under GUI Linux you can call up the CLI terminal with <code class="language-plaintext highlighter-rouge">Ctrl</code> + <code class="language-plaintext highlighter-rouge">Alt</code> + <code class="language-plaintext highlighter-rouge">T</code>.</p>

<h2 id="step-2-network-setup">Step 2: Network Setup</h2>
<p><img src="../assets/img/2019-09-13-Cluster-Setup-Part-2/fix-ip-dhcp.jpg" alt="alt text" title="Router assign static IP with MAC address under DHCP" /></p>

<p>It is essential to keep all nodes IPs constant over time to guarantee stable communication between nodes. In most modern day routers users may login to the admin interface to bind device IP according their MAC addresses under DHCP.</p>

<h2 id="step-3-node-setup">Step 3: Node Setup</h2>
<blockquote>
  <p>Slurm expects hosts to be named with a specific pattern: <code class="language-plaintext highlighter-rouge">&lt;nodename&gt;</code><code class="language-plaintext highlighter-rouge">&lt;nodenumber&gt;</code>. When choosing the hostname for the nodes, it would be convenient to name them systemically in order. (e.g. <code class="language-plaintext highlighter-rouge">node01</code>,<code class="language-plaintext highlighter-rouge">node02</code>,<code class="language-plaintext highlighter-rouge">node03</code>,<code class="language-plaintext highlighter-rouge">node04</code>,…)</p>
</blockquote>

<h3 id="hostname">Hostname</h3>
<p>Now we may setup the hostname:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo hostname </span>node01       	<span class="c"># whatever name you chose</span>
<span class="nb">sudo </span>vim /etc/hostname    	<span class="c"># change the hostname here too</span>
<span class="nb">sudo </span>vim /etc/hosts       	<span class="c"># change the hostname to "node01"</span>
</code></pre></div></div>

<h3 id="system-time">System Time</h3>
<p>Node communication requires accurate time synchronizations. The <code class="language-plaintext highlighter-rouge">ntpdate</code> package will periodically synchronize OS time in the background.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt-get <span class="nb">install </span>ntpdate <span class="nt">-y</span>
</code></pre></div></div>

<h3 id="reboot">Reboot</h3>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>reboot
</code></pre></div></div>

<p><strong>Repeat the procedure for all nodes but each of them with a different node number.</strong></p>

<h2 id="shared-storage">Shared Storage</h2>
<p><img src="../assets/img/2019-09-13-Cluster-Setup-Part-2/NFS.jpg" alt="alt text" title="NFS illustration" /></p>

<blockquote>
  <p>Storage node is one the three key components of the HPC cluster. In order for the softwares/ data be able to run on any of the nodes in the cluster, each node should be able access to the same files. In a large scale cluster there is often an individual node for data storage purposes.</p>
</blockquote>

<p>In this mini setup we will use the head node to act as the storage node. A specific folder will be exported as a network file system (NFS) and mounted among all nodes. If you have a separate network attached storage (NAS), you may mount that on all nodes as NFS.</p>

<h3 id="create-and-export-nfs-directory">Create and Export NFS directory</h3>
<ol>
  <li>Create mount directory in head node
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo mkdir</span> /clusterfs <span class="c">#create NFS directory at /clusterfs</span>
<span class="nb">sudo chown </span>nobody.nogroup <span class="nt">-R</span> /clusterfs <span class="c">#/clusterfs now owned by pseduo user</span>
<span class="nb">sudo chmod </span>777 <span class="nt">-R</span> /clusterfs <span class="c">#R/W permission for all users to the NFS directory</span>
</code></pre></div>    </div>
  </li>
  <li>Export the NFS directory
You need to host a NFS server in the head node.
    <ol>
      <li>Install NFS server
        <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">sudo </span>apt <span class="nb">install </span>nfs-kernel-server <span class="nt">-y</span>
</code></pre></div>        </div>
      </li>
      <li>Export the NFS directory
 Add following lines to <code class="language-plaintext highlighter-rouge">/etc/exports</code>:
        <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> /clusterfs    &lt;ip-address&gt;/24(rw,sync,no_root_squash,no_subtree_check)
</code></pre></div>        </div>
        <p>where <code class="language-plaintext highlighter-rouge">&lt;ip-address&gt;</code> is the IP of the head node. You may check with router interface or via <code class="language-plaintext highlighter-rouge">ifconfig</code>. This permission setting allows any clients to mount the shared directory. e.g. if the LAN address is <code class="language-plaintext highlighter-rouge">192.168.0.123</code>, you will have</p>
        <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> /clusterfs    192.168.0.123/24(rw,sync,no_root_squash,no_subtree_check)
</code></pre></div>        </div>
      </li>
    </ol>

    <ul>
      <li><code class="language-plaintext highlighter-rouge">rw</code> provides client R/W access</li>
      <li><code class="language-plaintext highlighter-rouge">sync</code> forces changes to be written on each transaction</li>
      <li><code class="language-plaintext highlighter-rouge">no_root_squash</code> enables the root users of the clients to write files as root permissions</li>
      <li><code class="language-plaintext highlighter-rouge">no_subtree_check</code> prevents errors caused by a file being changed while another system is using it.</li>
    </ul>
  </li>
  <li>Update the NFS kernel server
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>exportfs <span class="nt">-a</span>
</code></pre></div>    </div>
  </li>
</ol>

<h3 id="mount-the-nfs-directory">Mount the NFS directory</h3>
<p>Now we have exported the NFS directory from head node to the network. On child nodes you need mount in order to work like a single directory. <strong>Repeat the following procedures for all child nodes</strong></p>

<ol>
  <li>Install NFS client
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt <span class="nb">install </span>nfs-common <span class="nt">-y</span>
</code></pre></div>    </div>
  </li>
  <li>Create mount directory in child nodes
Guess what, this is exactly the same you have done for the head node
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo mkdir</span> /clusterfs <span class="c">#create NFS directory at /clusterfs</span>
<span class="nb">sudo chown </span>nobody.nogroup <span class="nt">-R</span> /clusterfs <span class="c">#/clusterfs now owned by pseduo user</span>
<span class="nb">sudo chmod </span>777 <span class="nt">-R</span> /clusterfs <span class="c">#R/W permission for all users to the NFS directory</span>
</code></pre></div>    </div>
  </li>
  <li>Auto mounting
We want the NFS directory automatically mounted on the child nodes when they boot.
    <ol>
      <li>Edit <code class="language-plaintext highlighter-rouge">/etc/fstab</code> by adding:</li>
    </ol>

    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> &lt;head-node-ip&gt;:/clusterfs    /clusterfs    nfs    defaults   0 0
</code></pre></div>    </div>

    <p>This line refers to mounting shared directory at head node to the “local” folder <code class="language-plaintext highlighter-rouge">/clusterfs</code> as NFS.</p>
    <ol>
      <li>Actually mount the drive:
 <code class="language-plaintext highlighter-rouge">sudo mount -a</code>
 Once you create a file in any node’s <code class="language-plaintext highlighter-rouge">/clusterfs</code> it will be RWable in all other nodes.</li>
    </ol>
  </li>
</ol>

<h2 id="nis-system">NIS System</h2>
<p>You will need a NIS server in order to synchronize all user’s account among the cluster network.</p>

<h3 id="configuring-nis-server">Configuring NIS Server</h3>
<ol>
  <li>Install NIS System on head node
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">sudo </span>apt-get <span class="nb">install </span>nis
</code></pre></div>    </div>
  </li>
  <li>Configure this node as master
    <ol>
      <li>Edit the NIS configuration file
        <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">sudo </span>vim /etc/default/nis
</code></pre></div>        </div>
        <p>Change the line</p>
        <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> NISSERVER=master
</code></pre></div>        </div>
      </li>
      <li>Select proper access IPs to the NIS
        <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">sudo </span>vim /etc/ypserv.securenets
</code></pre></div>        </div>
        <p>Change the line</p>
        <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> # This line gives access to everybody. PLEASE ADJUST!
 # comment out
 # 0.0.0.0 0.0.0.0
 # add to the end: IP range you allow to access
 255.255.255.0   10.0.0.0
</code></pre></div>        </div>
      </li>
      <li>Modify the Makefile
        <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">sudo </span>vim /var/yp/Makefile
</code></pre></div>        </div>
        <p>Change the lines</p>
        <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> # line 52: change
 MERGE_PASSWD=true
 # line 56: change
 MERGE_GROUP=true
</code></pre></div>        </div>
        <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">sudo </span>vim /etc/hosts
</code></pre></div>        </div>
        <p>Add the IP address for NIS</p>
        <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> 127.0.0.1       localhost
 # add own IP address for NIS
 10.0.0.30       dlp.srv.world        dlp
</code></pre></div>        </div>
      </li>
      <li>Update the NIS database
        <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> /usr/lib/yp/ypinit <span class="nt">-m</span>
</code></pre></div>        </div>

        <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> At this point, we have to construct a list of the hosts which will run NIS
 servers.  dlp.srv.world is in the list of NIS server hosts.  Please continue to add
 the names for the other hosts, one per line.  When you are done with the
 list, type a &lt;control D&gt;.
         next host to add:  dlp.srv.world
         next host to add:  # Ctrl + D キー
 The current list of NIS servers looks like this:
 dlp.srv.world
 Is this correct?  [y/n: y]  y
 We need a few minutes to build the databases...
 Building /var/yp/srv.world/ypservers...
 Running /var/yp/Makefile...
 make[1]: Entering directory '/var/yp/srv.world'
 Updating passwd.byname...
 Updating passwd.byuid...
 Updating group.byname...
 Updating group.bygid...
 Updating hosts.byname...
 Updating hosts.byaddr...
 Updating rpc.byname...
 Updating rpc.bynumber...
 Updating services.byname...
 Updating services.byservicename...
 Updating netid.byname...
 Updating protocols.bynumber...
 Updating protocols.byname...
 Updating netgroup...
 Updating netgroup.byhost...
 Updating netgroup.byuser...
 Updating shadow.byname... Ignored -&gt; merged with passwd
 make[1]: Leaving directory '/var/yp/srv.world'
 dlp.srv.world has been set up as a NIS master server.
 Now you can run ypinit -s dlp.srv.world on all slave server.
</code></pre></div>        </div>
      </li>
      <li>Restart the NIS service
        <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">sudo </span>systemctl restart nis
</code></pre></div>        </div>
      </li>
    </ol>
  </li>
  <li>If you have added users in local servers, apply them to NIS database as well
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">cd</span> /var/yp
 make
</code></pre></div>    </div>
  </li>
</ol>

<h3 id="configuring-nis-client">Configuring NIS Client</h3>
<ol>
  <li>Install NIS System on head node
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">sudo </span>apt-get <span class="nb">install </span>nis
</code></pre></div>    </div>
  </li>
  <li>Configure this node as client
    <ol>
      <li>Edit the NIS configuration file
        <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">sudo </span>vim /etc/yp.conf
</code></pre></div>        </div>
        <p>Change the line</p>
        <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> # ypserver ypserver.network.com
 # add to the end: [domain name] [server] [NIS server's hostname]
 domain srv.world server dlp.srv.world
</code></pre></div>        </div>
      </li>
      <li>Edit NS Switch Config
        <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">sudo </span>vim /etc/nsswitch.conf
</code></pre></div>        </div>
        <p>Change the lines</p>
        <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> # line 7: add like follows
 passwd:         compat systemd nis
 group:          compat systemd nis
 shadow:         compat nis
 gshadow:        files
 hosts:          files dns nis
</code></pre></div>        </div>
      </li>
      <li>Set the PAM rule for SSH if you wan to create /home/user/ directory automatically
        <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">sudo </span>vim /etc/pam.d/common-session
</code></pre></div>        </div>
        <p>Add the lines</p>
        <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> # add to the end
 session optional        pam_mkhomedir.so skel=/etc/skel umask=077
</code></pre></div>        </div>
      </li>
      <li>Restart the NIS
        <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">sudo </span>systemctl restart rpcbind nis
</code></pre></div>        </div>
      </li>
      <li>
        <p>Try to logout and login again and see the NIS works</p>
      </li>
      <li>Change the NIS password if you want to
        <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> yppasswd
</code></pre></div>        </div>
        <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> Changing NIS account information for bionic on dlp.srv.world.
 Please enter old password:
 Changing NIS password for bionic on dlp.srv.world.
 Please enter new password:
 Please retype new password:
 The NIS password has been changed on dlp.srv.world.
</code></pre></div>        </div>
      </li>
    </ol>
  </li>
</ol>

<p>The hardware part is done. Coming next we will start to install the job scheduler <strong>Slurm</strong>.</p>

<h2 id="references">References</h2>
<ul>
  <li><a href="https://medium.com/@glmdev/building-a-raspberry-pi-cluster-784f0df9afbd">Building a Raspberry Pi Cluster</a></li>
  <li><a href="https://slurm.schedmd.com/documentation.html">Slurm documentation</a></li>
  <li><a href="https://hpcc.usc.edu/support/documentation/slurm/">Running a Job on HPC using Slurm</a></li>
</ul>]]></content><author><name>Jacky Ko</name></author><category term="journal" /><category term="documentation" /><category term="clusters" /><category term="hpc" /><summary type="html"><![CDATA[To setup a HPC cluster, you should always get the hardware ready first.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://jackyko1991.github.io/2019-09-13-Cluster-Setup-Part-2/pi-cluster.jpg" /><media:content medium="image" url="https://jackyko1991.github.io/2019-09-13-Cluster-Setup-Part-2/pi-cluster.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">HPC Cluster Setup Part 1 - The Basics</title><link href="https://jackyko1991.github.io/journal/Cluster-Setup-1.html" rel="alternate" type="text/html" title="HPC Cluster Setup Part 1 - The Basics" /><published>2019-09-12T00:00:00+00:00</published><updated>2019-09-12T00:00:00+00:00</updated><id>https://jackyko1991.github.io/journal/Cluster-Setup-1</id><content type="html" xml:base="https://jackyko1991.github.io/journal/Cluster-Setup-1.html"><![CDATA[<p>High performance computing (HPC) refers to the high speed calculations and data processing ability. A modern PC or even mobile devices could provide up to 5 billions calculations per CPU core per second, and a more powerful workstation could assemble more than 50 CPU cores and multiples GPU in a single chassis unit. However the computation power of a single PC is still limited, how could we boost up the calculation speed when we have multiple devices? The solution is the concept of HPC clusters.</p>

<h2 id="content">Content</h2>
<ul>
  <li><a href="#how-does-hpc-cluster-work?">How Does HPC Cluster Work?</a>
    <ul>
      <li><a href="#detailed-device-list-of-hpc-cluster">Detailed device list of HPC cluster</a></li>
    </ul>
  </li>
  <li><a href="#how-to-maximize-the-hpc-ability?">How to Maximize the HPC Ability?</a></li>
  <li><a href="#when-will-i-need-a-hpc-cluster-for-computational-radiology?">When will I Need a HPC cluster for Computational Radiology?</a></li>
  <li><a href="#selection-of-distributed-resources-management-software">Selection of Distributed Resources Management Software</a></li>
</ul>

<h2 id="how-does-hpc-cluster-work">How Does HPC Cluster Work?</h2>
<p>The HPC cluster is an assembly of one or more computational devices, which can be divided into three main components:</p>
<ul>
  <li>Nodes</li>
  <li>Network</li>
  <li>Storage</li>
</ul>

<p><img src="../assets/img/2019-09-12-Cluster-Setup-Part-1/how-hpc-works.jpg" alt="alt text" title="Main components of HPC cluster" /></p>

<p>The HPC architecture connects multiple computers via networks to form a cluster. In clustering we name the computers as “nodes”. Each node may carry specific functions including job scheduling and distribution, GPU computation, heterogeneous CPU architecture computations (ARM, FPGA nodes) and data storage. Even though individual devices may only carry very low computational ability, every node is playing an important role in terms of resource leveraging. The components operate seamless together to complete a diverse set of tasks.</p>

<h3 id="detailed-device-list-of-hpc-cluster">Detailed device list of HPC cluster</h3>
<p><img src="../assets/img/2019-09-12-Cluster-Setup-Part-1/HPCCluster.jpg" alt="alt text" title="HPC cluster" /></p>
<ul>
  <li>Headnode or login node, where users log in</li>
  <li>Specialized data transfer node</li>
  <li>Regular compute nodes (where majority of computations is run)</li>
  <li>“Fat” compute nodes that have at least 1TB of memory</li>
  <li>GPU nodes (on these nodes computations can be run both on CPU cores and on a Graphical Processing Unit)</li>
  <li>Switch and router to connect all nodes</li>
</ul>

<h2 id="how-to-maximize-the-hpc-ability">How to Maximize the HPC Ability?</h2>
<p>To maximize the power of HPC clusters, one may put every nodes in full loading whole time and keep each components keep pace with each others. The data storage nodes take responsibility of raw data ingestion and analyzed data output. To transfer data among storage nodes and computational nodes, a fast network and caching technique for data input/output is one of the keystones to boost up processing speed. To maintain such coordinated works, a bunch of software toolkits are developed to automate the process.</p>

<h2 id="when-will-i-need-a-hpc-cluster-for-computational-radiology">When will I Need a HPC cluster for Computational Radiology?</h2>
<p>Take a look at this <a href="https://www.reddit.com/r/MachineLearning/comments/6xzv3h/d_which_gpu_scheduler_are_you_using_in_your/">post</a>. Docker container is an easy to use tool for AI development, all environments are ready with single docker pull command. This is only the case when computational resources are readily available, however this is never a case comes to GPU computation. Imagine 20 PhD students in same department share a 8 card PC, this will eventually result in computer resources monopolization. The scheduling technique in HPC clusters could bring in a fair usage environment to every user of the shared devices.</p>

<h2 id="selection-of-distributed-resources-management-software">Selection of Distributed Resources Management Software</h2>
<p>There are a number of cluster resources management systems available under Linux:</p>
<ul>
  <li>Task scheduler:
    <ul>
      <li><a href="https://slurm.schedmd.com/overview.html">Slurm</a></li>
      <li><a href="https://help.ubuntu.com/community/TorquePbsHowto">Torque PBS</a></li>
      <li><a href="https://research.cs.wisc.edu/htcondor/">HTCondor (minihtcondor for single node cluster)</a></li>
    </ul>
  </li>
  <li>Container Solution:
    <ul>
      <li><a href="https://kubernetes.io/">Kubernetes</a></li>
      <li><a href="https://singularity.lbl.gov/">Singularity</a></li>
    </ul>
  </li>
  <li>and more…</li>
</ul>

<p><img src="../assets/img/2019-09-12-Cluster-Setup-Part-1/swarm+kubernetes.png" alt="alt text" title="Docker and Kubernetes" /></p>

<p>Each of the resource management system has it’s unique features. The combined usage of Kubernetes and Singularity with Docker provides flexible cluster orchestration as a container solution. What if I am only a small development team and wish to automate GPU scheduling? Slurm do support GPUs as the GRES (generic resource) and thus would be the preferable management tool for small cluster system. Slurm also has been supported by the most popular cloud services providers including AWS, Azure and GCP, thus provides high flexibility to mix private and public clusters.</p>

<p><img src="../assets/img/2019-09-12-Cluster-Setup-Part-1/pt2.jpg" alt="alt text" title="Slurm support in AWS" /></p>

<p>In the coming posts there will be hand on steps to setup a Slurm cluster.</p>

<h2 id="references">References</h2>
<ul>
  <li><a href="https://medium.com/@glmdev/building-a-raspberry-pi-cluster-784f0df9afbd">Building a Raspberry Pi Cluster</a></li>
  <li><a href="https://aws.amazon.com/blogs/compute/deploying-a-burstable-and-event-driven-hpc-cluster-on-aws-using-slurm-part-1/">Deploying a Burstable and Event-driven HPC Cluster on AWS Using SLURM, Part 1</a></li>
  <li><a href="https://aws.amazon.com/blogs/compute/deploying-a-burstable-and-event-driven-hpc-cluster-on-aws-using-slurm-part-2/">Deploying a Burstable and Event-driven HPC Cluster on AWS Using SLURM, Part 2</a></li>
  <li><a href="https://www.docker.com/products/orchestration">Run Swarm and Kubernetes Interchangeably</a></li>
  <li><a href="https://blog.docker.com/2018/05/integrating-kubernetes-docker-enterprise-edition-2-0-top-10-questions-docker-virtual-event/">Integrating Kubernetes with Docker Enterprise Edition 2.0 – Top 10 Questions from the Docker Virtual Event</a></li>
</ul>]]></content><author><name>Jacky Ko</name></author><category term="journal" /><category term="documentation" /><category term="clusters" /><category term="hpc" /><summary type="html"><![CDATA[High performance computing (HPC) refers to the high speed calculations and data processing ability. A modern PC or even mobile devices could provide up to 5 billions calculations per CPU core per second, and a more powerful workstation could assemble more than 50 CPU cores and multiples GPU in a single chassis unit. However the computation power of a single PC is still limited, how could we boost up the calculation speed when we have multiple devices? The solution is the concept of HPC clusters.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://jackyko1991.github.io/2019-09-12-Cluster-Setup-Part-1/slurm_overview.png" /><media:content medium="image" url="https://jackyko1991.github.io/2019-09-12-Cluster-Setup-Part-1/slurm_overview.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Blog Introduction</title><link href="https://jackyko1991.github.io/journal/Blog-Introduction.html" rel="alternate" type="text/html" title="Blog Introduction" /><published>2019-01-16T00:00:00+00:00</published><updated>2019-01-16T00:00:00+00:00</updated><id>https://jackyko1991.github.io/journal/Blog-Introduction</id><content type="html" xml:base="https://jackyko1991.github.io/journal/Blog-Introduction.html"><![CDATA[<p>Hi everyone! I’m Jacky and working as a software developer on medical images. By the time I issuing this post, I have been worked for 5 years in this area. It is very hard to newbies to enter this discipline as it includes both computer and medical knowledges. The blog’s aim is to deliver my experiences in this domain to shorten dummies learning period and lowering the entry difficulty.</p>

<p>So…let’s begin!!!</p>

<h2 id="what-is-computational-radiology">What is “Computational Radiology”?</h2>

<p>Computation radiology is to apply computer techniques and algorithms for radiographic diagnostics and treatments. The term includes two parts:</p>

<h3 id="radiology">Radiology</h3>
<p>Radiology is a medical branch focusing on the generation and interpretation of in-vivo human scans, which can be categorized through different imaging modalities:</p>
<ul>
  <li>X-ray (XR)</li>
  <li>Ultrasound (US)</li>
  <li>Computational Tomography (CT)</li>
  <li>Magnetic Resonance Imaging (MR)</li>
  <li>and more…</li>
</ul>

<h3 id="computation">Computation</h3>

<p>In the digital era, the above-mentioned images are mostly generated and stored in digital format. In traditional medical practices the scanned images are interpreted by professional clinicians. With the continual improvement of computation technology, Computer Assisted Diagnostics (CAD) has gained more and more attentions. Followings are brief list in this field:</p>

<ul>
  <li>Image Reconstruction
    <ul>
      <li>From raw signals to 3D medical images</li>
      <li>Signal processing</li>
    </ul>
  </li>
  <li>Quantitative Analysis
    <ul>
      <li>Image segmentation</li>
      <li>Landmark extraction</li>
    </ul>
  </li>
  <li>Image Visualization
    <ul>
      <li>2D orthogonal images</li>
      <li>3D rendering</li>
      <li>Spatial orientations</li>
      <li>Image registration</li>
    </ul>
  </li>
  <li>Functional Imaging
    <ul>
      <li>Cine-imaging (perfusion, angiogram)</li>
      <li>Functional MRI (BOLD, ASL)</li>
      <li>Diffusion Tensor Imaging</li>
    </ul>
  </li>
  <li>Computer Visions
    <ul>
      <li>Machine learning (supervised and unsupervised)</li>
      <li>Denoising</li>
      <li>Accelerated processing (multi-CPU/GPU)</li>
    </ul>
  </li>
  <li>And More…</li>
</ul>

<p>We will start by introducing basic tools and programming skills in coming posts.</p>]]></content><author><name>Jacky Ko</name></author><category term="journal" /><category term="documentation" /><summary type="html"><![CDATA[Hi everyone! I’m Jacky and working as a software developer on medical images. By the time I issuing this post, I have been worked for 5 years in this area. It is very hard to newbies to enter this discipline as it includes both computer and medical knowledges. The blog’s aim is to deliver my experiences in this domain to shorten dummies learning period and lowering the entry difficulty.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://jackyko1991.github.io/2019-01-16-Blog-Introduction/2019-01-16-Blog-Introduction.jpg" /><media:content medium="image" url="https://jackyko1991.github.io/2019-01-16-Blog-Introduction/2019-01-16-Blog-Introduction.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Welcome to Lagrange!</title><link href="https://jackyko1991.github.io/journal/welcome-to-lagrange.html" rel="alternate" type="text/html" title="Welcome to Lagrange!" /><published>2016-01-01T00:00:00+00:00</published><updated>2016-01-01T00:00:00+00:00</updated><id>https://jackyko1991.github.io/journal/welcome-to-lagrange</id><content type="html" xml:base="https://jackyko1991.github.io/journal/welcome-to-lagrange.html"><![CDATA[<p>Lagrange is a minimalist Jekyll theme. The purpose of this theme is to provide a simple, clean, content-focused blogging platform for your personal site or blog. Below you can find everything you need to get started.</p>

<h2 id="getting-started">Getting Started</h2>

<p><a href="https://jackyko1991.github.io/journal/getting-started.html">Getting Started</a>: getting started with installing Lagrange, whether you are completely new to using Jekyll, or simply just migrating to a new Jekyll theme.</p>

<h2 id="example-content">Example Content</h2>

<p><a href="https://jackyko1991.github.io/journal/text-formatting-examples.html">Text and Formatting</a></p>

<h2 id="questions">Questions?</h2>

<p>This theme is completely free and open source software. You may use it however you want, as it is distributed under the <a href="http://choosealicense.com/licenses/mit/">MIT License</a>. If you are having any problems, any questions or suggestions, feel free to <a href="https://twitter.com/intent/tweet?text=My%question%about%Lagrange%is:%&amp;via=paululele">tweet at me</a>, or <a href="https://github.com/lenpaul/lagrange/issues/new">file a GitHub issue</a>.</p>

<h2 id="more-jekyll">More Jekyll!</h2>

<h3 id="millennial">Millennial</h3>

<p>Millennial is a minimalist Jekyll blog theme that I built from scratch. The purpose of this theme is to provide a simple, clean, content-focused publishing platform for a publication or blog.</p>

<p>Feel free to check out <a href="https://lenpaul.github.io/Millennial/" target="_blank">the demo</a>, where you’ll also find instructions on <a href="https://lenpaul.github.io/Millennial/documentation/getting-started.html">how to use install</a> and use the theme.</p>

<h3 id="portfolio-jekyll-theme">Portfolio Jekyll Theme</h3>

<p>This is a Jekyll theme built using the <a href="http://devtipsstarterkit.com/">DevTips Starter Kit</a> as a foundation for starting, and following closely the amazing tutorial by <a href="https://www.youtube.com/watch?v=T6jKLsxbFg4&amp;list=PL0CB3OvPhDA_STygmp3sDenx3UpdOMk7P">Travis Neilson over at DevTips</a>. The purpose of this theme is to provide a clean and simple website for your portfolio. Emphasis is placed on your projects, which are shown front and center on the home page.</p>

<p>Everything that you will ever need to know about this Jekyll theme is included in <a href="https://github.com/LeNPaul/portfolio-jekyll-theme">the repository</a>, which you can also find in <a href="https://lenpaul.github.io/portfolio-jekyll-theme/">the demo site</a>.</p>

<h3 id="jekyll-starter-kit">Jekyll Starter Kit</h3>

<p>The Jekyll Starter Kit is a simple framework for starting your own Jekyll project using all of the best practices that I learned from building my other Jekyll themes.</p>

<p>Feel free to check out <a href="https://github.com/LeNPaul/jekyll-starter-kit" target="_blank">the GitHub repository</a>, where you’ll also find instructions on how to use install and use the theme.</p>]]></content><author><name>Paul Le</name></author><category term="journal" /><category term="sample" /><summary type="html"><![CDATA[Lagrange is a minimalist Jekyll theme. The purpose of this theme is to provide a simple, clean, content-focused blogging platform for your personal site or blog. Below you can find everything you need to get started.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://jackyko1991.github.io/mountains.jpg" /><media:content medium="image" url="https://jackyko1991.github.io/mountains.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Getting Started</title><link href="https://jackyko1991.github.io/journal/getting-started.html" rel="alternate" type="text/html" title="Getting Started" /><published>2015-10-10T00:00:00+00:00</published><updated>2015-10-10T00:00:00+00:00</updated><id>https://jackyko1991.github.io/journal/getting-started</id><content type="html" xml:base="https://jackyko1991.github.io/journal/getting-started.html"><![CDATA[<h1 id="lagrange">Lagrange</h1>

<p>Lagrange is a minimalist Jekyll theme for running a personal blog or site for free through <a href="https://pages.github.com/">Github Pages</a>, or on your own server. Everything that you will ever need to know about this Jekyll theme is included in the README below, which you can also find in <a href="https://lenpaul.github.io/Lagrange/">the demo site</a>.</p>

<p><img src="https://user-images.githubusercontent.com/8409329/32631384-17107870-c56e-11e7-932f-deeb7c12e4db.png" alt="alt text" title="Lagrange Demo Image" /></p>

<h2 id="notable-features">Notable features</h2>

<ul>
  <li>
    <p>Compatible with GitHub Pages.</p>
  </li>
  <li>
    <p>Support for Jekyll’s built-in Sass/SCSS preprocessor and data files for making customizing easier.</p>
  </li>
  <li>
    <p><a href="https://www.google.com/analytics/">Google Analytics</a> support.</p>
  </li>
  <li>
    <p>Commenting support powered by <a href="https://disqus.com/">Disqus</a>.</p>
  </li>
  <li>
    <p>Optimized for search engines.</p>
  </li>
  <li>
    <p>LaTeX support through <a href="https://www.mathjax.org/">MathJax</a>.</p>
  </li>
</ul>

<h2 id="table-of-contents">Table of Contents</h2>

<ol>
  <li><a href="#introduction">Introduction</a>
    <ol>
      <li><a href="#what-is-jekyll">What is Jekyll</a></li>
      <li><a href="#never-used-jekyll-before">Never Used Jeykll Before?</a></li>
    </ol>
  </li>
  <li><a href="#installation">Installation</a>
    <ol>
      <li><a href="#github-pages-installation">GitHub Pages Installation</a></li>
      <li><a href="#local-installation">Local Installation</a></li>
      <li><a href="#directory-structure">Directory Structure</a></li>
      <li><a href="#starting-from-scratch">Starting From Scratch</a></li>
    </ol>
  </li>
  <li><a href="#configuration">Configuration</a>
    <ol>
      <li><a href="#sample-posts">Sample Posts</a></li>
      <li><a href="#site-variables">Site Variables</a></li>
      <li><a href="#adding-menu-pages">Adding Menu Pages</a></li>
      <li><a href="#posts">Posts</a></li>
      <li><a href="#layouts">Layouts</a></li>
      <li><a href="#yaml-front-block-matter">YAML Front Block Matter</a></li>
    </ol>
  </li>
  <li><a href="#features">Features</a>
    <ol>
      <li><a href="#design-considerations">Design Considerations</a></li>
      <li><a href="#disqus">Disqus</a></li>
      <li><a href="#google-analytics">Google Analytics</a></li>
      <li><a href="#rss-feeds">RSS Feeds</a></li>
      <li><a href="#social-media-icons">Social Media Icons</a></li>
      <li><a href="#mathjax">MathJax</a></li>
      <li><a href="#syntax-highlighting">Syntax Highlighting</a></li>
      <li><a href="#markdown">Markdown</a></li>
    </ol>
  </li>
  <li><a href="#everything-else">Everything Else</a></li>
  <li><a href="#Contributing">Contributing</a></li>
  <li><a href="#questions">Questions?</a></li>
  <li><a href="#credits">Credits</a></li>
  <li><a href="#license">License</a></li>
</ol>

<h2 id="introduction">Introduction</h2>

<p>Lagrange is a Jekyll theme that was built to be 100% compatible with <a href="https://pages.github.com/">GitHub Pages</a>. If you are unfamiliar with GitHub Pages, you can check out <a href="https://help.github.com/categories/github-pages-basics/">their documentation</a> for more information. <a href="http://jmcglone.com/guides/github-pages/">Jonathan McGlone’s guide</a> on creating and hosting a personal site on GitHub is also a good resource.</p>

<h3 id="what-is-jekyll">What is Jekyll?</h3>

<p>Jekyll is a simple, blog-aware, static site generator for personal, project, or organization sites. Basically, Jekyll takes your page content along with template files and produces a complete website. For more information, visit the <a href="https://jekyllrb.com/docs/home/">official Jekyll site</a> for their documentation. Codecademy also offers a great course on <a href="https://www.codecademy.com/learn/deploy-a-website">how to deploy a Jekyll site</a> for complete beginners.</p>

<h3 id="never-used-jekyll-before">Never Used Jekyll Before?</h3>

<p>The beauty of hosting your website on GitHub is that you don’t have to actually have Jekyll installed on your computer. Everything can be done through the GitHub code editor, with minimal knowledge of how to use Jekyll or the command line. All you have to do is add your posts to the <code class="language-plaintext highlighter-rouge">_posts</code> directory and edit the <code class="language-plaintext highlighter-rouge">_config.yml</code> file to change the site settings. With some rudimentary knowledge of HTML and CSS, you can even modify the site to your liking. This can all be done through the GitHub code editor, which acts like a content management system (CMS).</p>

<h2 id="installation">Installation</h2>

<h3 id="github-pages-installation">GitHub Pages Installation</h3>

<p>To start using Jekyll right away with GitHub Pages, <a href="https://github.com/LeNPaul/Lagrange/fork">fork the Lagrange repository on GitHub</a>. From there, you can rename your repository to ‘USERNAME.github.io’, where ‘USERNAME’ is your GitHub username, and edit the <code class="language-plaintext highlighter-rouge">settings.yml</code> file in the <code class="language-plaintext highlighter-rouge">_data</code> folder to your liking. Ensure that you have a branch named <code class="language-plaintext highlighter-rouge">gh-pages</code>. Your website should be ready immediately at ‘http://USERNAME.github.io’. Note: if you are hosting several sites under the same GitHub username, then you will have to use <a href="https://help.github.com/articles/user-organization-and-project-pages/">Project Pages instead of User Pages</a> - just change the repository name to something other than ‘http://USERNAME.github.io’.</p>

<p>Head over to the <code class="language-plaintext highlighter-rouge">_posts</code> directory to view all the posts that are currently on the website, and to see examples of what post files generally look like. You can simply just duplicate the template post and start adding your own content.</p>

<h3 id="local-installation">Local Installation</h3>

<p>For a full local installation of Lagrange, <a href="https://github.com/LeNPaul/Lagrange/archive/gh-pages.zip">download your own copy of Lagrange</a> and unzip it into it’s own directory. From there, open up your favorite command line tool, enter <code class="language-plaintext highlighter-rouge">bundle install</code>, and then enter <code class="language-plaintext highlighter-rouge">jekyll serve</code>. Your site should be up and running locally at <a href="http://localhost:4000">http://localhost:4000</a>.</p>

<h3 id="directory-structure">Directory Structure</h3>

<p>If you are familiar with Jekyll, then the Lagrange directory structure shouldn’t be too difficult to navigate. The following some highlights of the differences you might notice between the default directory structure. More information on what these folders and files do can be found in the <a href="https://jekyllrb.com/docs/structure/">Jekyll documentation site</a>.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Lagrange/
├── _data                      <span class="c"># Data files</span>
|  └── settings.yml            <span class="c"># Theme settings and custom text</span>
├── _includes                  <span class="c"># Theme includes</span>
├── _layouts                   <span class="c"># Theme layouts (see below for details)</span>
├── _posts                     <span class="c"># Where all your posts will go</span>
├── assets                     <span class="c"># Style sheets and images are found here</span>
|  ├── css                     <span class="c"># Style sheets go here</span>
|  |  └── main.css             <span class="c"># Main CSS file</span>
|  |  └── syntax.css           <span class="c"># Style sheet for code syntax highlighting</span>
|  └── img                     <span class="c"># Images go here</span>
├── menu                       <span class="c"># Menu pages</span>
├── _config.yml                <span class="c"># Site build settings</span>
├── Gemfile                    <span class="c"># Ruby Gemfile for managing Jekyll plugins</span>
├── index.md                   <span class="c"># Home page</span>
├── LICENSE.md                 <span class="c"># License for this theme</span>
├── README.md                  <span class="c"># Includes all of the documentation for this theme</span>
└── rss-feed.xml               <span class="c"># Generates RSS 2.0 file which Jekyll points to</span>
</code></pre></div></div>

<h3 id="starting-from-scratch">Starting From Scratch</h3>

<p>To completely start from scratch, simply delete all the files in the <code class="language-plaintext highlighter-rouge">_posts</code>, <code class="language-plaintext highlighter-rouge">assets/img</code>, and <code class="language-plaintext highlighter-rouge">menu</code> folder, and add your own content. You may also replace the <code class="language-plaintext highlighter-rouge">README.md</code> file with your own README. Everything in the <code class="language-plaintext highlighter-rouge">_data</code> folder and <code class="language-plaintext highlighter-rouge">_config.yml</code> file can be edited to suit your needs. You may also change the <code class="language-plaintext highlighter-rouge">favicon.ico</code> file to your own favicon.</p>

<h2 id="configuration">Configuration</h2>

<h3 id="sample-posts">Sample Posts</h3>

<p>Visit the <a href="https://lenpaul.github.io/Lagrange/">the demo site</a> to find sample posts that show what different types of text formatting look like. You can find these posts in the <code class="language-plaintext highlighter-rouge">_posts</code> folder, which show what the best practices for setting up your own site are.</p>

<h3 id="site-variables">Site Variables</h3>

<p>To change site build settings, edit the <code class="language-plaintext highlighter-rouge">_config.yml</code> file found in the root of your repository, which you can tweak however you like. More information on configuration settings and plugins can be found on <a href="https://jekyllrb.com/docs/configuration/">the Jekyll documentation site</a>. This is also where you will be able to customize the title, description, and the author/owner of your site.</p>

<p>If you are hosting your site on GitHub Pages, then committing a change to the <code class="language-plaintext highlighter-rouge">_config.yml</code> file will force a rebuild of your site with Jekyll. Any changes made should be viewable soon after. If you are hosting your site locally, then you must run <code class="language-plaintext highlighter-rouge">jekyll serve</code> again for the changes to take place.</p>

<p>In the <code class="language-plaintext highlighter-rouge">settings.yml</code> file found in the <code class="language-plaintext highlighter-rouge">_data</code> folder, you will be able to customize your site settings, such as setting Disqus comments, Google Analytics, what shows up in your menu, and social media information.</p>

<h3 id="adding-menu-pages">Adding Menu Pages</h3>

<p>The menu pages are found in the <code class="language-plaintext highlighter-rouge">menu</code> folder in the root directory, and can be added to your menu in the <code class="language-plaintext highlighter-rouge">settings.yml</code> file.</p>

<h3 id="posts">Posts</h3>

<p>You will find example posts in your <code class="language-plaintext highlighter-rouge">_posts</code> directory. Go ahead and edit any post and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run <code class="language-plaintext highlighter-rouge">jekyll serve</code>, which launches a web server and auto-regenerates your site when a file is updated.</p>

<p>To add new posts, simply add a file in the <code class="language-plaintext highlighter-rouge">_posts</code> directory that follows the convention of <code class="language-plaintext highlighter-rouge">YYYY-MM-DD-name-of-post.md</code> and includes the necessary front matter. Take a look at any sample post to get an idea about how it works. If you already have a website built with Jekyll, simply copy over your posts to migrate to Lagrange.</p>

<h3 id="layouts">Layouts</h3>

<p>There are two main layout options that are included with Lagrange: post and page. Layouts are specified through the <a href="https://jekyllrb.com/docs/frontmatter/">YAML front block matter</a>. Any file that contains a YAML front block matter will be processed by Jekyll. For example:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>---
layout: post
title: "Example Post"
---
</code></pre></div></div>

<p>Examples of what posts looks like can be found in the <code class="language-plaintext highlighter-rouge">_posts</code> directory, which includes this post you are reading right now. Posts are the basic blog post layout, which includes a header image, post content, author name, date published, social media sharing links, and related posts.</p>

<p>Pages are essentially the post layout without any of the extra features of the posts layout. An example of what pages look like can be found at the <a href="https://lenpaul.github.io/Lagrange/menu/about.html">About</a> and <a href="https://lenpaul.github.io/Lagrange/menu/contact.html">Contacts</a>.</p>

<p>In addition to the two main layout options above, there are also custom layouts that have been created for the <a href="https://lenpaul.github.io/Lagrange/">home page</a> and the <a href="https://lenpaul.github.io/Lagrange/menu/writing.html">archives page</a>. These are simply just page layouts with some <a href="https://shopify.github.io/liquid/">Liquid template code</a>. Check out the <code class="language-plaintext highlighter-rouge">index.html</code> file in the root directory for what the code looks like.</p>

<h3 id="yaml-front-block-matter">YAML Front Block Matter</h3>

<p>The recommended YAML front block is:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>---
layout:
title:
author:
categories:
tags: []
image:
---
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">layout</code> specifies which layout to use, <code class="language-plaintext highlighter-rouge">title</code> is the page or post title, <code class="language-plaintext highlighter-rouge">categories</code> can be used to better organize your posts, <code class="language-plaintext highlighter-rouge">tags</code> are used when generating related posts based on the topic of the post, and <code class="language-plaintext highlighter-rouge">image</code> specifies which images to use. Have a look at some posts in the <code class="language-plaintext highlighter-rouge">_posts</code> directory to see how these variables are set.</p>

<h2 id="features">Features</h2>

<h3 id="design-considerations">Design Considerations</h3>

<p>Lagrange was designed to be a minimalist theme in order for the focus to remain on your content. For example, links are signified mainly through an underline text-decoration, in order to maximize the perceived affordance of clickability (I originally just wanted to make the links a darker shade of grey).</p>

<h3 id="disqus">Disqus</h3>

<p>Lagrange supports comments at the end of posts through <a href="https://disqus.com/">Disqus</a>. In order to activate Disqus commenting, set <code class="language-plaintext highlighter-rouge">disqus.comments</code> to true in the <code class="language-plaintext highlighter-rouge">_data/settings.yml</code> file. If you do not have a Disqus account already, you will have to set one up, and create a profile for your website. You will be given a <code class="language-plaintext highlighter-rouge">disqus_shortname</code> that will be used to generate the appropriate comments sections for your site. More information on <a href="http://www.perfectlyrandom.org/2014/06/29/adding-disqus-to-your-jekyll-powered-github-pages/">how to set up Disqus</a>.</p>

<h3 id="google-analytics">Google Analytics</h3>

<p>It is possible to track your site statistics through <a href="https://www.google.com/analytics/">Google Analytics</a>. Similar to Disqus, you will have to create an account for Google Analytics, and enter the correct Google ID for your site under <code class="language-plaintext highlighter-rouge">google-ID</code> in the <code class="language-plaintext highlighter-rouge">settings.yml</code> file. More information on <a href="https://michaelsoolee.com/google-analytics-jekyll/">how to set up Google Analytics</a>.</p>

<h3 id="rss-feeds">RSS Feeds</h3>

<p>Atom is supported by default through <a href="https://github.com/jekyll/jekyll-feed">jekyll-feed</a>. With jekyll-feed, you can set configuration variables such as ‘title’, ‘description’, and ‘author’, in the <code class="language-plaintext highlighter-rouge">_config.yml</code> file.</p>

<p>RSS 2.0 is also supported through <a href="http://www.rssboard.org/rss-autodiscovery">RSS auto-discovery</a>. The <code class="language-plaintext highlighter-rouge">rss-feed.xml</code> file (based on the template found at <a href="https://github.com/snaptortoise/jekyll-rss-feeds">jekyll-rss-feeds</a>) that the feed path points to when using RSS 2.0 is automatically generated based on the appropriate configuration variables found in <code class="language-plaintext highlighter-rouge">_data/settings.yml</code>.</p>

<p>To use RSS 2.0, ensure the following is done:</p>

<ul>
  <li>
    <p>Uncomment the last two lines in the <code class="language-plaintext highlighter-rouge">_config.yml</code> file.</p>
  </li>
  <li>
    <p>In <code class="language-plaintext highlighter-rouge">_data/settings.yml</code>, under ‘social’, comment out the rss-square that points to <code class="language-plaintext highlighter-rouge">feed.xml</code>, and uncomment the rss-square that points to <code class="language-plaintext highlighter-rouge">rss-feed.xml</code>.</p>
  </li>
  <li>
    <p>In <code class="language-plaintext highlighter-rouge">_includes/head.html</code>, comment out <code class="language-plaintext highlighter-rouge">&lt;link type="application/atom+xml" rel="alternate" href="https://jackyko1991.github.io/feed.xml" title="jackyko1991.github.io" /&gt;</code> and uncomment the line under the RSS 2.0 comment.</p>
  </li>
</ul>

<h3 id="social-media-icons">Social Media Icons</h3>

<p>All social media icons are courtesy of <a href="http://fontawesome.io/">Font Awesome</a>. You can change which icons appear, as well as the account that they link to, in the <code class="language-plaintext highlighter-rouge">settings.yml</code> file in the <code class="language-plaintext highlighter-rouge">_data</code> folder.</p>

<h3 id="mathjax">MathJax</h3>

<p>Lagrange comes out of the box with <a href="https://www.mathjax.org/">MathJax</a>, which allows you to display mathematical equations in your posts through the use of <a href="http://www.andy-roberts.net/writing/latex/mathematics_1">LaTeX</a>.</p>

<h3 id="syntax-highlighting">Syntax Highlighting</h3>

<p>Lagrange provides syntax highlighting through <a href="https://help.github.com/articles/creating-and-highlighting-code-blocks/">fenced code blocks</a>. Syntax highlighting allows you to display source code in different colors and fonts depending on what programming language is being displayed. You can find the full list of supported programming languages <a href="https://github.com/jneen/rouge/wiki/List-of-supported-languages-and-lexers">here</a>. Another option is to embed your code through <a href="https://en.support.wordpress.com/gist/">Gist</a>.</p>

<h3 id="markdown">Markdown</h3>

<p>As always, Jekyll offers support for GitHub Flavored Markdown, which allows you to format your posts using the <a href="https://guides.github.com/features/mastering-markdown/">Markdown syntax</a>. Examples of these text formatting features can be seen below. You can find this post in the <code class="language-plaintext highlighter-rouge">_posts</code> directory as well as the <code class="language-plaintext highlighter-rouge">README.md</code> file.</p>

<h2 id="everything-else">Everything Else</h2>

<p>Check out the <a href="http://jekyllrb.com/docs/home">Jekyll docs</a> for more info on how to get the most out of Jekyll. File all bugs/feature requests at <a href="https://github.com/jekyll/jekyll">Jekyll’s GitHub repo</a>. If you have questions, you can ask them on <a href="https://talk.jekyllrb.com/">Jekyll Talk</a>.</p>

<h2 id="contributing">Contributing</h2>

<p>If you would like to make a feature request, or report a bug or typo in the documentation, then please <a href="https://github.com/LeNPaul/Lagrange/issues/new">submit a GitHub issue</a>. If you would like to make a contribution, then feel free to <a href="https://help.github.com/articles/about-pull-requests/">submit a pull request</a> - as a bonus, I will credit all contributors below! If this is your first pull request, it may be helpful to read up on the <a href="https://guides.github.com/introduction/flow/">GitHub Flow</a> first.</p>

<p>Lagrange has been designed as a base for users to customize and fit to their own unique needs. Please keep this in mind when requesting features and/or submitting pull requests. Some examples of changes that I would love to see are things that would make the site easier to use, or better ways of doing things. Please avoid changes that do not benefit the majority of users.</p>

<h2 id="questions">Questions?</h2>

<p>This theme is completely free and open source software. You may use it however you want, as it is distributed under the <a href="http://choosealicense.com/licenses/mit/">MIT License</a>. If you are having any problems, any questions or suggestions, feel free to <a href="https://twitter.com/intent/tweet?text=My%question%about%Lagrange%is:%&amp;via=paululele">tweet at me</a>, or <a href="https://github.com/lenpaul/lagrange/issues/new">file a GitHub issue</a>.</p>

<h2 id="credits">Credits</h2>

<h3 id="creator">Creator</h3>

<h4 id="paul-le">Paul Le</h4>

<ul>
  <li>
    <p><a href="http://lenpaul.com">www.lenpaul.com</a></p>
  </li>
  <li>
    <p><a href="https://twitter.com/paululele">Twitter</a></p>
  </li>
  <li>
    <p><a href="https://github.com/LeNPaul">GitHub</a></p>
  </li>
</ul>

<h3 id="contributors">Contributors</h3>

<ul>
  <li>
    <p><a href="https://github.com/nikolalukovic">nikolalukovic</a></p>
  </li>
  <li>
    <p><a href="https://github.com/gmemstr">gmemstr</a></p>
  </li>
  <li>
    <p><a href="https://github.com/lynn9388">lynn9388</a></p>
  </li>
  <li>
    <p><a href="https://github.com/robqiao">robqiao</a></p>
  </li>
  <li>
    <p><a href="https://github.com/Mauladen">Mauladen</a></p>
  </li>
  <li>
    <p><a href="https://github.com/dhanus">dhanus</a></p>
  </li>
  <li>
    <p><a href="https://github.com/mlewand">mlewand</a></p>
  </li>
  <li>
    <p><a href="https://github.com/Hguimaraes">Hguimaraes</a></p>
  </li>
  <li>
    <p><a href="https://github.com/ilhamadun">ilhamadun</a></p>
  </li>
</ul>

<h3 id="icons--demo-images">Icons + Demo Images</h3>

<ul>
  <li>
    <p><a href="https://deathtothestockphoto.com/">Death to Stock</a></p>
  </li>
  <li>
    <p><a href="http://fontawesome.io/">Font Awesome</a></p>
  </li>
</ul>

<h3 id="other">Other</h3>

<ul>
  <li>
    <p><a href="https://jekyllrb.com/">Jekyll</a></p>
  </li>
  <li>
    <p><a href="https://www.freecodecamp.org">Free Code Camp</a></p>
  </li>
  <li>
    <p><a href="https://www.khanacademy.org/">Khan Academy</a></p>
  </li>
</ul>

<h2 id="license">License</h2>

<p>Open sourced under the <a href="https://github.com/LeNPaul/Lagrange/blob/gh-pages/LICENSE.md">MIT license</a>.</p>]]></content><author><name>Paul Le</name></author><category term="journal" /><category term="sample" /><summary type="html"><![CDATA[Lagrange]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://jackyko1991.github.io/forest.jpg" /><media:content medium="image" url="https://jackyko1991.github.io/forest.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Text Formatting Examples</title><link href="https://jackyko1991.github.io/journal/text-formatting-examples.html" rel="alternate" type="text/html" title="Text Formatting Examples" /><published>2014-01-01T00:00:00+00:00</published><updated>2014-01-01T00:00:00+00:00</updated><id>https://jackyko1991.github.io/journal/text-formatting-examples</id><content type="html" xml:base="https://jackyko1991.github.io/journal/text-formatting-examples.html"><![CDATA[<h1 id="markdown-support">Markdown Support</h1>

<p>As always, Jekyll offers support for GitHub Flavored Markdown, which allows you to format your posts using the <a href="https://guides.github.com/features/mastering-markdown/">Markdown syntax</a>. Examples of these text formatting features can be seen below. You can find this post in the <code class="language-plaintext highlighter-rouge">_posts</code> directory.</p>

<h2 id="basic-formatting">Basic Formatting</h2>

<p>With Markdown, it is possible to emphasize words by making them <em>italicized</em>, using <em>astericks</em> or <em>underscores</em>, or making them <strong>bold</strong>, using <strong>double astericks</strong> or <strong>double underscores</strong>. Of course, you can combine those two formats, with both <em><strong>bold and italicized</strong></em> text, using any combination of the above syntax. You can also add a strikethrough to text using a <del>double tilde</del>.</p>

<h2 id="paragraphs">Paragraphs</h2>

<p>This is what a paragraph looks like. For the purpose of demonstration, the rest of this paragraph and the next paragraph after will mean absolutely nothing. Proin eget nibh a massa vestibulum pretium. Suspendisse eu nisl a ante aliquet bibendum quis a nunc. Praesent varius interdum vehicula. Aenean risus libero, placerat at vestibulum eget, ultricies eu enim. Praesent nulla tortor, malesuada adipiscing adipiscing sollicitudin, adipiscing eget est. Praesent nulla tortor, malesuada adipiscing adipiscing sollicitudin, adipiscing eget est.</p>

<p>Proin eget nibh a massa vestibulum pretium. Suspendisse eu nisl a ante aliquet bibendum quis a nunc. Mauris lobortis nulla et felis ullamcorper bibendum. Phasellus et hendrerit mauris. Proin eget nibh a massa vestibulum pretium. Suspendisse eu nisl a ante aliquet bibendum quis a nunc. Praesent varius interdum vehicula. Aenean risus libero, placerat at vestibulum eget, ultricies eu enim. Praesent nulla tortor, malesuada adipiscing adipiscing sollicitudin, adipiscing eget est.</p>

<h2 id="headings">Headings</h2>

<p>Sometimes it is useful to have different levels of headings to structure your documents. Start lines with <code class="language-plaintext highlighter-rouge">#</code> to create headings. Multiple <code class="language-plaintext highlighter-rouge">##</code> in a row denote smaller heading size. The following demonstrate the full range of heading sizes:</p>

<h1 id="heading-one-h1">Heading One (h1)</h1>

<h2 id="heading-two-h2">Heading Two (h2)</h2>

<h3 id="heading-three-h3">Heading Three (h3)</h3>

<h4 id="heading-four-h4">Heading Four (h4)</h4>

<h5 id="heading-five-h5">Heading Five (h5)</h5>

<h6 id="heading-six-h6">Heading Six (h6)</h6>

<h2 id="links">Links</h2>

<p>You can create an inline link by wrapping link text in square brackets <code class="language-plaintext highlighter-rouge">[ ]</code>, and then wrapping the URL in parentheses <code class="language-plaintext highlighter-rouge">( )</code>. For example, it is very easy to <a href="http://google.com">link to Google!</a>.</p>

<h2 id="blockquotes">Blockquotes</h2>

<p>Blockquotes are useful for denoting quotes, or highlighting a large block of text. Single line blockquote:</p>

<blockquote>
  <p>This quote will change your life.</p>
</blockquote>

<p>Multi line blockquote with a cite reference:</p>

<blockquote>
  <p>People think focus means saying yes to the thing you’ve got to focus on. But that’s not what it means at all. It means saying no to the hundred other good ideas that there are. You have to pick carefully. I’m actually as proud of the things we haven’t done as the things I have done. Innovation is saying no to 1,000 things.</p>
</blockquote>

<h2 id="code-and-syntax-highlighting">Code and Syntax Highlighting</h2>

<p>Code blocks are part of the Markdown spec, but syntax highlighting isn’t. However, many renderers - like GitHub or most Jekyll themes - support syntax highlighting. Which languages are supported and how those language names should be written will vary from renderer to renderer. You can find the full list of supported programming languages <a href="https://github.com/jneen/rouge/wiki/List-of-supported-languages-and-lexers">here</a>. Also, it is possible to do <code class="language-plaintext highlighter-rouge">inline code blocks</code>, by wrapping the text in ` ` ` quotations.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>No language indicated, so no syntax highlighting.
</code></pre></div></div>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">print_hi</span><span class="p">(</span><span class="nb">name</span><span class="p">)</span>
  <span class="nb">puts</span> <span class="s2">"Hi, </span><span class="si">#{</span><span class="nb">name</span><span class="si">}</span><span class="s2">"</span>
<span class="k">end</span>
<span class="n">print_hi</span><span class="p">(</span><span class="s1">'Tom'</span><span class="p">)</span>
<span class="c1">#=&gt; prints 'Hi, Tom' to STDOUT.</span>
</code></pre></div></div>

<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="c1">// Example can be run directly in your JavaScript console</span>

<span class="c1">// Create a function that takes two arguments and returns the sum of those arguments</span>
<span class="kd">var</span> <span class="nx">adder</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Function</span><span class="p">(</span><span class="dl">"</span><span class="s2">a</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">b</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">return a + b</span><span class="dl">"</span><span class="p">);</span>

<span class="c1">// Call the function</span>
<span class="nx">adder</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">6</span><span class="p">);</span>
<span class="c1">// &gt; 8</span></code></pre></figure>

<p>Another option is to embed your code through <a href="https://en.support.wordpress.com/gist/">Gist</a>.</p>

<h2 id="images">Images</h2>

<p>To add an image, use <code class="language-plaintext highlighter-rouge">![alt text](&lt;Image url&gt; "Image meta title")</code>:</p>

<p><img src="http://noirve.com/wp-content/uploads/2013/10/DTTSP_Coffee.jpg" alt="alt text" title="Example" /></p>

<h2 id="unordered-and-numbered-lists">Unordered and Numbered Lists</h2>

<p>You can make an unordered and nested list by preceding one or more lines of text with <code class="language-plaintext highlighter-rouge">-</code>, <code class="language-plaintext highlighter-rouge">*</code>, or <code class="language-plaintext highlighter-rouge">+</code>, and indenting sublists. The following lists show the full range of possible list formats.</p>

<ul>
  <li>List item one
    <ul>
      <li>List item one
        <ul>
          <li>List item one</li>
          <li>List item two</li>
          <li>List item three</li>
          <li>List item four</li>
        </ul>
      </li>
      <li>List item two</li>
      <li>List item three</li>
      <li>List item four</li>
    </ul>
  </li>
  <li>List item two</li>
  <li>List item three</li>
  <li>List item four</li>
</ul>

<p>Numbered lists are made by using numbers instead of bullet points.</p>

<ol>
  <li>List item one
    <ol>
      <li>List item one
        <ol>
          <li>List item one</li>
          <li>List item two</li>
          <li>List item three</li>
          <li>List item four</li>
        </ol>
      </li>
      <li>List item two</li>
      <li>List item three</li>
      <li>List item four</li>
    </ol>
  </li>
  <li>List item two</li>
  <li>List item three</li>
  <li>List item four</li>
</ol>

<h2 id="mathjax-example">MathJax Example</h2>

<p>The <a href="https://en.wikipedia.org/wiki/Schr%C3%B6dinger_equation">Schrödinger equation</a> is a partial differential equation that describes how the quantum state of a quantum system changes with time:</p>

\[i\hbar\frac{\partial}{\partial t} \Psi(\mathbf{r},t) = \left [ \frac{-\hbar^2}{2\mu}\nabla^2 + V(\mathbf{r},t)\right ] \Psi(\mathbf{r},t)\]

<p><a href="https://en.wikipedia.org/wiki/Joseph-Louis_Millennial">Joseph-Louis Millennial</a> was an Italian mathematician and astronomer who was responsible for the formulation of Lagrangian mechanics, which is a reformulation of Newtonian mechanics.</p>

\[\frac{\mathrm{d}}{\mathrm{d}t} \left ( \frac {\partial  L}{\partial \dot{q}_j} \right ) =  \frac {\partial L}{\partial q_j}\]

<h2 id="tables">Tables</h2>

<table>
  <thead>
    <tr>
      <th>Title 1</th>
      <th style="text-align: center">Title 2</th>
      <th style="text-align: left">Title 3</th>
      <th style="text-align: right">Title 4</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>lorem</td>
      <td style="text-align: center">lorem ipsum</td>
      <td style="text-align: left">lorem ipsum dolor</td>
      <td style="text-align: right">lorem ipsum dolor sit</td>
    </tr>
    <tr>
      <td>lorem ipsum dolor sit</td>
      <td style="text-align: center">lorem ipsum dolor sit</td>
      <td style="text-align: left">lorem ipsum dolor sit</td>
      <td style="text-align: right">lorem ipsum dolor sit</td>
    </tr>
    <tr>
      <td>lorem ipsum dolor sit</td>
      <td style="text-align: center">lorem ipsum dolor sit</td>
      <td style="text-align: left">lorem ipsum dolor sit</td>
      <td style="text-align: right">lorem ipsum dolor sit</td>
    </tr>
    <tr>
      <td>lorem ipsum dolor sit</td>
      <td style="text-align: center">lorem ipsum dolor sit</td>
      <td style="text-align: left">lorem ipsum dolor sit</td>
      <td style="text-align: right">lorem ipsum dolor sit</td>
    </tr>
  </tbody>
</table>

<h2 id="embedding">Embedding</h2>

<p>Plenty of social media sites offer the option of embedding certain parts of their site on your own site, such as YouTube and Twitter:</p>

<iframe width="560" height="315" src="https://www.youtube.com/embed/mthtn1X4eUY" frameborder="0" allowfullscreen=""></iframe>

<p><a class="twitter-grid" data-partner="tweetdeck" href="https://twitter.com/paululele/timelines/755079130027352064">New Collection</a> <script async="" src="//platform.twitter.com/widgets.js" charset="utf-8"></script></p>

<h2 id="inline-html-elements">Inline HTML elements</h2>

<p>HTML defines a long list of available inline tags, which you can mix with Markdown if you like. A complete list of which can be found on the <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element">Mozilla Developer Network</a>.</p>

<h2 id="horizontal-rule">Horizontal Rule</h2>

<p>Can be created by having three or more hyphens <code class="language-plaintext highlighter-rouge">---</code>, asterisks <code class="language-plaintext highlighter-rouge">***</code>, or underscores <code class="language-plaintext highlighter-rouge">___</code>:</p>

<hr />

<h2 id="useful-resources">Useful Resources</h2>

<p>More information on Markdown can be found at the following links:</p>

<ul>
  <li><a href="https://github.com/adam-p/markdown-here/wiki/Markdown-Here-Cheatsheet#code">Markdown Here Cheatsheet</a></li>
  <li><a href="http://www.unexpected-vortices.com/sw/rippledoc/quick-markdown-example.html">Quick Markdown Example</a></li>
  <li><a href="https://daringfireball.net/projects/markdown/basics">Markdown Basics</a></li>
  <li><a href="https://github.github.com/gfm/">GitHub Flavoured Markdown Spec</a></li>
  <li><a href="https://help.github.com/articles/basic-writing-and-formatting-syntax/#lists">Basic writing and formatting syntax</a></li>
</ul>]]></content><author><name>Paul Le</name></author><category term="journal" /><category term="sample" /><summary type="html"><![CDATA[Markdown Support]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://jackyko1991.github.io/cards.jpg" /><media:content medium="image" url="https://jackyko1991.github.io/cards.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>