This example demonstrates creating a new Materials Commons project from a Jupyter notebook. To try running it locally, download the notebook from here.
To install the necessary dependencies (requires Python 3):
pip install materials-commons-cli
Notes:
# Login information (Edit here or be prompted by the next cell)
email = None
mcurl = "https://materialscommons.org/api"
# Construct a Materials Commons client
from materials_commons.cli.user_config import make_client_and_login_if_necessary
if email is None:
print("Account (email):")
email = input()
client = make_client_and_login_if_necessary(email=email, mcurl=mcurl)
Account (email): user@domain.edu Login to: user@domain.edu https://materialscommons.org/api password: ········ Added APIKey for user@domain.edu at https://materialscommons.org/api to /Users/username/.materialscommons/config.json
import materials_commons.api as mcapi
# Project name
name = "ExampleProjectFromJupyter"
# Projct summary - short description to show in tables
summary = "Example project created via Jupyter notebook"
# Project description - describes the project, may be more detailed
description = "This project was created as an example of how to create "\
"and use Materials Commons projects from within a Jupyter notebook"
# Create a new project (or return existing one with same name)
request = mcapi.CreateProjectRequest(description=description, summary=summary)
remote_mc_proj = client.create_project(name, request)
print(str(remote_mc_proj))
print("URL:", client.base_url)
print("Project ID:", remote_mc_proj.id)
print("Project name:", remote_mc_proj.name)
<materials_commons.api.models.Project object at 0x7fe991784940> URL: https://materialscommons.org/api Project ID: 657 Project name: ExampleProjectFromJupyter
"Cloning" a project creates a local directory which is used as a place to upload and download project files. There are three construction options:
import os
import pathlib
import shutil
from materials_commons.cli.cloned_project import ClonedProject
This example clones the project using a temporary directory. Downloaded files will be eventually be cleaned up by the system when the ClonedObject
instance is no longer in use.
cloned_mc_proj = ClonedProject(email=email, mcurl=mcurl, proj_id=remote_mc_proj.id)
print(str(cloned_mc_proj))
print("Cloned project local path:", cloned_mc_proj.local_path)
<materials_commons.cli.cloned_project.ClonedProject object at 0x7fe991a91940> Cloned project local path: /var/folders/v7/lq3_7hgj7n95d1xrct505ryh0000gp/T/tmpbq88nimt/ExampleProjectFromJupyter
This example clones the project to ~/mc_projects/ExampleProjectFromJupyter
.
parent_path = pathlib.Path.home() / "mc_projects"
os.makedirs(parent_path, exist_ok=True)
cloned_mc_proj = ClonedProject(email=email,
mcurl=mcurl,
proj_id=remote_mc_proj.id,
parent_path=parent_path, # must exist
name=None) # default uses project name
print(str(cloned_mc_proj))
print("Cloned project local path:", cloned_mc_proj.local_path)
<materials_commons.cli.cloned_project.ClonedProject object at 0x7fe991aa0ca0> Cloned project local path: /Users/username/mc_projects/ExampleProjectFromJupyter
This example opens a local project that has already been cloned.
cloned_mc_proj = ClonedProject(email=email,
mcurl=mcurl,
proj_id=remote_mc_proj.id,
path=pathlib.Path.home() / "mc_projects" / "ExampleProjectFromJupyter")
print(str(cloned_mc_proj))
print("Cloned project local path:", cloned_mc_proj.local_path)
<materials_commons.cli.cloned_project.ClonedProject object at 0x7fe991aa0310> Cloned project local path: /Users/username/mc_projects/ExampleProjectFromJupyter
The ClonedProject
instance provides access to Client
and Project
objects from the Materials Commons API (materials_commons.api
) along with the location of the cloned local project directory local_path
.
print(str(cloned_mc_proj.proj))
print(str(cloned_mc_proj.proj.remote))
print(type(cloned_mc_proj.local_path), str(cloned_mc_proj.local_path))
<materials_commons.api.models.Project object at 0x7fe991aa0d60> <materials_commons.api.client.Client object at 0x7fe991aa0bb0> <class 'pathlib.PosixPath'> /Users/username/mc_projects/ExampleProjectFromJupyter
The ClonedProject
instance from the CLI also provides methods for uploading and downloading files using features beyond those included in materials_commons.api
.
For example, transfers can include checks to skip transferring files that are equivalent, support recursive upload and download, globus transfer, etc.
Other methods implemented by the CLI will be added to ClonedProject
in the future.
This creates a directory and writes some files used in the upload examples.
example_file1 = cloned_mc_proj.local_path / "example_file1.txt"
with open(example_file1, 'w') as f:
f.write("Hello World!\n")
example_file2 = cloned_mc_proj.local_path / "example_file2.txt"
with open(example_file2, 'w') as f:
f.write("Hello World, again!\n")
example_dir = cloned_mc_proj.local_path / "dir"
os.makedirs(example_dir, exist_ok=True)
example_file3 = example_dir / "example_file3.txt"
with open(example_file3, 'w') as f:
f.write("Got some data here!\n")
example_file4 = example_dir / "example_file4.txt"
with open(example_file4, 'w') as f:
f.write("So much data!\n")
cloned_mc_proj.upload(example_file1)
uploaded: example_file1.txt
no_compare=True
to transfer without comparing checksums. Materials Commons will still check for file equivalence and only create a new file version if the file is different. cloned_mc_proj.upload(example_file1)
cloned_mc_proj.upload(example_file1, no_compare=True)
example_file1.txt: local is equivalent to remote (skipping) uploaded: example_file1.txt
cloned_mc_proj.upload(example_file1, example_file2)
example_file1.txt: local is equivalent to remote (skipping) uploaded: example_file2.txt
recursive=True
argument to transfer files and directories recursivelycloned_mc_proj.upload(example_dir, recursive=True)
uploaded: dir/example_file3.txt uploaded: dir/example_file4.txt
It is possible to upload a notebook, from within the notebook itself. To do so, we can use the "upload_as" option which allows uploading files that do not exist in the local cloned project directory. The following cells demonstrate getting the notebook's name, nb_name
, and then uploading the notebook itself to the Materials Commons project. It is placed in a "notebooks" directory. Note that it uploads the last saved version of the notebook, not the current state.
Note: Getting the notebook file path from `os.path.join(os.getcwd(), nb_name)` may not work in all cases
nb_name = "MaterialsCommons-Project-Example.ipynb"
notebook_local_abspath = os.path.join(os.getcwd(), nb_name)
notebook_upload_as = cloned_mc_proj.local_path / "notebooks" / nb_name
cloned_mc_proj.upload(notebook_local_abspath, upload_as=notebook_upload_as)
uploaded: ../../Work/codes/mccli/doc/source/assets/examples/MaterialsCommons-Project-Example.ipynb as notebooks/MaterialsCommons-Project-Example.ipynb
This removes the existing local files and directories to demonstrate downloading from Materials Commons.
for file in [example_file1, example_file2]:
if os.path.exists(file):
os.remove(file)
if os.path.exists(example_dir):
shutil.rmtree(example_dir)
print("Local project directory contents:", os.listdir(cloned_mc_proj.local_path))
Local project directory contents: ['.mc']
cloned_mc_proj.download(example_file1)
downloaded: example_file1.txt
no_compare=True
to transfer without comparing checksums.force=True
to force overwriting existing files without prompting.cloned_mc_proj.download(example_file1, no_compare=True)
cloned_mc_proj.download(example_file2)
shutil.copyfile(example_file2, example_file1)
cloned_mc_proj.download(example_file1, force=True)
Overwrite 'example_file1.txt'? y/n: y downloaded: example_file1.txt downloaded: example_file2.txt downloaded: example_file1.txt
cloned_mc_proj.download(example_file1, example_file2, force=True)
example_file1.txt: local is equivalent to remote (skipping) example_file2.txt: local is equivalent to remote (skipping)
recursive=True
argument to transfer files and directories recursivelycloned_mc_proj.download(example_dir, recursive=True)
downloaded: dir/example_file3.txt downloaded: dir/example_file4.txt
output
argument to output one file or directory to a different locationcloned_mc_proj.download(example_file1, output=cloned_mc_proj.local_path / "example_file3.txt")
downloaded: example_file1.txt as example_file3.txt
globus=True
argument to peform the file transfer using the current globus upload or download directorylabel
argument to give the transfer a label for easier trackingClonedProject
but it can be done using shell commands or the Materials Commons websitecloned_mc_proj.upload(example_file1, globus=True)
Created new globus upload (name=cavern-jaob-tryst, id=385). Globus task_id: 70e9548c-b298-11eb-a161-5fad80e6400b Globus transfer task initiated. Use `globus task list` to monitor task status. Use `mc globus upload` to manage Globus uploads. Multiple transfer tasks may be initiated. When all tasks finish uploading, use `mc globus upload --id 385 --finish` to import all uploaded files into the Materials Commons project.
cloned_mc_proj.download(example_file2, globus=True, force=True)
Created new globus download (name=oxbane-ureido-rifter, id=386). Checking if download is ready.. Download is ready. task_id = 7597269e-b298-11eb-a161-5fad80e6400b Globus transfer task initiated. Use `globus task list` to monitor task status. Use `mc globus download` to manage Globus downloads. Multiple transfer tasks may be initiated. When all tasks finish downloading, use `mc globus download --id 386 --delete` to close the download.
! cd {cloned_mc_proj.local_path} && mc globus upload && mc globus download
! globus task list
project_name project_id type name id created status -- ------------------------- ------------ ------ ----------------- ---- -------------------- -------- * ExampleProjectFromJupyter 657 upload cavern-jaob-tryst 385 2021 May 11 20:35:33 Ready project_name project_id type name id created status -- ------------------------- ------------ -------- -------------------- ---- -------------------- -------- * ExampleProjectFromJupyter 657 download oxbane-ureido-rifter 386 2021 May 11 20:35:40 Ready Task ID | Status | Type | Source Display Name | Dest Display Name | Label ------------------------------------ | --------- | -------- | -------------------------- | -------------------------- | ---------------------------------------------- 7597269e-b298-11eb-a161-5fad80e6400b | SUCCEEDED | TRANSFER | materials-commons-2-upload | user_computer | ExampleProjectFromJupyter-oxbane-ureido-rifter 70e9548c-b298-11eb-a161-5fad80e6400b | SUCCEEDED | TRANSFER | user_computer | materials-commons-2-upload | ExampleProjectFromJupyter-cavern-jaob-tryst
mc globus upload
results, and all files should appear in the project directory. The processing time required before files appear in your project will depend on the size of the transfer. from materials_commons.cli.functions import read_project_config
project_config = read_project_config(cloned_mc_proj.local_path)
! cd {cloned_mc_proj.local_path} && mc globus upload --id {project_config.globus_upload_id} --finish --force
Finishing current Globus upload
! cd {cloned_mc_proj.local_path} && mc globus download --id {project_config.globus_download_id} --delete --force
project_name project_id type name id created status -- ------------------------- ------------ -------- -------------------- ---- -------------------- -------- * ExampleProjectFromJupyter 657 download oxbane-ureido-rifter 386 2021 May 11 20:35:40 Ready Permanently deleting with --force... Deleted current Globus download
The delete_project
call will delete a project on Materials Commons.
Notes:
# Delete the remote project
projs = client.get_all_projects()
for proj in projs:
if proj.name == "ExampleProjectFromJupyter":
client.delete_project(proj.id)
# Delete the local project
local_project_path = pathlib.Path.home() / "mc_projects" / "ExampleProjectFromJupyter"
if os.path.exists(local_project_path):
shutil.rmtree(local_project_path)