From f2992d17cc6e29175ef41ea58d4f77fc6c431a30 Mon Sep 17 00:00:00 2001 From: Adrian Henle Date: Sat, 12 Jun 2021 10:38:14 -0700 Subject: [PATCH] set_paths (#85) --- Project.toml | 6 +++--- docs/src/globals.md | 15 +++++++++++++++ src/Xtals.jl | 10 ++++++---- src/misc.jl | 29 +++++++++++++++++++++++++++++ test/paths.jl | 15 ++++++++++----- 5 files changed, 63 insertions(+), 12 deletions(-) diff --git a/Project.toml b/Project.toml index ad91fa0..7aaad7a 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Xtals" uuid = "ede5f01d-793e-4c47-9885-c447d1f18d6d" authors = ["SimonEnsemble "] -version = "0.3.0" +version = "0.3.1" [deps] CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" @@ -17,10 +17,10 @@ PyCall = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0" UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" [compat] -JLD2 = "^0.4.9" -FIGlet = "^0.2.1" CSV = "^0.8.0" DataFrames = "^0.22.1" +FIGlet = "^0.2.1" +JLD2 = "^0.4.9" LightGraphs = "^1.3.0" MetaGraphs = "^0.6.6" PyCall = "^1.92" diff --git a/docs/src/globals.md b/docs/src/globals.md index ac88249..b8692a8 100644 --- a/docs/src/globals.md +++ b/docs/src/globals.md @@ -8,7 +8,22 @@ In `Xtals.jl`, global variables are stored in a dictionary called `rc`. The ent - `rc[:covalent_radii]` : a dictionary which maps atomic species to their covalent radii in Å - `rc[:paths]` : a dictionary of paths to directories to search for input data +## Paths + The `rc[:paths]` dictionary holds the following: - `rc[:paths][:crystals]` : the path to find crystallographic files (`.cif`, `.cssr`) to read in - `rc[:paths][:data]` : not directly used by `Xtals.jl`, but important for other packages which use `Xtals`, e.g. [PorousMaterials.jl](https://simonensemble.github.io/PorousMaterials.jl/dev/) + +When `Xtals` is first loaded, the paths are set based on the present working directory. `Xtals` expects to find a folder named `data` in the working directory, and assumes that crystallographic data will be present in `data/crystals`. To change the location of the crystal inputs, either set `rc[:paths][:crystals]` directly, or use `set_paths`: + +```julia +rc[:paths][:crystals] = "other_crystals" # crystals are now loaded from "other_crystals" +set_paths("other_data") # crystals are now loaded from "other_data/crystals" +``` + +# Docs + +```@docs +set_paths +``` diff --git a/src/Xtals.jl b/src/Xtals.jl index d297933..167a41c 100644 --- a/src/Xtals.jl +++ b/src/Xtals.jl @@ -32,9 +32,11 @@ include("pydeps.jl") function __init__() # load Python dependencies init_pydeps() - # sets paths to data and crystals relative to pwd() at import - rc[:paths][:data] = joinpath(pwd(), "data") - rc[:paths][:crystals] = joinpath(rc[:paths][:data], "crystals") + # create path entries in global dictionary + rc[:paths][:crystals] = "" + rc[:paths][:data] = "" + # set paths to data and crystals relative to pwd() at import + set_paths(joinpath(pwd(), "data")) end @@ -52,7 +54,7 @@ export nearest_image!, distance, overlap, remove_duplicates, pairwise_distances, # misc.jl - read_xyz, write_xyz, read_mol, write_mol2, assert_P1_symmetry, + read_xyz, write_xyz, read_mol, write_mol2, assert_P1_symmetry, set_paths, # crystal.jl Crystal, strip_numbers_from_atom_labels!, assign_charges, chemical_formula, molecular_weight, diff --git a/src/misc.jl b/src/misc.jl index be593da..282839f 100644 --- a/src/misc.jl +++ b/src/misc.jl @@ -154,3 +154,32 @@ function write_mol2(xtal::Crystal; filename::String="") # flush the buffer close(f) end + + +""" + `set_paths("path_to_data", print_paths=true)` + +Sets all paths in `rc[:paths]` relative to `path_to_data`. Paths follow the standard format of +`rc[:paths][:foo] = "path_to_data/foo"`, except for `rc[:paths][:data]` which is `"path_to_data"`. +Warnings are issued if any chosen paths are not valid folders. +# Arguments +- `path_to_data::String` : an absolute or relative path to use as the root of the data folder tree. Defaults to present working directory. +- `print_paths::Bool` : Optional. If `true`, prints contents of `rc[:paths]` to console. Defaults to `false`. +- `no_warn::Bool` : Optional. Set `true` to suppress invalid path warnings. Default to `false`. +""" +function set_paths(path_to_data::String=pwd(); print_paths::Bool=false, no_warn::Bool=false) + for (key, path) ∈ rc[:paths] # set all relative paths + rc[:paths][key] = joinpath(path_to_data, String(key)) + end + rc[:paths][:data] = path_to_data # correct data root path + if print_paths + @info rc[:paths] + end + if !no_warn + for (key, path) ∈ rc[:paths] + if !isdir(path) + @warn "$key path directory not found" path + end + end + end +end diff --git a/test/paths.jl b/test/paths.jl index 48b045a..28c0def 100644 --- a/test/paths.jl +++ b/test/paths.jl @@ -5,10 +5,15 @@ using Test @testset "Path Tests" begin @test rc[:atomic_masses][:He] == 4.0026 - oldpath = rc[:paths][:crystals] - rc[:paths][:crystals] = joinpath(pwd(), "other_data", "other_crystals") - Crystal("other_SBMOF-1.cif") - rc[:paths][:crystals] = oldpath - @test true # if made it this far :) + oldpath = rc[:paths][:data] + newpath = joinpath(pwd(), "other_data") + set_paths(newpath, print_paths=true) + @test rc[:paths][:crystals] == joinpath(newpath, "crystals") + rc[:paths][:crystals] = joinpath(newpath, "other_crystals") + xtal = Crystal("SBMOF-1.cif") + @test xtal.atoms.n == 120 + rc[:paths][:foo] = "bar" + set_paths(oldpath) + @test rc[:paths][:foo] == joinpath(oldpath, "foo") end end