<jupyter_start><jupyter_text>2.4 External ToolsThe following section demonstrates how to use the **signac** command line interface (CLI) in conjunction with other tools.<jupyter_code>%%bash
signac --help<jupyter_output><empty_output><jupyter_text>To interact with a project on the command line, the current working directory needs to be within or below the project root directory.Let's start by reseting the designated project root directory for this section of the tutorial.<jupyter_code>% pwd
% rm -rf projects/tutorial/cli
% mkdir -p projects/tutorial/cli
% cp idg projects/tutorial/cli<jupyter_output><empty_output><jupyter_text>Next we switch the current working directory to the project root directory.<jupyter_code>% cd projects/tutorial/cli<jupyter_output><empty_output><jupyter_text>Then we initialize the project.<jupyter_code>%%bash
signac init TutorialCLIProject<jupyter_output><empty_output><jupyter_text>We can verify the project configuration.<jupyter_code>%%bash
signac project
signac project --workspace<jupyter_output><empty_output><jupyter_text>We access the job handle by providing the state point on the command line in JSON format.<jupyter_code>%%bash
signac job '{"kT": 1.0, "p": 1.0, "N": 1000}'<jupyter_output><empty_output><jupyter_text>The statepoints could also be read from STDIN, e.g., by reading it from a file.Let's create a statepoints file with three statepoints:<jupyter_code>%%bash
echo '{"kT": 1.0, "p": 0.1, "N": 1000}' > statepoints.txt
echo '{"kT": 1.0, "p": 1.0, "N": 1000}' >> statepoints.txt
echo '{"kT": 1.0, "p": 10.0, "N": 1000}' >> statepoints.txt

cat statepoints.txt<jupyter_output><empty_output><jupyter_text>We can pipe the content of this file into the **signac** CLI to get the corresponding *job id*.<jupyter_code>%%bash
head -n 1 statepoints.txt | signac job<jupyter_output><empty_output><jupyter_text>Instead of the *job id*, we can directly obtain the path to the *job workspace*.<jupyter_code>%%bash
head -n 1 statepoints.txt | signac job --workspace<jupyter_output><empty_output><jupyter_text>That's specifically useful in conjunction with external tools.Let's pretend that we need to use a program called `idg` to calculate the ideal gas equation.The `idg` program will calculate the volume of an ideal gas given the input parameters *p*, *kT* and *N*, just like in the previous sections.<jupyter_code>%%bash
./idg -p 1.0 -N 1000 --kT 1.0<jupyter_output><empty_output><jupyter_text>We can store the result in a file based on the input arguments using the `-cw` argument, short for ``--create --workspace``, which returns the workspace path and creates it if necessary.<jupyter_code>%%bash
./idg -p 1.0 --kT 1.0 -N 1000 > $(signac job -cw '{"p": 1.0, "kT": 1.0, "N": 1000}')/V.txt<jupyter_output><empty_output><jupyter_text>Obviously, we wouldn't write these commands all manually, but use a script instead.<jupyter_code>import signac
import json
project = signac.get_project()
for p in 0.1, 1.0, 10.0:
    job = project.open_job({'N': 1000, 'p': p, 'kT': 1.0})
    cmd = './idg -p {p} --kT {kT} -N {N}'.format(**job.statepoint())
    cmd += " > $(signac job -cw '{}')/V.txt".format(json.dumps(job.statepoint()))
    print(cmd)<jupyter_output><empty_output><jupyter_text>We can then execute this script...<jupyter_code>%%bash
./idg -p 0.1 --kT 1.0 -N 1000 > $(signac job -cw '{"kT": 1.0, "p": 0.1, "N": 1000}')/V.txt
./idg -p 1.0 --kT 1.0 -N 1000 > $(signac job -cw '{"kT": 1.0, "p": 1.0, "N": 1000}')/V.txt
./idg -p 10.0 --kT 1.0 -N 1000 > $(signac job -cw '{"kT": 1.0, "p": 10.0, "N": 1000}')/V.txt<jupyter_output><empty_output><jupyter_text>... and examine the results.<jupyter_code>% cat `signac project -w`/*/V.txt<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1448220064724919, 'fraction_numerical': 0.03344120819848975, 'mean_word_length': 5.191986644407345, 'pattern_counts': {'":': 24, '<': 57, '<?xml version=': 0, '>': 67, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '14', 'dir': 'jupyter-structured-clean-dedup', 'id': '293899', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 1434, 'n_tokens_neox': 1312, 'n_words': 418, 'path': 'notebooks/signac_204_External_Tools.ipynb', 'repo_name': 'phmalek/signac-examples', 'size': '3708'}