From db3dd86dadbd76ab8ef7610850903dcd941856e6 Mon Sep 17 00:00:00 2001 From: Mike Tyszka Date: Thu, 28 Mar 2019 15:02:39 -0700 Subject: [PATCH 1/3] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 663300d..bdd8c3d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# BIDSKIT 1.2.2 +# BIDSKIT 1.2.3 DEVELOPMENT Python utilities for converting from DICOM to BIDS neuroimaging formats. The *bidskit* console command takes a directory tree containing imaging series from one or more subjects (eg T1w MPRAGE, BOLD EPI, Fieldmaps), converts the imaging data to Nifti-1 format with JSON metadata files (sidecars) and populates a @@ -16,4 +16,4 @@ Let us know about bugs and feature requests through this repo's ## Related Projects - [heudiconv](https://github.com/nipy/heudiconv) General purpose heuristic DICOM converter -- [dcm2bids](https://github.com/cbedetti/Dcm2Bids) Christophe Beddetti's DICOM to BIDS converter \ No newline at end of file +- [dcm2bids](https://github.com/cbedetti/Dcm2Bids) Christophe Beddetti's DICOM to BIDS converter From 740aedf9d03f17b5b23d596360725ad65a297e32 Mon Sep 17 00:00:00 2001 From: Mike Tyszka Date: Fri, 12 Apr 2019 10:33:51 -0700 Subject: [PATCH 2/3] Added virtual environment In venv/ subdirectory --- venv/bin/activate | 76 +++++++++++++++++++++++++++++++++++++++++ venv/bin/activate.csh | 37 ++++++++++++++++++++ venv/bin/activate.fish | 75 ++++++++++++++++++++++++++++++++++++++++ venv/bin/python | Bin 0 -> 13620 bytes venv/bin/python3 | Bin 0 -> 13620 bytes venv/bin/python3.7 | Bin 0 -> 13620 bytes venv/pyvenv.cfg | 3 ++ 7 files changed, 191 insertions(+) create mode 100644 venv/bin/activate create mode 100644 venv/bin/activate.csh create mode 100644 venv/bin/activate.fish create mode 100755 venv/bin/python create mode 100755 venv/bin/python3 create mode 100755 venv/bin/python3.7 create mode 100644 venv/pyvenv.cfg diff --git a/venv/bin/activate b/venv/bin/activate new file mode 100644 index 0000000..337081a --- /dev/null +++ b/venv/bin/activate @@ -0,0 +1,76 @@ +# This file must be used with "source bin/activate" *from bash* +# you cannot run it directly + +deactivate () { + # reset old environment variables + if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then + PATH="${_OLD_VIRTUAL_PATH:-}" + export PATH + unset _OLD_VIRTUAL_PATH + fi + if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then + PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}" + export PYTHONHOME + unset _OLD_VIRTUAL_PYTHONHOME + fi + + # This should detect bash and zsh, which have a hash command that must + # be called to get it to forget past commands. Without forgetting + # past commands the $PATH changes we made may not be respected + if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then + hash -r + fi + + if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then + PS1="${_OLD_VIRTUAL_PS1:-}" + export PS1 + unset _OLD_VIRTUAL_PS1 + fi + + unset VIRTUAL_ENV + if [ ! "$1" = "nondestructive" ] ; then + # Self destruct! + unset -f deactivate + fi +} + +# unset irrelevant variables +deactivate nondestructive + +VIRTUAL_ENV="/Users/jmt/GitHub/bidskit/venv" +export VIRTUAL_ENV + +_OLD_VIRTUAL_PATH="$PATH" +PATH="$VIRTUAL_ENV/bin:$PATH" +export PATH + +# unset PYTHONHOME if set +# this will fail if PYTHONHOME is set to the empty string (which is bad anyway) +# could use `if (set -u; : $PYTHONHOME) ;` in bash +if [ -n "${PYTHONHOME:-}" ] ; then + _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}" + unset PYTHONHOME +fi + +if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then + _OLD_VIRTUAL_PS1="${PS1:-}" + if [ "x(venv) " != x ] ; then + PS1="(venv) ${PS1:-}" + else + if [ "`basename \"$VIRTUAL_ENV\"`" = "__" ] ; then + # special case for Aspen magic directories + # see http://www.zetadev.com/software/aspen/ + PS1="[`basename \`dirname \"$VIRTUAL_ENV\"\``] $PS1" + else + PS1="(`basename \"$VIRTUAL_ENV\"`)$PS1" + fi + fi + export PS1 +fi + +# This should detect bash and zsh, which have a hash command that must +# be called to get it to forget past commands. Without forgetting +# past commands the $PATH changes we made may not be respected +if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then + hash -r +fi diff --git a/venv/bin/activate.csh b/venv/bin/activate.csh new file mode 100644 index 0000000..6d624fd --- /dev/null +++ b/venv/bin/activate.csh @@ -0,0 +1,37 @@ +# This file must be used with "source bin/activate.csh" *from csh*. +# You cannot run it directly. +# Created by Davide Di Blasi . +# Ported to Python 3.3 venv by Andrew Svetlov + +alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; test "\!:*" != "nondestructive" && unalias deactivate' + +# Unset irrelevant variables. +deactivate nondestructive + +setenv VIRTUAL_ENV "/Users/jmt/GitHub/bidskit/venv" + +set _OLD_VIRTUAL_PATH="$PATH" +setenv PATH "$VIRTUAL_ENV/bin:$PATH" + + +set _OLD_VIRTUAL_PROMPT="$prompt" + +if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then + if ("venv" != "") then + set env_name = "venv" + else + if (`basename "VIRTUAL_ENV"` == "__") then + # special case for Aspen magic directories + # see http://www.zetadev.com/software/aspen/ + set env_name = `basename \`dirname "$VIRTUAL_ENV"\`` + else + set env_name = `basename "$VIRTUAL_ENV"` + endif + endif + set prompt = "[$env_name] $prompt" + unset env_name +endif + +alias pydoc python -m pydoc + +rehash diff --git a/venv/bin/activate.fish b/venv/bin/activate.fish new file mode 100644 index 0000000..e7b8cf3 --- /dev/null +++ b/venv/bin/activate.fish @@ -0,0 +1,75 @@ +# This file must be used with ". bin/activate.fish" *from fish* (http://fishshell.org) +# you cannot run it directly + +function deactivate -d "Exit virtualenv and return to normal shell environment" + # reset old environment variables + if test -n "$_OLD_VIRTUAL_PATH" + set -gx PATH $_OLD_VIRTUAL_PATH + set -e _OLD_VIRTUAL_PATH + end + if test -n "$_OLD_VIRTUAL_PYTHONHOME" + set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME + set -e _OLD_VIRTUAL_PYTHONHOME + end + + if test -n "$_OLD_FISH_PROMPT_OVERRIDE" + functions -e fish_prompt + set -e _OLD_FISH_PROMPT_OVERRIDE + functions -c _old_fish_prompt fish_prompt + functions -e _old_fish_prompt + end + + set -e VIRTUAL_ENV + if test "$argv[1]" != "nondestructive" + # Self destruct! + functions -e deactivate + end +end + +# unset irrelevant variables +deactivate nondestructive + +set -gx VIRTUAL_ENV "/Users/jmt/GitHub/bidskit/venv" + +set -gx _OLD_VIRTUAL_PATH $PATH +set -gx PATH "$VIRTUAL_ENV/bin" $PATH + +# unset PYTHONHOME if set +if set -q PYTHONHOME + set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME + set -e PYTHONHOME +end + +if test -z "$VIRTUAL_ENV_DISABLE_PROMPT" + # fish uses a function instead of an env var to generate the prompt. + + # save the current fish_prompt function as the function _old_fish_prompt + functions -c fish_prompt _old_fish_prompt + + # with the original prompt function renamed, we can override with our own. + function fish_prompt + # Save the return status of the last command + set -l old_status $status + + # Prompt override? + if test -n "(venv) " + printf "%s%s" "(venv) " (set_color normal) + else + # ...Otherwise, prepend env + set -l _checkbase (basename "$VIRTUAL_ENV") + if test $_checkbase = "__" + # special case for Aspen magic directories + # see http://www.zetadev.com/software/aspen/ + printf "%s[%s]%s " (set_color -b blue white) (basename (dirname "$VIRTUAL_ENV")) (set_color normal) + else + printf "%s(%s)%s" (set_color -b blue white) (basename "$VIRTUAL_ENV") (set_color normal) + end + end + + # Restore the return status of the previous command. + echo "exit $old_status" | . + _old_fish_prompt + end + + set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV" +end diff --git a/venv/bin/python b/venv/bin/python new file mode 100755 index 0000000000000000000000000000000000000000..645c5940072c249fcd74714f46a70af01bb9b928 GIT binary patch literal 13620 zcmeHOVQd^n6`l)8W6~zJle7tt(xa_|TZGSUVo0JGZkt@PhO={t6W3{J#_PLv?&$jN z*xQTkl7eYs!G$6+a*#eq58v4b+PBt3WEGhE{??NH-J&LMVm)$nw3} zS>N6IT2{w=-||?TUd%hs1HSY{@Be93=({C+3>y(aa9Yg?UfC^#=>$1~X!&tyk)0@wRH zdzZVugmgmK@1xc~-Paj$U-v49l^RXh_2b>gB}xw%8r@esb8IC6G|saIFHDY&@TQyJPz5QQ~?d|n)Eb7{BrzE1* z=@Jjqx@vvhjrV{s!O#R<6KKMnBE})$Axt>i<+`G0gJNg{Zvy?-HpZgR-wNKFNB+G| z_P3+IUmL>wPd8AmgDi}G8+xQzFe650B$ApmQoz(cflllA;j5V+AN|74@n?#E`Q{H& zeBHf}wV<=LYZzO%hTZRBlA*O@zckPPo}lZb(Mczs|JAsg=L?DPj5P={9K?H&b1QGZ@kH8VN^k?NEWl%Xhpq~0`XK(3-I@_}wb#Ap>tk{1? z)pq(q^XWC9@!2OT@seZTgBq?{dPOaNeYgEK~(p9WT8dFWt1?BXK#t z#px}t+!EjUmUYLARJvC0yD~N5M64#&xuiP3DE?C|tD&hK9cpvzl3Ga~7!Ux3)q|569QWphJ)|BM$h5`Rik%yDo^o{a&do%E`Aa^_$ksgeo3>Z zFIb(*3=cs!3}JO1MKiVJ-)yrF0xXI{5I8tS>nq>>S-5){a@KXh-b2Rao+Cojy@8yO z#?~0I8#wezqfbMzGhc_1%mi&Q0NsP^whr{t4BTcgdHk=aXu;)KLv$@ED>^WKs~k4@`!TmQ9Nwjmofcitc5mt3pw%goo&Lt-+*YIjwjq*E8xW9MMWP|=ppq&MW+%@TN-nnwy%oO5Mx%1c`=$| zw8VHqj1yvfT#P5h_zf{miSbD>o)+V`#W;g8UcU1!Tv!=!+I|B%m&TRZ^=ppfq_+_F zCUKu3?lN&v;w}-_Pux6lM~VA6aXN87B94x}u0K!Qw}|@=ac78onz*yXJxSbeiJKtq z260*9HewyuQ^egv+{45@KwN@2g}8m-OkFebnw8!aZY!`37Qqo);^<(ke~`zOBmH~S z*dfkYK3B+0@Iqc2&k8#)BfUKJve(OLFVl0`+NqjlnK)3jmdOgbHIm8ZO?~tORN+xA zW9X@{l?x|x`N=hnOh*mvxHvAv?idB0S}nz`5@%T3L8+g|xivN7DQ9lODb_~!BrCKV z#-CyLed)LiAmm@ z%~%=D$ULsIgJ#Rz`Y5OG*;Be{=Gk17>)8_-6Qz&2D1CV=zMSW%Z$QtcUPsAAv=CJs znb}U0`v>;xR%}8~7A_o;QehB>NxS6qZLc>5~nqlOUgwjAYqW9`_3W*FVMwz@u+OGwdnLsdow!S1CqSH6> z@_&IS-2}R6DAS8t-v8l CJB8N( literal 0 HcmV?d00001 diff --git a/venv/bin/python3 b/venv/bin/python3 new file mode 100755 index 0000000000000000000000000000000000000000..645c5940072c249fcd74714f46a70af01bb9b928 GIT binary patch literal 13620 zcmeHOVQd^n6`l)8W6~zJle7tt(xa_|TZGSUVo0JGZkt@PhO={t6W3{J#_PLv?&$jN z*xQTkl7eYs!G$6+a*#eq58v4b+PBt3WEGhE{??NH-J&LMVm)$nw3} zS>N6IT2{w=-||?TUd%hs1HSY{@Be93=({C+3>y(aa9Yg?UfC^#=>$1~X!&tyk)0@wRH zdzZVugmgmK@1xc~-Paj$U-v49l^RXh_2b>gB}xw%8r@esb8IC6G|saIFHDY&@TQyJPz5QQ~?d|n)Eb7{BrzE1* z=@Jjqx@vvhjrV{s!O#R<6KKMnBE})$Axt>i<+`G0gJNg{Zvy?-HpZgR-wNKFNB+G| z_P3+IUmL>wPd8AmgDi}G8+xQzFe650B$ApmQoz(cflllA;j5V+AN|74@n?#E`Q{H& zeBHf}wV<=LYZzO%hTZRBlA*O@zckPPo}lZb(Mczs|JAsg=L?DPj5P={9K?H&b1QGZ@kH8VN^k?NEWl%Xhpq~0`XK(3-I@_}wb#Ap>tk{1? z)pq(q^XWC9@!2OT@seZTgBq?{dPOaNeYgEK~(p9WT8dFWt1?BXK#t z#px}t+!EjUmUYLARJvC0yD~N5M64#&xuiP3DE?C|tD&hK9cpvzl3Ga~7!Ux3)q|569QWphJ)|BM$h5`Rik%yDo^o{a&do%E`Aa^_$ksgeo3>Z zFIb(*3=cs!3}JO1MKiVJ-)yrF0xXI{5I8tS>nq>>S-5){a@KXh-b2Rao+Cojy@8yO z#?~0I8#wezqfbMzGhc_1%mi&Q0NsP^whr{t4BTcgdHk=aXu;)KLv$@ED>^WKs~k4@`!TmQ9Nwjmofcitc5mt3pw%goo&Lt-+*YIjwjq*E8xW9MMWP|=ppq&MW+%@TN-nnwy%oO5Mx%1c`=$| zw8VHqj1yvfT#P5h_zf{miSbD>o)+V`#W;g8UcU1!Tv!=!+I|B%m&TRZ^=ppfq_+_F zCUKu3?lN&v;w}-_Pux6lM~VA6aXN87B94x}u0K!Qw}|@=ac78onz*yXJxSbeiJKtq z260*9HewyuQ^egv+{45@KwN@2g}8m-OkFebnw8!aZY!`37Qqo);^<(ke~`zOBmH~S z*dfkYK3B+0@Iqc2&k8#)BfUKJve(OLFVl0`+NqjlnK)3jmdOgbHIm8ZO?~tORN+xA zW9X@{l?x|x`N=hnOh*mvxHvAv?idB0S}nz`5@%T3L8+g|xivN7DQ9lODb_~!BrCKV z#-CyLed)LiAmm@ z%~%=D$ULsIgJ#Rz`Y5OG*;Be{=Gk17>)8_-6Qz&2D1CV=zMSW%Z$QtcUPsAAv=CJs znb}U0`v>;xR%}8~7A_o;QehB>NxS6qZLc>5~nqlOUgwjAYqW9`_3W*FVMwz@u+OGwdnLsdow!S1CqSH6> z@_&IS-2}R6DAS8t-v8l CJB8N( literal 0 HcmV?d00001 diff --git a/venv/bin/python3.7 b/venv/bin/python3.7 new file mode 100755 index 0000000000000000000000000000000000000000..645c5940072c249fcd74714f46a70af01bb9b928 GIT binary patch literal 13620 zcmeHOVQd^n6`l)8W6~zJle7tt(xa_|TZGSUVo0JGZkt@PhO={t6W3{J#_PLv?&$jN z*xQTkl7eYs!G$6+a*#eq58v4b+PBt3WEGhE{??NH-J&LMVm)$nw3} zS>N6IT2{w=-||?TUd%hs1HSY{@Be93=({C+3>y(aa9Yg?UfC^#=>$1~X!&tyk)0@wRH zdzZVugmgmK@1xc~-Paj$U-v49l^RXh_2b>gB}xw%8r@esb8IC6G|saIFHDY&@TQyJPz5QQ~?d|n)Eb7{BrzE1* z=@Jjqx@vvhjrV{s!O#R<6KKMnBE})$Axt>i<+`G0gJNg{Zvy?-HpZgR-wNKFNB+G| z_P3+IUmL>wPd8AmgDi}G8+xQzFe650B$ApmQoz(cflllA;j5V+AN|74@n?#E`Q{H& zeBHf}wV<=LYZzO%hTZRBlA*O@zckPPo}lZb(Mczs|JAsg=L?DPj5P={9K?H&b1QGZ@kH8VN^k?NEWl%Xhpq~0`XK(3-I@_}wb#Ap>tk{1? z)pq(q^XWC9@!2OT@seZTgBq?{dPOaNeYgEK~(p9WT8dFWt1?BXK#t z#px}t+!EjUmUYLARJvC0yD~N5M64#&xuiP3DE?C|tD&hK9cpvzl3Ga~7!Ux3)q|569QWphJ)|BM$h5`Rik%yDo^o{a&do%E`Aa^_$ksgeo3>Z zFIb(*3=cs!3}JO1MKiVJ-)yrF0xXI{5I8tS>nq>>S-5){a@KXh-b2Rao+Cojy@8yO z#?~0I8#wezqfbMzGhc_1%mi&Q0NsP^whr{t4BTcgdHk=aXu;)KLv$@ED>^WKs~k4@`!TmQ9Nwjmofcitc5mt3pw%goo&Lt-+*YIjwjq*E8xW9MMWP|=ppq&MW+%@TN-nnwy%oO5Mx%1c`=$| zw8VHqj1yvfT#P5h_zf{miSbD>o)+V`#W;g8UcU1!Tv!=!+I|B%m&TRZ^=ppfq_+_F zCUKu3?lN&v;w}-_Pux6lM~VA6aXN87B94x}u0K!Qw}|@=ac78onz*yXJxSbeiJKtq z260*9HewyuQ^egv+{45@KwN@2g}8m-OkFebnw8!aZY!`37Qqo);^<(ke~`zOBmH~S z*dfkYK3B+0@Iqc2&k8#)BfUKJve(OLFVl0`+NqjlnK)3jmdOgbHIm8ZO?~tORN+xA zW9X@{l?x|x`N=hnOh*mvxHvAv?idB0S}nz`5@%T3L8+g|xivN7DQ9lODb_~!BrCKV z#-CyLed)LiAmm@ z%~%=D$ULsIgJ#Rz`Y5OG*;Be{=Gk17>)8_-6Qz&2D1CV=zMSW%Z$QtcUPsAAv=CJs znb}U0`v>;xR%}8~7A_o;QehB>NxS6qZLc>5~nqlOUgwjAYqW9`_3W*FVMwz@u+OGwdnLsdow!S1CqSH6> z@_&IS-2}R6DAS8t-v8l CJB8N( literal 0 HcmV?d00001 diff --git a/venv/pyvenv.cfg b/venv/pyvenv.cfg new file mode 100644 index 0000000..9bbbb6d --- /dev/null +++ b/venv/pyvenv.cfg @@ -0,0 +1,3 @@ +home = /usr/local/bin +include-system-site-packages = true +version = 3.7.3 From e6f8c6181a7fede2a8db8c21918e3dac7fc9e769 Mon Sep 17 00:00:00 2001 From: Mike Tyszka Date: Tue, 30 Apr 2019 13:23:01 -0700 Subject: [PATCH 3/3] Add additional exception catches for JSON file read in io.py --- CHANGELOG.md | 7 ++++++- bidskit/bidstree.py | 2 -- bidskit/io.py | 7 +++++-- bidskit/launcher.py | 2 +- bidskit/organize.py | 2 -- bidskit/translate.py | 11 ++++++++--- setup.py | 2 +- 7 files changed, 21 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bdccc5..a7f8b9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # BIDSKIT Changelog -## Version 1.2 +## Version 1.2.3 + +## Version 1.2.2 +- Fixed auto run number issue #55 + +## Version 1.2.1 - Bring output directory structure into compliance with BIDS v1.2 - Old source/ directory contents raised to top level of BIDS dataset directory diff --git a/bidskit/bidstree.py b/bidskit/bidstree.py index 4094dc7..499a54d 100644 --- a/bidskit/bidstree.py +++ b/bidskit/bidstree.py @@ -24,8 +24,6 @@ SOFTWARE. """ -__version__ = '1.2.2' - import os import sys import json diff --git a/bidskit/io.py b/bidskit/io.py index 8141466..c0db4be 100644 --- a/bidskit/io.py +++ b/bidskit/io.py @@ -24,8 +24,6 @@ SOFTWARE. """ -__version__ = '1.2.2' - import os import sys import shutil @@ -46,8 +44,13 @@ def read_json(fname): json_dict = json.load(fd) fd.close() except IOError: + print('*** {}'.format(fname)) print('*** JSON sidecar not found - returning empty dictionary') json_dict = dict() + except json.decoder.JSONDecodeError: + print('*** {}'.format(fname)) + print('*** JSON sidecar decoding error - returning empty dictionary') + json_dict = dict() return json_dict diff --git a/bidskit/launcher.py b/bidskit/launcher.py index 52d2d41..7bf2c07 100755 --- a/bidskit/launcher.py +++ b/bidskit/launcher.py @@ -42,7 +42,7 @@ SOFTWARE. """ -__version__ = '1.2.2' +__version__ = '1.2.3' import os import sys diff --git a/bidskit/organize.py b/bidskit/organize.py index 17911c2..a86bbdf 100644 --- a/bidskit/organize.py +++ b/bidskit/organize.py @@ -24,8 +24,6 @@ SOFTWARE. """ -__version__ = '1.2.2' - import os import shutil import bidskit.translate as btr diff --git a/bidskit/translate.py b/bidskit/translate.py index 9e94849..4a49654 100644 --- a/bidskit/translate.py +++ b/bidskit/translate.py @@ -24,8 +24,6 @@ SOFTWARE. """ -__version__ = '1.2.2' - import os import sys import json @@ -72,7 +70,14 @@ def get_acq_time(json_file): """ info = bio.read_json(json_file) - return info['AcquisitionTime'] + + if 'AcquisitionTime' in info: + acq_time = info['AcquisitionTime'] + else: + print('* AcquisitionTime not found in {}'.format(json_file)) + acq_time = "00:00:00.00" + + return acq_time def prune_intendedfors(bids_subj_dir, fmap_only): diff --git a/setup.py b/setup.py index dfecfbe..f55ec94 100644 --- a/setup.py +++ b/setup.py @@ -45,7 +45,7 @@ # For a discussion on single-sourcing the version across setup.py and the # project code, see # https://packaging.python.org/en/latest/single_source_version.html - version='1.2.2', # Required + version='1.2.3', # Required # This is a one-line description or tagline of what your project does. This # corresponds to the "Summary" metadata field: