<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Create a new Materials Commons project
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)
Step1:  Cloning a project
"Cloning" a project creates a local directory which is used as a place to upload and download project files. There are three construction options
Step2:  Example 1
Step3:  Example 2
Step4:  Example 3
Step5:  Using the ClonedProject
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.
Step6:  File transfer
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.
Setup for upload examples
Step7:  Upload one file
Step8:  By default, files that already exist will be skipped
Use 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.
Step9:  Upload multiple files
Step10:  Upload files and directories, recursively
Use the recursive=True argument to transfer files and directories recursively
Step11:  Uploading the notebook itself / use of "upload_as"
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.
<i> Note
Step12:  Setup for download examples
Step13:  Download one file
Step14:  By default, files that already exist will be skipped
Use no_compare=True to transfer without comparing checksums.
Use force=True to force overwriting existing files without prompting.
Step15:  Download multiple files
Step16:  Download files and directories, recursively
Use the recursive=True argument to transfer files and directories recursively
Step17:  Download with different name
Use the output argument to output one file or directory to a different location
Step18:  Using Globus file transfer
Use the globus=True argument to peform the file transfer using the current globus upload or download directory
Use the label argument to give the transfer a label for easier tracking
Globus configuration and transfer management is not currently supported via ClonedProject but it can be done using shell commands or the Materials Commons website
See the online documentation for more information on Globus file transfers.
Step19:  Monitor transfer status
Step20:  Finish the transfer
Uploads must be "finished" to transfer files into the project. Once processing is finished, the upload directory will no longer appear in 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. 
Globus download directories should be "deleted" when download tasks are finished. The download directory may be left as long as desired, but it will not reflect any file or directory changes to the project since the time the download directory was created.
Step21:  Example cleanup
The delete_project call will delete a project on Materials Commons.   
Notes
<ASSISTANT_TASK:>
Python Code:
# 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)
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)
Explanation: Create a new Materials Commons project
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:
- If you do not yet have a Materials Commons account, it can be created here.
- If you have not yet configured the Materials Commons client to access your account, you will be prompted to enter a password.
- Only one project per owner may have the same name. If the same name as an existing project is given, then the existing project is returned instead of creating a new project.
End of explanation
import os
import pathlib
import shutil
from materials_commons.cli.cloned_project import ClonedProject
Explanation: Cloning a project
"Cloning" a project creates a local directory which is used as a place to upload and download project files. There are three construction options:
Clone the project in a temporary directory (default)
Clone the project in a particular location or open the project if it already exists. This option makes use of the "parent_path" and "name" constructor arguments to specify where the local project directory will be constructed if it doesn't already exist.
Open an existing local cloned project. This option uses the "path" constructor argument to It can be at a particular location that a user chooses to reuse (by constructing with the
End of explanation
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)
Explanation: Example 1: Clone the project - using a temporary directory
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.
End of explanation
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)
Explanation: Example 2: Clone the project - specifying the location
This example clones the project to ~/mc_projects/ExampleProjectFromJupyter.
End of explanation
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)
Explanation: Example 3: Open an existing cloned project
This example opens a local project that has already been cloned.
End of explanation
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))
Explanation: Using the ClonedProject
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.
End of explanation
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")
Explanation: File transfer
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.
Setup for upload examples:
This creates a directory and writes some files used in the upload examples.
End of explanation
cloned_mc_proj.upload(example_file1)
Explanation: Upload one file
End of explanation
cloned_mc_proj.upload(example_file1)
cloned_mc_proj.upload(example_file1, no_compare=True)
Explanation: By default, files that already exist will be skipped
Use 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.
End of explanation
cloned_mc_proj.upload(example_file1, example_file2)
Explanation: Upload multiple files
End of explanation
cloned_mc_proj.upload(example_dir, recursive=True)
Explanation: Upload files and directories, recursively
Use the recursive=True argument to transfer files and directories recursively
End of explanation
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)
Explanation: Uploading the notebook itself / use of "upload_as"
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.
<i> Note: Getting the notebook file path from os.path.join(os.getcwd(), nb_name) may not work in all cases </i>
End of explanation
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))
Explanation: Setup for download examples:
This removes the existing local files and directories to demonstrate downloading from Materials Commons.
End of explanation
cloned_mc_proj.download(example_file1)
Explanation: Download one file
End of explanation
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)
Explanation: By default, files that already exist will be skipped
Use no_compare=True to transfer without comparing checksums.
Use force=True to force overwriting existing files without prompting.
End of explanation
cloned_mc_proj.download(example_file1, example_file2, force=True)
Explanation: Download multiple files
End of explanation
cloned_mc_proj.download(example_dir, recursive=True)
Explanation: Download files and directories, recursively
Use the recursive=True argument to transfer files and directories recursively
End of explanation
cloned_mc_proj.download(example_file1, output=cloned_mc_proj.local_path / "example_file3.txt")
Explanation: Download with different name
Use the output argument to output one file or directory to a different location
End of explanation
cloned_mc_proj.upload(example_file1, globus=True)
cloned_mc_proj.download(example_file2, globus=True, force=True)
Explanation: Using Globus file transfer
Use the globus=True argument to peform the file transfer using the current globus upload or download directory
Use the label argument to give the transfer a label for easier tracking
Globus configuration and transfer management is not currently supported via ClonedProject but it can be done using shell commands or the Materials Commons website
See the online documentation for more information on Globus file transfers.
End of explanation
! cd {cloned_mc_proj.local_path} && mc globus upload && mc globus download
! globus task list
Explanation: Monitor transfer status
End of explanation
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
! cd {cloned_mc_proj.local_path} && mc globus download --id {project_config.globus_download_id} --delete --force
Explanation: Finish the transfer
Uploads must be "finished" to transfer files into the project. Once processing is finished, the upload directory will no longer appear in 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. 
Globus download directories should be "deleted" when download tasks are finished. The download directory may be left as long as desired, but it will not reflect any file or directory changes to the project since the time the download directory was created.
End of explanation
# 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)
Explanation: Example cleanup
The delete_project call will delete a project on Materials Commons.   
Notes:
- Only the project owner can delete a project
- A project that has published datasets may not be deleted
- Be careful, there is no undo! Deleting a project deletes all project files and data.
- Deleting the remote project does not delete the local project files.
- Deleting the local project files does not delete the remote project
End of explanation
<END_TASK>