Initial commit
Browse files- .gitignore +132 -0
- LICENSE +21 -0
- Procfile +1 -0
- app.py +23 -0
- apps/google.py +95 -0
- apps/grant.py +108 -0
- apps/h_index.py +67 -0
- apps/home.py +16 -0
- apps/journal.py +310 -0
- apps/orcid.py +146 -0
- apps/organization.py +153 -0
- apps/publication.py +122 -0
- apps/researcher.py +240 -0
- data/journals.json +280 -0
- data/journals.xlsx +0 -0
- multiapp.py +71 -0
- packages.txt +0 -0
- postBuild +6 -0
- requirements.txt +14 -0
- setup.sh +8 -0
- streamlit_app.py +61 -0
- streamlit_call.py +14 -0
    	
        .gitignore
    ADDED
    
    | @@ -0,0 +1,132 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            # Byte-compiled / optimized / DLL files
         | 
| 2 | 
            +
            __pycache__/
         | 
| 3 | 
            +
            *.py[cod]
         | 
| 4 | 
            +
            *$py.class
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            # C extensions
         | 
| 7 | 
            +
            *.so
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            # Distribution / packaging
         | 
| 10 | 
            +
            .Python
         | 
| 11 | 
            +
            data/*.csv
         | 
| 12 | 
            +
            .vscode/
         | 
| 13 | 
            +
            private/
         | 
| 14 | 
            +
            build/
         | 
| 15 | 
            +
            develop-eggs/
         | 
| 16 | 
            +
            dist/
         | 
| 17 | 
            +
            downloads/
         | 
| 18 | 
            +
            eggs/
         | 
| 19 | 
            +
            .eggs/
         | 
| 20 | 
            +
            lib/
         | 
| 21 | 
            +
            lib64/
         | 
| 22 | 
            +
            parts/
         | 
| 23 | 
            +
            sdist/
         | 
| 24 | 
            +
            var/
         | 
| 25 | 
            +
            wheels/
         | 
| 26 | 
            +
            pip-wheel-metadata/
         | 
| 27 | 
            +
            share/python-wheels/
         | 
| 28 | 
            +
            *.egg-info/
         | 
| 29 | 
            +
            .installed.cfg
         | 
| 30 | 
            +
            *.egg
         | 
| 31 | 
            +
            MANIFEST
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            # PyInstaller
         | 
| 34 | 
            +
            #  Usually these files are written by a python script from a template
         | 
| 35 | 
            +
            #  before PyInstaller builds the exe, so as to inject date/other infos into it.
         | 
| 36 | 
            +
            *.manifest
         | 
| 37 | 
            +
            *.spec
         | 
| 38 | 
            +
             | 
| 39 | 
            +
            # Installer logs
         | 
| 40 | 
            +
            pip-log.txt
         | 
| 41 | 
            +
            pip-delete-this-directory.txt
         | 
| 42 | 
            +
             | 
| 43 | 
            +
            # Unit test / coverage reports
         | 
| 44 | 
            +
            htmlcov/
         | 
| 45 | 
            +
            .tox/
         | 
| 46 | 
            +
            .nox/
         | 
| 47 | 
            +
            .coverage
         | 
| 48 | 
            +
            .coverage.*
         | 
| 49 | 
            +
            .cache
         | 
| 50 | 
            +
            nosetests.xml
         | 
| 51 | 
            +
            coverage.xml
         | 
| 52 | 
            +
            *.cover
         | 
| 53 | 
            +
            *.py,cover
         | 
| 54 | 
            +
            .hypothesis/
         | 
| 55 | 
            +
            .pytest_cache/
         | 
| 56 | 
            +
             | 
| 57 | 
            +
            # Translations
         | 
| 58 | 
            +
            *.mo
         | 
| 59 | 
            +
            *.pot
         | 
| 60 | 
            +
             | 
| 61 | 
            +
            # Django stuff:
         | 
| 62 | 
            +
            *.log
         | 
| 63 | 
            +
            local_settings.py
         | 
| 64 | 
            +
            db.sqlite3
         | 
| 65 | 
            +
            db.sqlite3-journal
         | 
| 66 | 
            +
             | 
| 67 | 
            +
            # Flask stuff:
         | 
| 68 | 
            +
            instance/
         | 
| 69 | 
            +
            .webassets-cache
         | 
| 70 | 
            +
             | 
| 71 | 
            +
            # Scrapy stuff:
         | 
| 72 | 
            +
            .scrapy
         | 
| 73 | 
            +
             | 
| 74 | 
            +
            # Sphinx documentation
         | 
| 75 | 
            +
            docs/_build/
         | 
| 76 | 
            +
             | 
| 77 | 
            +
            # PyBuilder
         | 
| 78 | 
            +
            target/
         | 
| 79 | 
            +
             | 
| 80 | 
            +
            # Jupyter Notebook
         | 
| 81 | 
            +
            .ipynb_checkpoints
         | 
| 82 | 
            +
             | 
| 83 | 
            +
            # IPython
         | 
| 84 | 
            +
            profile_default/
         | 
| 85 | 
            +
            ipython_config.py
         | 
| 86 | 
            +
             | 
| 87 | 
            +
            # pyenv
         | 
| 88 | 
            +
            .python-version
         | 
| 89 | 
            +
             | 
| 90 | 
            +
            # pipenv
         | 
| 91 | 
            +
            #   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
         | 
| 92 | 
            +
            #   However, in case of collaboration, if having platform-specific dependencies or dependencies
         | 
| 93 | 
            +
            #   having no cross-platform support, pipenv may install dependencies that don't work, or not
         | 
| 94 | 
            +
            #   install all needed dependencies.
         | 
| 95 | 
            +
            #Pipfile.lock
         | 
| 96 | 
            +
             | 
| 97 | 
            +
            # PEP 582; used by e.g. github.com/David-OConnor/pyflow
         | 
| 98 | 
            +
            __pypackages__/
         | 
| 99 | 
            +
             | 
| 100 | 
            +
            # Celery stuff
         | 
| 101 | 
            +
            celerybeat-schedule
         | 
| 102 | 
            +
            celerybeat.pid
         | 
| 103 | 
            +
             | 
| 104 | 
            +
            # SageMath parsed files
         | 
| 105 | 
            +
            *.sage.py
         | 
| 106 | 
            +
             | 
| 107 | 
            +
            # Environments
         | 
| 108 | 
            +
            .env
         | 
| 109 | 
            +
            .venv
         | 
| 110 | 
            +
            env/
         | 
| 111 | 
            +
            venv/
         | 
| 112 | 
            +
            ENV/
         | 
| 113 | 
            +
            env.bak/
         | 
| 114 | 
            +
            venv.bak/
         | 
| 115 | 
            +
             | 
| 116 | 
            +
            # Spyder project settings
         | 
| 117 | 
            +
            .spyderproject
         | 
| 118 | 
            +
            .spyproject
         | 
| 119 | 
            +
             | 
| 120 | 
            +
            # Rope project settings
         | 
| 121 | 
            +
            .ropeproject
         | 
| 122 | 
            +
             | 
| 123 | 
            +
            # mkdocs documentation
         | 
| 124 | 
            +
            /site
         | 
| 125 | 
            +
             | 
| 126 | 
            +
            # mypy
         | 
| 127 | 
            +
            .mypy_cache/
         | 
| 128 | 
            +
            .dmypy.json
         | 
| 129 | 
            +
            dmypy.json
         | 
| 130 | 
            +
             | 
| 131 | 
            +
            # Pyre type checker
         | 
| 132 | 
            +
            .pyre/
         | 
    	
        LICENSE
    ADDED
    
    | @@ -0,0 +1,21 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            MIT License
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            Copyright (c) 2021 Qiusheng Wu
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            Permission is hereby granted, free of charge, to any person obtaining a copy
         | 
| 6 | 
            +
            of this software and associated documentation files (the "Software"), to deal
         | 
| 7 | 
            +
            in the Software without restriction, including without limitation the rights
         | 
| 8 | 
            +
            to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
         | 
| 9 | 
            +
            copies of the Software, and to permit persons to whom the Software is
         | 
| 10 | 
            +
            furnished to do so, subject to the following conditions:
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            The above copyright notice and this permission notice shall be included in all
         | 
| 13 | 
            +
            copies or substantial portions of the Software.
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         | 
| 16 | 
            +
            IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
         | 
| 17 | 
            +
            FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
         | 
| 18 | 
            +
            AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
         | 
| 19 | 
            +
            LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
         | 
| 20 | 
            +
            OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
         | 
| 21 | 
            +
            SOFTWARE.
         | 
    	
        Procfile
    ADDED
    
    | @@ -0,0 +1 @@ | |
|  | 
|  | |
| 1 | 
            +
            web: sh setup.sh && streamlit run streamlit_app.py
         | 
    	
        app.py
    ADDED
    
    | @@ -0,0 +1,23 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import scholarpy
         | 
| 2 | 
            +
            import streamlit as st
         | 
| 3 | 
            +
            from multiapp import MultiApp
         | 
| 4 | 
            +
            from apps import grant, home, journal, orcid, publication, researcher
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            st.set_page_config(layout="wide")
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            if "dsl" not in st.session_state:
         | 
| 9 | 
            +
                st.session_state["dsl"] = scholarpy.Dsl()
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            apps = MultiApp()
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            # Add all your application here
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            apps.add_app("Home", home.app)
         | 
| 16 | 
            +
            apps.add_app("Grant", grant.app)
         | 
| 17 | 
            +
            apps.add_app("Journal", journal.app)
         | 
| 18 | 
            +
            apps.add_app("Publication", publication.app)
         | 
| 19 | 
            +
            apps.add_app("Researcher", researcher.app)
         | 
| 20 | 
            +
            apps.add_app("ORCID", orcid.app)
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            # The main app
         | 
| 23 | 
            +
            apps.run()
         | 
    	
        apps/google.py
    ADDED
    
    | @@ -0,0 +1,95 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import os
         | 
| 2 | 
            +
            import scholarpy
         | 
| 3 | 
            +
            import tempfile
         | 
| 4 | 
            +
            import pandas as pd
         | 
| 5 | 
            +
            import streamlit as st
         | 
| 6 | 
            +
            import leafmap.foliumap as leafmap
         | 
| 7 | 
            +
            import plotly.express as px
         | 
| 8 | 
            +
            from scholarly import scholarly
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            # if "dsl" not in st.session_state:
         | 
| 11 | 
            +
            #     st.session_state["dsl"] = scholarpy.Dsl()
         | 
| 12 | 
            +
             | 
| 13 | 
            +
             | 
| 14 | 
            +
            def app():
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                st.title("Search Google Scholar")
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                row1_col1, row1_col2 = st.columns([1, 1])
         | 
| 19 | 
            +
                placeholder = st.empty()
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                with row1_col1:
         | 
| 22 | 
            +
                    name = st.text_input("Enter a researcher name:", "")
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                if name:
         | 
| 25 | 
            +
                    placeholder.text("Searching...")
         | 
| 26 | 
            +
                    if name not in st.session_state:
         | 
| 27 | 
            +
                        authors = scholarpy.get_author_list(name)
         | 
| 28 | 
            +
                        st.session_state[name] = authors
         | 
| 29 | 
            +
                    else:
         | 
| 30 | 
            +
                        authors = st.session_state[name]
         | 
| 31 | 
            +
                    placeholder.empty()
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                    if len(authors) == 0:
         | 
| 34 | 
            +
                        with row1_col1:
         | 
| 35 | 
            +
                            st.write("No results found")
         | 
| 36 | 
            +
                    else:
         | 
| 37 | 
            +
                        with row1_col1:
         | 
| 38 | 
            +
                            st.write("Found {} results:".format(len(authors)))
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                            author = st.selectbox("Select a researcher:", authors)
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                        if author:
         | 
| 43 | 
            +
                            placeholder.text("Retrieving data...")
         | 
| 44 | 
            +
                            id = author.split("|")[1].strip()
         | 
| 45 | 
            +
                            if id not in st.session_state:
         | 
| 46 | 
            +
                                record = scholarpy.get_author_record(id=id)
         | 
| 47 | 
            +
                                st.session_state[id] = record
         | 
| 48 | 
            +
                            else:
         | 
| 49 | 
            +
                                record = st.session_state[id]
         | 
| 50 | 
            +
                            basics = scholarpy.get_author_basics(
         | 
| 51 | 
            +
                                record=record, return_df=True)
         | 
| 52 | 
            +
                            out_csv = os.path.join(tempfile.gettempdir(), "basics.csv")
         | 
| 53 | 
            +
                            basics.to_csv(out_csv, sep="\t", index=False)
         | 
| 54 | 
            +
                            df = pd.read_csv(out_csv, sep="\t")
         | 
| 55 | 
            +
                            with row1_col1:
         | 
| 56 | 
            +
                                st.header("Basic information")
         | 
| 57 | 
            +
                                markdown = f"""Google Scholar Profile: <https://scholar.google.com/citations?user={id}>"""
         | 
| 58 | 
            +
                                st.markdown(markdown)
         | 
| 59 | 
            +
                                if "url_picture" in record and len(record["url_picture"]) > 0:
         | 
| 60 | 
            +
                                    st.image(record["url_picture"])
         | 
| 61 | 
            +
                                st.dataframe(df)
         | 
| 62 | 
            +
                                leafmap.st_download_button(
         | 
| 63 | 
            +
                                    "Download data", df, csv_sep="\t")
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                            pubs = scholarpy.get_author_pubs(record=record, return_df=True)
         | 
| 66 | 
            +
                            with row1_col1:
         | 
| 67 | 
            +
                                st.header("Publications")
         | 
| 68 | 
            +
                                st.text(f"Total number of publications: {len(pubs)}")
         | 
| 69 | 
            +
                                st.dataframe(pubs)
         | 
| 70 | 
            +
                                leafmap.st_download_button(
         | 
| 71 | 
            +
                                    "Download data", pubs, csv_sep="\t")
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                            pubs_stats, pubs_fig = scholarpy.author_pubs_by_year(
         | 
| 74 | 
            +
                                record=record, return_plot=True)
         | 
| 75 | 
            +
                            citations_stats, citations_fig = scholarpy.author_citations_by_year(
         | 
| 76 | 
            +
                                record=record, return_plot=True)
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                            with row1_col2:
         | 
| 79 | 
            +
                                st.header("Plots")
         | 
| 80 | 
            +
                                st.plotly_chart(pubs_fig)
         | 
| 81 | 
            +
                                leafmap.st_download_button("Download data", pubs_stats,
         | 
| 82 | 
            +
                                                           file_name="data.csv", csv_sep="\t")
         | 
| 83 | 
            +
                                st.plotly_chart(citations_fig)
         | 
| 84 | 
            +
                                leafmap.st_download_button(
         | 
| 85 | 
            +
                                    "Download data", citations_stats, file_name="data.csv", csv_sep="\t")
         | 
| 86 | 
            +
                                if len(record["coauthors"]) > 0:
         | 
| 87 | 
            +
                                    st.header("Co-authors")
         | 
| 88 | 
            +
                                    st.text(
         | 
| 89 | 
            +
                                        "Co-authors listed on Google Scholar profile only.")
         | 
| 90 | 
            +
                                    coauthors = scholarpy.get_author_coauthors(
         | 
| 91 | 
            +
                                        record=record, return_df=True)
         | 
| 92 | 
            +
                                    st.dataframe(coauthors)
         | 
| 93 | 
            +
                                    leafmap.st_download_button(
         | 
| 94 | 
            +
                                        "Download data", coauthors, file_name="data.csv", csv_sep="\t")
         | 
| 95 | 
            +
                            placeholder.empty()
         | 
    	
        apps/grant.py
    ADDED
    
    | @@ -0,0 +1,108 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import os
         | 
| 2 | 
            +
            import scholarpy
         | 
| 3 | 
            +
            import pandas as pd
         | 
| 4 | 
            +
            import streamlit as st
         | 
| 5 | 
            +
            import leafmap.foliumap as leafmap
         | 
| 6 | 
            +
            import plotly.express as px
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            if "dsl" not in st.session_state:
         | 
| 9 | 
            +
                st.session_state["dsl"] = scholarpy.Dsl()
         | 
| 10 | 
            +
             | 
| 11 | 
            +
             | 
| 12 | 
            +
            def app():
         | 
| 13 | 
            +
                st.title("Search Grants")
         | 
| 14 | 
            +
                dsl = st.session_state["dsl"]
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                (
         | 
| 17 | 
            +
                    row1_col1,
         | 
| 18 | 
            +
                    row1_col2,
         | 
| 19 | 
            +
                    row1_col3,
         | 
| 20 | 
            +
                    row1_col4,
         | 
| 21 | 
            +
                    row1_col5,
         | 
| 22 | 
            +
                ) = st.columns([1, 0.5, 1, 1, 1])
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                (
         | 
| 25 | 
            +
                    row2_col1,
         | 
| 26 | 
            +
                    row2_col2,
         | 
| 27 | 
            +
                    row2_col3,
         | 
| 28 | 
            +
                    row2_col4,
         | 
| 29 | 
            +
                    row2_col5,
         | 
| 30 | 
            +
                ) = st.columns([1, 0.5, 1, 1, 1])
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                with row1_col1:
         | 
| 33 | 
            +
                    keywords = st.text_input("Enter a keyword to search for")
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                with row1_col2:
         | 
| 36 | 
            +
                    exact_match = st.checkbox("Exact match", True)
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                with row1_col3:
         | 
| 39 | 
            +
                    scope = st.selectbox(
         | 
| 40 | 
            +
                        "Select a search scope",
         | 
| 41 | 
            +
                        [
         | 
| 42 | 
            +
                            "concepts",
         | 
| 43 | 
            +
                            "full_data",
         | 
| 44 | 
            +
                            "investigators",
         | 
| 45 | 
            +
                            "title_abstract_only",
         | 
| 46 | 
            +
                            "title_only",
         | 
| 47 | 
            +
                        ],
         | 
| 48 | 
            +
                        index=4,
         | 
| 49 | 
            +
                    )
         | 
| 50 | 
            +
                with row1_col4:
         | 
| 51 | 
            +
                    years = st.slider("Select the start and end year:", 1950, 2030, (2010, 2025))
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                with row1_col5:
         | 
| 54 | 
            +
                    limit = st.slider("Select the number of grants to return", 1, 1000, 100)
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                if keywords:
         | 
| 57 | 
            +
                    result = dsl.search_grants_by_keyword(
         | 
| 58 | 
            +
                        keywords,
         | 
| 59 | 
            +
                        exact_match,
         | 
| 60 | 
            +
                        scope,
         | 
| 61 | 
            +
                        start_year=years[0],
         | 
| 62 | 
            +
                        end_year=years[1],
         | 
| 63 | 
            +
                        limit=limit,
         | 
| 64 | 
            +
                    )
         | 
| 65 | 
            +
                    df = scholarpy.json_to_df(result)
         | 
| 66 | 
            +
                    if limit > result.count_total:
         | 
| 67 | 
            +
                        limit = result.count_total
         | 
| 68 | 
            +
                    markdown = f"""
         | 
| 69 | 
            +
                    Returned grants: {limit} (total = {result.count_total})        
         | 
| 70 | 
            +
                    
         | 
| 71 | 
            +
                    """
         | 
| 72 | 
            +
                    with row2_col1:
         | 
| 73 | 
            +
                        st.markdown(markdown)
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                    with row2_col2:
         | 
| 76 | 
            +
                        filter = st.checkbox("Apply a filter")
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                    if filter:
         | 
| 79 | 
            +
                        countries = []
         | 
| 80 | 
            +
                        for row in df.itertuples():
         | 
| 81 | 
            +
                            countries.append(eval(row.funder_countries)[0]["name"])
         | 
| 82 | 
            +
                        df["funder_country"] = countries
         | 
| 83 | 
            +
                        with row2_col3:
         | 
| 84 | 
            +
                            filter_by = st.selectbox(
         | 
| 85 | 
            +
                                "Select a filter",
         | 
| 86 | 
            +
                                [
         | 
| 87 | 
            +
                                    "funder_country",
         | 
| 88 | 
            +
                                    "funding_org_name",
         | 
| 89 | 
            +
                                    "funding_org_acronym",
         | 
| 90 | 
            +
                                    "research_org_name",
         | 
| 91 | 
            +
                                ],
         | 
| 92 | 
            +
                            )
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                            df["funding_org_acronym"] = df["funding_org_acronym"].astype(str)
         | 
| 95 | 
            +
                            df["research_org_name"] = df["research_org_name"].astype(str)
         | 
| 96 | 
            +
                            options = df[filter_by].unique()
         | 
| 97 | 
            +
                            options.sort()
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                        with row2_col4:
         | 
| 100 | 
            +
                            selected = st.selectbox("Select a filter value", options)
         | 
| 101 | 
            +
                            df = df[df[filter_by] == selected]
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                        with row2_col5:
         | 
| 104 | 
            +
                            st.write("")
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                    if df is not None:
         | 
| 107 | 
            +
                        st.dataframe(df)
         | 
| 108 | 
            +
                        leafmap.st_download_button("Download data", df, csv_sep="\t")
         | 
    	
        apps/h_index.py
    ADDED
    
    | @@ -0,0 +1,67 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import dimcli
         | 
| 2 | 
            +
            import pandas as pd
         | 
| 3 | 
            +
            import sys
         | 
| 4 | 
            +
            import os
         | 
| 5 | 
            +
            import streamlit as st
         | 
| 6 | 
            +
            import scholarpy
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            if "dsl" not in st.session_state:
         | 
| 9 | 
            +
                st.session_state["dsl"] = scholarpy.Dsl()
         | 
| 10 | 
            +
             | 
| 11 | 
            +
             | 
| 12 | 
            +
            @st.cache
         | 
| 13 | 
            +
            def the_H_function(sorted_citations_list, n=1):
         | 
| 14 | 
            +
                """from a list of integers [n1, n2 ..] representing publications citations,
         | 
| 15 | 
            +
                return the max list-position which is >= integer
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                eg
         | 
| 18 | 
            +
                >>> the_H_function([10, 8, 5, 4, 3]) => 4
         | 
| 19 | 
            +
                >>> the_H_function([25, 8, 5, 3, 3]) => 3
         | 
| 20 | 
            +
                >>> the_H_function([1000, 20]) => 2
         | 
| 21 | 
            +
                """
         | 
| 22 | 
            +
                if sorted_citations_list and sorted_citations_list[0] >= n:
         | 
| 23 | 
            +
                    return the_H_function(sorted_citations_list[1:], n + 1)
         | 
| 24 | 
            +
                else:
         | 
| 25 | 
            +
                    return n - 1
         | 
| 26 | 
            +
             | 
| 27 | 
            +
             | 
| 28 | 
            +
            def dim_login(key=None, endpoint=None):
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                if key is None:
         | 
| 31 | 
            +
                    KEY = os.environ.get("DIM_TOKEN")
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                if endpoint is None:
         | 
| 34 | 
            +
                    ENDPOINT = "https://app.dimensions.ai"
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                try:
         | 
| 37 | 
            +
                    dimcli.login(key=KEY, endpoint=ENDPOINT)
         | 
| 38 | 
            +
                    dsl = dimcli.Dsl()
         | 
| 39 | 
            +
                    return dsl
         | 
| 40 | 
            +
                except:
         | 
| 41 | 
            +
                    raise Exception("Failed to login to Dimensions")
         | 
| 42 | 
            +
             | 
| 43 | 
            +
             | 
| 44 | 
            +
            @st.cache
         | 
| 45 | 
            +
            def get_pubs_df(dsl, researcher_id):
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                q = """search publications where researchers.id = "{}" return publications[id+title+doi+times_cited] sort by times_cited limit 1000"""
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                pubs = dsl.query(q.format(researcher_id))
         | 
| 50 | 
            +
                return pubs.as_dataframe()
         | 
| 51 | 
            +
             | 
| 52 | 
            +
             | 
| 53 | 
            +
            @st.cache
         | 
| 54 | 
            +
            def get_citations(df):
         | 
| 55 | 
            +
                return list(df.fillna(0)["times_cited"])
         | 
| 56 | 
            +
             | 
| 57 | 
            +
             | 
| 58 | 
            +
            def app():
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                dsl = st.session_state["dsl"]
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                researchER_id = st.text_input("Enter researcher ID:", "ur.013632443777.66")
         | 
| 63 | 
            +
                df = get_pubs_df(dsl, researchER_id)
         | 
| 64 | 
            +
                st.dataframe(df)
         | 
| 65 | 
            +
                citations = get_citations(df)
         | 
| 66 | 
            +
                h_index = the_H_function(citations)
         | 
| 67 | 
            +
                st.write(f"H-index: {h_index}")
         | 
    	
        apps/home.py
    ADDED
    
    | @@ -0,0 +1,16 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import streamlit as st
         | 
| 2 | 
            +
             | 
| 3 | 
            +
             | 
| 4 | 
            +
            def app():
         | 
| 5 | 
            +
                st.title("Home")
         | 
| 6 | 
            +
                st.text(
         | 
| 7 | 
            +
                    "Welcome to the Scholar Web App. Click on the left sidebar menu to explore."
         | 
| 8 | 
            +
                )
         | 
| 9 | 
            +
                markdown = """
         | 
| 10 | 
            +
                Disclaimer: The data records are pulled from the [Dimensions.ai database](https://app.dimensions.ai), which might not be the most complete bibliometric database.
         | 
| 11 | 
            +
                We plan to incorporate [Scopus](https://www.scopus.com) and [Google Scholar](https://scholar.google.com) in the near future. Don't be surprised if you see that 
         | 
| 12 | 
            +
                your publication records are not the same as your Google Scholar profile. This is a very preliminary version. A lot more features will be added in the future.
         | 
| 13 | 
            +
                We would welcome any feedback. Please send feedback to Qiusheng Wu ([email protected]).
         | 
| 14 | 
            +
                """
         | 
| 15 | 
            +
                st.info(markdown)
         | 
| 16 | 
            +
                st.image("https://i.imgur.com/ZNUJ9fF.gif")
         | 
    	
        apps/journal.py
    ADDED
    
    | @@ -0,0 +1,310 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import os
         | 
| 2 | 
            +
            import json
         | 
| 3 | 
            +
            import dimcli
         | 
| 4 | 
            +
            import pandas as pd
         | 
| 5 | 
            +
            import plotly.express as px
         | 
| 6 | 
            +
            import streamlit as st
         | 
| 7 | 
            +
            import scholarpy
         | 
| 8 | 
            +
            import leafmap.foliumap as leafmap
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            if "dsl" not in st.session_state:
         | 
| 11 | 
            +
                st.session_state["dsl"] = scholarpy.Dsl()
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            # create output data folder
         | 
| 14 | 
            +
            FOLDER_NAME = "data"
         | 
| 15 | 
            +
            if not (os.path.exists(FOLDER_NAME)):
         | 
| 16 | 
            +
                os.mkdir(FOLDER_NAME)
         | 
| 17 | 
            +
             | 
| 18 | 
            +
             | 
| 19 | 
            +
            def save(df, filename_dot_csv):
         | 
| 20 | 
            +
                df.to_csv(FOLDER_NAME + "/" + filename_dot_csv, index=False)
         | 
| 21 | 
            +
             | 
| 22 | 
            +
             | 
| 23 | 
            +
            def read(filename_dot_csv):
         | 
| 24 | 
            +
                df = pd.read_csv(FOLDER_NAME + "/" + filename_dot_csv)
         | 
| 25 | 
            +
                return df
         | 
| 26 | 
            +
             | 
| 27 | 
            +
             | 
| 28 | 
            +
            @st.cache
         | 
| 29 | 
            +
            def get_token():
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                return os.environ.get("DIM_TOKEN")
         | 
| 32 | 
            +
             | 
| 33 | 
            +
             | 
| 34 | 
            +
            @st.cache
         | 
| 35 | 
            +
            def get_journals():
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                with open("data/journals.json") as f:
         | 
| 38 | 
            +
                    journals = json.load(f)
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                return journals
         | 
| 41 | 
            +
             | 
| 42 | 
            +
             | 
| 43 | 
            +
            @st.cache
         | 
| 44 | 
            +
            def read_excel(sheet_name):
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                df = pd.read_excel(
         | 
| 47 | 
            +
                    "data/journals.xlsx", sheet_name=sheet_name, index_col=False, engine="openpyxl"
         | 
| 48 | 
            +
                )
         | 
| 49 | 
            +
                df.set_index("Rank", inplace=True)
         | 
| 50 | 
            +
                return df
         | 
| 51 | 
            +
             | 
| 52 | 
            +
             | 
| 53 | 
            +
            def app():
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                st.title("Search Journals")
         | 
| 56 | 
            +
                dsl = st.session_state["dsl"]
         | 
| 57 | 
            +
                search_type = st.radio(
         | 
| 58 | 
            +
                    "Select a search type",
         | 
| 59 | 
            +
                    ["Search by journal title", "List Google Scholar journal categories"],
         | 
| 60 | 
            +
                )
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                if search_type == "Search by journal title":
         | 
| 63 | 
            +
                    row1_col1, row1_col2, row1_col3, _ = st.columns([1, 1, 2, 1])
         | 
| 64 | 
            +
                    with row1_col1:
         | 
| 65 | 
            +
                        name = st.text_input("Enter a journal title")
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                    with row1_col2:
         | 
| 68 | 
            +
                        exact_match = st.checkbox("Exact match")
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                    with row1_col3:
         | 
| 71 | 
            +
                        options = [
         | 
| 72 | 
            +
                            "book",
         | 
| 73 | 
            +
                            "book_series",
         | 
| 74 | 
            +
                            "proceeding",
         | 
| 75 | 
            +
                            "journal",
         | 
| 76 | 
            +
                            "preprint_platform",
         | 
| 77 | 
            +
                        ]
         | 
| 78 | 
            +
                        types = st.multiselect(
         | 
| 79 | 
            +
                            "Select journal types", options, ["journal", "book_series"]
         | 
| 80 | 
            +
                        )
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                    if name:
         | 
| 83 | 
            +
                        result = dsl.search_journal_by_title(name, exact_match=exact_match)
         | 
| 84 | 
            +
                        if result is not None:
         | 
| 85 | 
            +
                            titles = result.as_dataframe()
         | 
| 86 | 
            +
                            titles = titles[titles["type"].isin(types)]
         | 
| 87 | 
            +
                            titles.sort_values("title", inplace=True)
         | 
| 88 | 
            +
                        else:
         | 
| 89 | 
            +
                            titles = pd.DataFrame()
         | 
| 90 | 
            +
                        # titles = titles.astype({"start_year": int})
         | 
| 91 | 
            +
                        if not titles.empty:
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                            markdown = f"""
         | 
| 94 | 
            +
                            Returned Journals: {len(titles)}        
         | 
| 95 | 
            +
                            
         | 
| 96 | 
            +
                            """
         | 
| 97 | 
            +
                            st.markdown(markdown)
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                            st.dataframe(titles)
         | 
| 100 | 
            +
                            titles["uid"] = (
         | 
| 101 | 
            +
                                titles["id"] + " | " + titles["type"] + " | " + titles["title"]
         | 
| 102 | 
            +
                            )
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                            row2_col1, row2_col2, row2_col3, row2_col4, row2_col5 = st.columns(
         | 
| 105 | 
            +
                                [2.4, 1, 0.6, 1, 1]
         | 
| 106 | 
            +
                            )
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                            with row2_col1:
         | 
| 109 | 
            +
                                title = st.selectbox(
         | 
| 110 | 
            +
                                    "Select a journal title", titles["uid"].values.tolist()
         | 
| 111 | 
            +
                                )
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                            with row2_col2:
         | 
| 114 | 
            +
                                keyword = st.text_input("Enter a keyword to search for")
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                            with row2_col3:
         | 
| 117 | 
            +
                                exact_match = st.checkbox("Exact match", True)
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                            with row2_col4:
         | 
| 120 | 
            +
                                scope = st.selectbox(
         | 
| 121 | 
            +
                                    "Select a search scope",
         | 
| 122 | 
            +
                                    [
         | 
| 123 | 
            +
                                        "authors",
         | 
| 124 | 
            +
                                        "concepts",
         | 
| 125 | 
            +
                                        "full_data",
         | 
| 126 | 
            +
                                        "full_data_exact",
         | 
| 127 | 
            +
                                        "title_abstract_only",
         | 
| 128 | 
            +
                                        "title_only",
         | 
| 129 | 
            +
                                    ],
         | 
| 130 | 
            +
                                    index=5,
         | 
| 131 | 
            +
                                )
         | 
| 132 | 
            +
             | 
| 133 | 
            +
                            with row2_col5:
         | 
| 134 | 
            +
                                years = st.slider(
         | 
| 135 | 
            +
                                    "Select the start and end year:", 1950, 2021, (1980, 2021)
         | 
| 136 | 
            +
                                )
         | 
| 137 | 
            +
             | 
| 138 | 
            +
                            if title:
         | 
| 139 | 
            +
                                journal_id = title.split(" | ")[0]
         | 
| 140 | 
            +
                                if keyword:
         | 
| 141 | 
            +
                                    pubs = dsl.search_pubs_by_keyword(
         | 
| 142 | 
            +
                                        keyword, exact_match, scope, years[0], years[1], journal_id
         | 
| 143 | 
            +
                                    )
         | 
| 144 | 
            +
                                else:
         | 
| 145 | 
            +
                                    pubs = dsl.search_pubs_by_journal_id(
         | 
| 146 | 
            +
                                        journal_id, years[0], years[1]
         | 
| 147 | 
            +
                                    )
         | 
| 148 | 
            +
                                pubs_df = pubs.as_dataframe()
         | 
| 149 | 
            +
                                if pubs_df is not None and (not pubs_df.empty):
         | 
| 150 | 
            +
                                    st.write(
         | 
| 151 | 
            +
                                        f"Total number of pulications: {pubs.count_total:,}. Display {min(pubs.count_total, 1000)} publications below."
         | 
| 152 | 
            +
                                    )
         | 
| 153 | 
            +
                                    try:
         | 
| 154 | 
            +
                                        st.dataframe(pubs_df)
         | 
| 155 | 
            +
                                    except Exception as e:
         | 
| 156 | 
            +
                                        st.dataframe(scholarpy.json_to_df(pubs))
         | 
| 157 | 
            +
                                        # st.error("An error occurred: " + str(e))
         | 
| 158 | 
            +
                                    leafmap.st_download_button(
         | 
| 159 | 
            +
                                        "Download data", pubs_df, csv_sep="\t"
         | 
| 160 | 
            +
                                    )
         | 
| 161 | 
            +
                        else:
         | 
| 162 | 
            +
                            st.text("No results found")
         | 
| 163 | 
            +
             | 
| 164 | 
            +
                elif search_type == "List Google Scholar journal categories":
         | 
| 165 | 
            +
             | 
| 166 | 
            +
                    st.markdown(
         | 
| 167 | 
            +
                        """
         | 
| 168 | 
            +
                    The journal categories are adopted from [Google Scholar](https://scholar.google.com/citations?view_op=top_venues&hl=en&inst=9897619243961157265).
         | 
| 169 | 
            +
                    See the list of journals [here](https://docs.google.com/spreadsheets/d/1uCEi3TsJCWl9QEZimvjlM8wjt7hNq3QvMqHGeT44HXQ/edit?usp=sharing).
         | 
| 170 | 
            +
                    """
         | 
| 171 | 
            +
                    )
         | 
| 172 | 
            +
             | 
| 173 | 
            +
                    st.session_state["orcids"] = None
         | 
| 174 | 
            +
                    # dsl = st.session_state["dsl"]
         | 
| 175 | 
            +
                    # token = get_token()
         | 
| 176 | 
            +
                    # dimcli.login(key=token, endpoint="https://app.dimensions.ai")
         | 
| 177 | 
            +
                    # dsl = dimcli.Dsl()
         | 
| 178 | 
            +
             | 
| 179 | 
            +
                    categories = get_journals()
         | 
| 180 | 
            +
             | 
| 181 | 
            +
                    row1_col1, row1_col2, _, row1_col3 = st.columns([1, 1, 0.05, 1])
         | 
| 182 | 
            +
             | 
| 183 | 
            +
                    with row1_col1:
         | 
| 184 | 
            +
                        category = st.selectbox("Select a category:", categories.keys())
         | 
| 185 | 
            +
             | 
| 186 | 
            +
                    if category:
         | 
| 187 | 
            +
                        with row1_col2:
         | 
| 188 | 
            +
                            journal = st.selectbox("Select a journal:", categories[category].keys())
         | 
| 189 | 
            +
             | 
| 190 | 
            +
                    with row1_col3:
         | 
| 191 | 
            +
                        years = st.slider(
         | 
| 192 | 
            +
                            "Select the start and end year:", 1950, 2021, (1980, 2021)
         | 
| 193 | 
            +
                        )
         | 
| 194 | 
            +
             | 
| 195 | 
            +
                    if journal:
         | 
| 196 | 
            +
                        pubs = read_excel(sheet_name=category)
         | 
| 197 | 
            +
                        with st.expander("Show journal metrics"):
         | 
| 198 | 
            +
                            st.dataframe(pubs)
         | 
| 199 | 
            +
             | 
| 200 | 
            +
                    journal_id = categories[category][journal]
         | 
| 201 | 
            +
                    if journal_id is not None and str(journal_id).startswith("jour"):
         | 
| 202 | 
            +
                        q_template = """search publications where
         | 
| 203 | 
            +
                            journal.id="{}" and
         | 
| 204 | 
            +
                            year>={} and 
         | 
| 205 | 
            +
                            year<={}
         | 
| 206 | 
            +
                            return publications[id+title+doi+year+authors+type+pages+journal+issue+volume+altmetric+times_cited]
         | 
| 207 | 
            +
                            limit 1000"""
         | 
| 208 | 
            +
                        q = q_template.format(journal_id, years[0], years[1])
         | 
| 209 | 
            +
                    else:
         | 
| 210 | 
            +
                        q_template = """search publications where
         | 
| 211 | 
            +
                            journal.title="{}" and
         | 
| 212 | 
            +
                            year>={} and 
         | 
| 213 | 
            +
                            year<={}
         | 
| 214 | 
            +
                            return publications[id+title+doi+year+authors+type+pages+journal+issue+volume+altmetric+times_cited]
         | 
| 215 | 
            +
                            limit 1000"""
         | 
| 216 | 
            +
                        q = q_template.format(journal, years[0], years[1])
         | 
| 217 | 
            +
             | 
| 218 | 
            +
                    pubs = dsl.query(q)
         | 
| 219 | 
            +
                    if pubs.count_total > 0:
         | 
| 220 | 
            +
                        st.header("Publications")
         | 
| 221 | 
            +
                        st.write(
         | 
| 222 | 
            +
                            f"Total number of pulications: {pubs.count_total:,}. Display 1,000 publications below."
         | 
| 223 | 
            +
                        )
         | 
| 224 | 
            +
                        df_pubs = pubs.as_dataframe()
         | 
| 225 | 
            +
                        save(df_pubs, "publications.csv")
         | 
| 226 | 
            +
                        df_pubs = read("publications.csv")
         | 
| 227 | 
            +
                        st.dataframe(df_pubs)
         | 
| 228 | 
            +
             | 
| 229 | 
            +
                        st.header("Authors")
         | 
| 230 | 
            +
                        authors = pubs.as_dataframe_authors()
         | 
| 231 | 
            +
                        st.write(
         | 
| 232 | 
            +
                            f"Total number of authors of the 1,000 pubs shown above: {authors.shape[0]:,}"
         | 
| 233 | 
            +
                        )
         | 
| 234 | 
            +
                        save(authors, "authors.csv")
         | 
| 235 | 
            +
                        df_authors = read("authors.csv")
         | 
| 236 | 
            +
                        st.dataframe(df_authors)
         | 
| 237 | 
            +
             | 
| 238 | 
            +
                        df_authors_orcid = df_authors[~df_authors["orcid"].isna()]
         | 
| 239 | 
            +
                        # st.dataframe(df_authors_orcid)
         | 
| 240 | 
            +
                        orcids = list(set(df_authors_orcid["orcid"].values.tolist()))
         | 
| 241 | 
            +
                        orcids = [i[2:21] for i in orcids]
         | 
| 242 | 
            +
                        orcids.sort()
         | 
| 243 | 
            +
                        # st.write(orcids)
         | 
| 244 | 
            +
                        st.session_state["orcids"] = orcids
         | 
| 245 | 
            +
             | 
| 246 | 
            +
                        st.header("Affiliations")
         | 
| 247 | 
            +
                        affiliations = pubs.as_dataframe_authors_affiliations()
         | 
| 248 | 
            +
                        st.write(
         | 
| 249 | 
            +
                            f"Total number of affiliations of the 1,000 pubs shown above: {affiliations.shape[0]:,}"
         | 
| 250 | 
            +
                        )
         | 
| 251 | 
            +
                        save(affiliations, "affiliations.csv")
         | 
| 252 | 
            +
                        df_affiliations = read("affiliations.csv")
         | 
| 253 | 
            +
                        st.dataframe(df_affiliations)
         | 
| 254 | 
            +
             | 
| 255 | 
            +
                        researchers = authors.query("researcher_id!=''")
         | 
| 256 | 
            +
                        #
         | 
| 257 | 
            +
                        df_researchers = pd.DataFrame(
         | 
| 258 | 
            +
                            {
         | 
| 259 | 
            +
                                "measure": [
         | 
| 260 | 
            +
                                    "Authors in total (non unique)",
         | 
| 261 | 
            +
                                    "Authors with a researcher ID",
         | 
| 262 | 
            +
                                    "Authors with a researcher ID (unique)",
         | 
| 263 | 
            +
                                ],
         | 
| 264 | 
            +
                                "count": [
         | 
| 265 | 
            +
                                    len(authors),
         | 
| 266 | 
            +
                                    len(researchers),
         | 
| 267 | 
            +
                                    researchers["researcher_id"].nunique(),
         | 
| 268 | 
            +
                                ],
         | 
| 269 | 
            +
                            }
         | 
| 270 | 
            +
                        )
         | 
| 271 | 
            +
                        fig_researchers = px.bar(
         | 
| 272 | 
            +
                            df_researchers,
         | 
| 273 | 
            +
                            x="measure",
         | 
| 274 | 
            +
                            y="count",
         | 
| 275 | 
            +
                            title=f"Author Research ID stats for {journal} ({years[0]}-{years[1]})",
         | 
| 276 | 
            +
                        )
         | 
| 277 | 
            +
             | 
| 278 | 
            +
                        orcids = authors.query("orcid!=''")
         | 
| 279 | 
            +
                        #
         | 
| 280 | 
            +
                        df_orcids = pd.DataFrame(
         | 
| 281 | 
            +
                            {
         | 
| 282 | 
            +
                                "measure": [
         | 
| 283 | 
            +
                                    "Authors in total (non unique)",
         | 
| 284 | 
            +
                                    "Authors with a ORCID",
         | 
| 285 | 
            +
                                    "Authors with a ORCID (unique)",
         | 
| 286 | 
            +
                                ],
         | 
| 287 | 
            +
                                "count": [
         | 
| 288 | 
            +
                                    len(authors),
         | 
| 289 | 
            +
                                    len(orcids),
         | 
| 290 | 
            +
                                    orcids["orcid"].nunique(),
         | 
| 291 | 
            +
                                ],
         | 
| 292 | 
            +
                            }
         | 
| 293 | 
            +
                        )
         | 
| 294 | 
            +
                        fig_orcids = px.bar(
         | 
| 295 | 
            +
                            df_orcids,
         | 
| 296 | 
            +
                            x="measure",
         | 
| 297 | 
            +
                            y="count",
         | 
| 298 | 
            +
                            title=f"Author ORCID stats for {journal} ({years[0]}-{years[1]})",
         | 
| 299 | 
            +
                        )
         | 
| 300 | 
            +
             | 
| 301 | 
            +
                        st.header("Stats")
         | 
| 302 | 
            +
             | 
| 303 | 
            +
                        row2_col1, row1_col2 = st.columns(2)
         | 
| 304 | 
            +
                        with row2_col1:
         | 
| 305 | 
            +
                            st.plotly_chart(fig_researchers)
         | 
| 306 | 
            +
                        with row1_col2:
         | 
| 307 | 
            +
                            st.plotly_chart(fig_orcids)
         | 
| 308 | 
            +
             | 
| 309 | 
            +
                    else:
         | 
| 310 | 
            +
                        st.warning("No publications found")
         | 
    	
        apps/orcid.py
    ADDED
    
    | @@ -0,0 +1,146 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            from geemap.common import ee_initialize
         | 
| 2 | 
            +
            import requests
         | 
| 3 | 
            +
            import folium
         | 
| 4 | 
            +
            import scholarpy
         | 
| 5 | 
            +
            import streamlit as st
         | 
| 6 | 
            +
            import geemap.foliumap as geemap
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            if "dsl" not in st.session_state:
         | 
| 9 | 
            +
                st.session_state["dsl"] = scholarpy.Dsl()
         | 
| 10 | 
            +
             | 
| 11 | 
            +
             | 
| 12 | 
            +
            def get_orcid_data(orcid, info_type=None):
         | 
| 13 | 
            +
                """Retrieve ORCID data based on an ORCID and information type.
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                Args:
         | 
| 16 | 
            +
                    orcid (str): The ORCID to retrieve data for, e.g., 0000-0001-5437-4073
         | 
| 17 | 
            +
                    info_type (str): The type of information to retrieve, e.g., educations, employments, works
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                Returns:
         | 
| 20 | 
            +
                    dict: The ORCID data as a dictionary.
         | 
| 21 | 
            +
                """
         | 
| 22 | 
            +
                headers = {
         | 
| 23 | 
            +
                    "Accept": "application/vnd.orcid+json",
         | 
| 24 | 
            +
                }
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                if info_type is not None:
         | 
| 27 | 
            +
                    url = f"https://pub.orcid.org/v3.0/{orcid}/{info_type}"
         | 
| 28 | 
            +
                else:
         | 
| 29 | 
            +
                    url = f"https://pub.orcid.org/v3.0/{orcid}"
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                response = requests.get(url, headers=headers)
         | 
| 32 | 
            +
                return response.json()
         | 
| 33 | 
            +
             | 
| 34 | 
            +
             | 
| 35 | 
            +
            def get_education_data(orcid):
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                result = get_orcid_data(orcid, "educations")
         | 
| 38 | 
            +
                affiliations = result["affiliation-group"]
         | 
| 39 | 
            +
                info_dict = {}
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                try:
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                    for affiliation in affiliations:
         | 
| 44 | 
            +
                        summary = affiliation["summaries"][0]["education-summary"]
         | 
| 45 | 
            +
                        name = summary["source"]["source-name"]["value"]
         | 
| 46 | 
            +
                        role = summary["role-title"]
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                        organization = summary["organization"]["name"]
         | 
| 49 | 
            +
                        start_year = summary["start-date"]["year"]["value"]
         | 
| 50 | 
            +
                        end_year = summary["end-date"]["year"]["value"]
         | 
| 51 | 
            +
                        # start_date = (
         | 
| 52 | 
            +
                        #     summary["start-date"]["year"]["value"]
         | 
| 53 | 
            +
                        #     + "-"
         | 
| 54 | 
            +
                        #     + summary["start-date"]["month"]["value"]
         | 
| 55 | 
            +
                        #     + "-"
         | 
| 56 | 
            +
                        #     + summary["start-date"]["day"]["value"]
         | 
| 57 | 
            +
                        # )
         | 
| 58 | 
            +
                        # end_date = (
         | 
| 59 | 
            +
                        #     summary["end-date"]["year"]["value"]
         | 
| 60 | 
            +
                        #     + "-"
         | 
| 61 | 
            +
                        #     + summary["end-date"]["month"]["value"]
         | 
| 62 | 
            +
                        #     + "-"
         | 
| 63 | 
            +
                        #     + summary["end-date"]["day"]["value"]
         | 
| 64 | 
            +
                        # )
         | 
| 65 | 
            +
                        city = summary["organization"]["address"]["city"]
         | 
| 66 | 
            +
                        region = summary["organization"]["address"]["region"]
         | 
| 67 | 
            +
                        country = summary["organization"]["address"]["country"]
         | 
| 68 | 
            +
                        address_list = [city, region, country]
         | 
| 69 | 
            +
                        address = ", ".join([i for i in address_list if i])
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                        # address = city + ", " + region + ", " + country
         | 
| 72 | 
            +
                        coords = geemap.geocode(address)[0]
         | 
| 73 | 
            +
                        lat = coords.lat
         | 
| 74 | 
            +
                        lng = coords.lng
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                        info_dict[role] = {
         | 
| 77 | 
            +
                            "name": name,
         | 
| 78 | 
            +
                            "organization": organization,
         | 
| 79 | 
            +
                            "start_year": start_year,
         | 
| 80 | 
            +
                            "end_year": end_year,
         | 
| 81 | 
            +
                            "city": city,
         | 
| 82 | 
            +
                            "region": region,
         | 
| 83 | 
            +
                            "country": country,
         | 
| 84 | 
            +
                            "address": address,
         | 
| 85 | 
            +
                            "lat": lat,
         | 
| 86 | 
            +
                            "lng": lng,
         | 
| 87 | 
            +
                        }
         | 
| 88 | 
            +
                except:
         | 
| 89 | 
            +
                    pass
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                return info_dict
         | 
| 92 | 
            +
             | 
| 93 | 
            +
             | 
| 94 | 
            +
            def app():
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                dsl = st.session_state["dsl"]
         | 
| 97 | 
            +
                st.title("Retrieve ORCID Data")
         | 
| 98 | 
            +
                m = geemap.Map(center=(20, 0), zoom=2, ee_initialize=False)
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                row1_col1, row1_col2 = st.columns(2)
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                with row1_col1:
         | 
| 103 | 
            +
                    name = st.text_input("Enter a researcher name", "")
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                if name:
         | 
| 106 | 
            +
                    orcids = dsl.search_orcid_by_name(name, return_list=True)
         | 
| 107 | 
            +
                    with row1_col2:
         | 
| 108 | 
            +
                        if orcids is not None:
         | 
| 109 | 
            +
                            selected = st.selectbox("Select an ORCID", orcids)
         | 
| 110 | 
            +
                        else:
         | 
| 111 | 
            +
                            selected = None
         | 
| 112 | 
            +
                            st.write("No ORCID found.")
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                    #     orcids = ["0000-0001-5437-4073", "0000-0001-6157-5519"]
         | 
| 115 | 
            +
                    #     if st.session_state.get("orcids", []) is not None:
         | 
| 116 | 
            +
                    #         orcids = orcids + st.session_state.get("orcids", [])
         | 
| 117 | 
            +
                    #     selected_orcid = st.selectbox("Select an ORCID:", orcids)
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                    # with row1_col2:
         | 
| 120 | 
            +
                    #     orcid = st.text_input("Enter an ORCID:", selected_orcid)
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                    row2_col1, row2_col2 = st.columns([1, 1])
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                    if selected is not None:
         | 
| 125 | 
            +
                        orcid = selected.split("|")[1].strip()
         | 
| 126 | 
            +
                        education_data = get_education_data(orcid)
         | 
| 127 | 
            +
                        roles = list(education_data.keys())
         | 
| 128 | 
            +
             | 
| 129 | 
            +
                        for role in roles:
         | 
| 130 | 
            +
                            popup = f"<b>Name: </b>{education_data[role]['name']}<br><b>Organization: </b>{education_data[role]['organization']}<br><b>Degree: </b>{role}"
         | 
| 131 | 
            +
                            marker = folium.Marker(
         | 
| 132 | 
            +
                                [education_data[role]["lat"], education_data[role]["lng"]],
         | 
| 133 | 
            +
                                popup=popup,
         | 
| 134 | 
            +
                            )
         | 
| 135 | 
            +
                            marker.add_to(m)
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                        with row2_col1:
         | 
| 138 | 
            +
                            markdown = f"""ORCID URL: <https://orcid.org/{orcid}>"""
         | 
| 139 | 
            +
                            st.markdown(markdown)
         | 
| 140 | 
            +
                            if len(education_data) > 0:
         | 
| 141 | 
            +
                                st.write("Education:")
         | 
| 142 | 
            +
                                st.write(education_data)
         | 
| 143 | 
            +
                            else:
         | 
| 144 | 
            +
                                st.write("No education data found.")
         | 
| 145 | 
            +
                        with row2_col2:
         | 
| 146 | 
            +
                            m.to_streamlit()
         | 
    	
        apps/organization.py
    ADDED
    
    | @@ -0,0 +1,153 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import os
         | 
| 2 | 
            +
            import scholarpy
         | 
| 3 | 
            +
            import pandas as pd
         | 
| 4 | 
            +
            import streamlit as st
         | 
| 5 | 
            +
            import leafmap.foliumap as leafmap
         | 
| 6 | 
            +
            import plotly.express as px
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            if "dsl" not in st.session_state:
         | 
| 9 | 
            +
                st.session_state["dsl"] = scholarpy.Dsl()
         | 
| 10 | 
            +
             | 
| 11 | 
            +
             | 
| 12 | 
            +
            def app():
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                st.title("Search Organizations")
         | 
| 15 | 
            +
                dsl = st.session_state["dsl"]
         | 
| 16 | 
            +
                row1_col1, row1_col2 = st.columns([1, 1])
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                with row1_col1:
         | 
| 19 | 
            +
                    name = st.text_input("Enter an organization name:", "")
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                if name:
         | 
| 22 | 
            +
                    orgs = dsl.search_org_by_name(
         | 
| 23 | 
            +
                        name, exact_match=False, return_list=True)
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                    if orgs is not None:
         | 
| 26 | 
            +
                        with row1_col1:
         | 
| 27 | 
            +
                            selected_org = st.selectbox("Select a organization id:", orgs)
         | 
| 28 | 
            +
                            org_id = selected_org.split("|")[0].strip()
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                            id_info = dsl.search_org_by_id(org_id)
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                            info_df = scholarpy.json_to_df(id_info, transpose=True)
         | 
| 33 | 
            +
                            info_df.rename(
         | 
| 34 | 
            +
                                columns={info_df.columns[0]: "Type",
         | 
| 35 | 
            +
                                         info_df.columns[1]: "Value"},
         | 
| 36 | 
            +
                                inplace=True,
         | 
| 37 | 
            +
                            )
         | 
| 38 | 
            +
                            with row1_col1:
         | 
| 39 | 
            +
                                st.header("Organization Information")
         | 
| 40 | 
            +
                                if not info_df.empty:
         | 
| 41 | 
            +
                                    st.dataframe(info_df)
         | 
| 42 | 
            +
                                    leafmap.st_download_button(
         | 
| 43 | 
            +
                                        "Download data", info_df, csv_sep="\t"
         | 
| 44 | 
            +
                                    )
         | 
| 45 | 
            +
                                else:
         | 
| 46 | 
            +
                                    st.text("No information found")
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                            with row1_col2:
         | 
| 49 | 
            +
                                years = st.slider(
         | 
| 50 | 
            +
                                    "Select the start and end year:", 1950, 2030, (1980, 2021))
         | 
| 51 | 
            +
                                st.header("Publications by year")
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                                pubs, fig = dsl.org_pubs_annual_stats(
         | 
| 54 | 
            +
                                    org_id, start_year=years[0], end_year=years[1], return_plot=True)
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                                st.text(
         | 
| 57 | 
            +
                                    f'Total number of publications: {pubs["count"].sum():,}')
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                                if fig is not None:
         | 
| 60 | 
            +
                                    st.plotly_chart(fig)
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                                    leafmap.st_download_button(
         | 
| 63 | 
            +
                                        "Download data",
         | 
| 64 | 
            +
                                        pubs,
         | 
| 65 | 
            +
                                        file_name="data.csv",
         | 
| 66 | 
            +
                                        csv_sep="\t",
         | 
| 67 | 
            +
                                    )
         | 
| 68 | 
            +
                                else:
         | 
| 69 | 
            +
                                    st.text("No publications found")
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                            with row1_col1:
         | 
| 72 | 
            +
                                st.header("Top funders")
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                                funder_count = st.slider(
         | 
| 75 | 
            +
                                    "Select the number of funders:", 1, 100, 20)
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                                funders, fig = dsl.org_grant_funders(
         | 
| 78 | 
            +
                                    org_id, limit=funder_count, return_plot=True)
         | 
| 79 | 
            +
                                st.text(
         | 
| 80 | 
            +
                                    f'Total funding amount: ${funders["funding"].sum():,}')
         | 
| 81 | 
            +
                                if fig is not None:
         | 
| 82 | 
            +
                                    st.plotly_chart(fig)
         | 
| 83 | 
            +
                                    leafmap.st_download_button(
         | 
| 84 | 
            +
                                        "Download data",
         | 
| 85 | 
            +
                                        funders,
         | 
| 86 | 
            +
                                        file_name="data.csv",
         | 
| 87 | 
            +
                                        csv_sep="\t",
         | 
| 88 | 
            +
                                    )
         | 
| 89 | 
            +
                                else:
         | 
| 90 | 
            +
                                    st.text("No funders found")
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                            with row1_col2:
         | 
| 93 | 
            +
                                st.header("The number of grants by year")
         | 
| 94 | 
            +
                                grants, fig_count, fig_amount = dsl.org_grants_annual_stats(
         | 
| 95 | 
            +
                                    org_id, start_year=years[0], end_year=years[1], return_plot=True)
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                                st.plotly_chart(fig_count)
         | 
| 98 | 
            +
                                st.plotly_chart(fig_amount)
         | 
| 99 | 
            +
                                leafmap.st_download_button(
         | 
| 100 | 
            +
                                    "Download data",
         | 
| 101 | 
            +
                                    grants,
         | 
| 102 | 
            +
                                    file_name="data.csv",
         | 
| 103 | 
            +
                                    csv_sep="\t",
         | 
| 104 | 
            +
                                )
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                            with row1_col1:
         | 
| 107 | 
            +
                                st.header("List of grants")
         | 
| 108 | 
            +
                                st.text("Only the first 1000 grants are shown")
         | 
| 109 | 
            +
                                result = dsl.search_grants_by_org(
         | 
| 110 | 
            +
                                    org_id, start_year=years[0], end_year=years[1])
         | 
| 111 | 
            +
                                df = result.as_dataframe()
         | 
| 112 | 
            +
                                if not df.empty:
         | 
| 113 | 
            +
                                    st.dataframe(df)
         | 
| 114 | 
            +
                                    leafmap.st_download_button(
         | 
| 115 | 
            +
                                        "Download data", df, file_name="data.csv", csv_sep="\t"
         | 
| 116 | 
            +
                                    )
         | 
| 117 | 
            +
             | 
| 118 | 
            +
                            with row1_col1:
         | 
| 119 | 
            +
                                st.header("Publications most cited in last 2 years")
         | 
| 120 | 
            +
                                result = dsl.org_pubs_most_cited(org_id, recent=True, limit=100)
         | 
| 121 | 
            +
                                df = scholarpy.json_to_df(result, transpose=False)
         | 
| 122 | 
            +
                                if not df.empty:
         | 
| 123 | 
            +
                                    st.dataframe(df)
         | 
| 124 | 
            +
                                    leafmap.st_download_button(
         | 
| 125 | 
            +
                                        "Download data", df, file_name="data.csv", csv_sep="\t"
         | 
| 126 | 
            +
                                    )
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                            with row1_col2:
         | 
| 129 | 
            +
                                st.header("Publications most cited - all time")
         | 
| 130 | 
            +
                                result = dsl.org_pubs_most_cited(org_id, recent=False, limit=100)
         | 
| 131 | 
            +
                                df = scholarpy.json_to_df(result, transpose=False)
         | 
| 132 | 
            +
                                if not df.empty:
         | 
| 133 | 
            +
                                    st.dataframe(df)
         | 
| 134 | 
            +
                                    leafmap.st_download_button(
         | 
| 135 | 
            +
                                        "Download data", df, file_name="data.csv", csv_sep="\t"
         | 
| 136 | 
            +
                                    )
         | 
| 137 | 
            +
             | 
| 138 | 
            +
                            df, area_fig, journal_fig = dsl.org_pubs_top_areas(org_id, return_plot=True)
         | 
| 139 | 
            +
                            if not df.empty:
         | 
| 140 | 
            +
                                with row1_col1:
         | 
| 141 | 
            +
                                    st.header("Research areas of most cited publications")
         | 
| 142 | 
            +
                                    st.plotly_chart(area_fig)
         | 
| 143 | 
            +
                                    # leafmap.st_download_button(
         | 
| 144 | 
            +
                                    #     "Download data", df, file_name="data.csv", csv_sep="\t"
         | 
| 145 | 
            +
                                    # )
         | 
| 146 | 
            +
                                with row1_col2:
         | 
| 147 | 
            +
                                    st.header("Journals of most cited publications")
         | 
| 148 | 
            +
                                    st.plotly_chart(journal_fig)                    
         | 
| 149 | 
            +
                                    leafmap.st_download_button(
         | 
| 150 | 
            +
                                        "Download data", df, file_name="data.csv", csv_sep="\t"
         | 
| 151 | 
            +
                                    )
         | 
| 152 | 
            +
                    else:
         | 
| 153 | 
            +
                        st.text("No organizations found")
         | 
    	
        apps/publication.py
    ADDED
    
    | @@ -0,0 +1,122 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import os
         | 
| 2 | 
            +
            import scholarpy
         | 
| 3 | 
            +
            import pandas as pd
         | 
| 4 | 
            +
            import streamlit as st
         | 
| 5 | 
            +
            import leafmap.foliumap as leafmap
         | 
| 6 | 
            +
            import plotly.express as px
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            if "dsl" not in st.session_state:
         | 
| 9 | 
            +
                st.session_state["dsl"] = scholarpy.Dsl()
         | 
| 10 | 
            +
             | 
| 11 | 
            +
             | 
| 12 | 
            +
            def app():
         | 
| 13 | 
            +
                st.title("Search Publications")
         | 
| 14 | 
            +
                dsl = st.session_state["dsl"]
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                (
         | 
| 17 | 
            +
                    row1_col1,
         | 
| 18 | 
            +
                    row1_col2,
         | 
| 19 | 
            +
                    row1_col3,
         | 
| 20 | 
            +
                    row1_col4,
         | 
| 21 | 
            +
                    row1_col5,
         | 
| 22 | 
            +
                ) = st.columns([1, 0.7, 1, 1, 1])
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                row2_col1, row2_col2, row2_col3, row2_col4, row2_col5 = st.columns(
         | 
| 25 | 
            +
                    [1, 0.7, 1, 1, 1]
         | 
| 26 | 
            +
                )
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                with row1_col1:
         | 
| 29 | 
            +
                    keywords = st.text_input("Enter a keyword to search for")
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                with row1_col2:
         | 
| 32 | 
            +
                    exact_match = st.checkbox("Exact match", True)
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                with row1_col3:
         | 
| 35 | 
            +
                    scope = st.selectbox(
         | 
| 36 | 
            +
                        "Select a search scope",
         | 
| 37 | 
            +
                        [
         | 
| 38 | 
            +
                            "authors",
         | 
| 39 | 
            +
                            "concepts",
         | 
| 40 | 
            +
                            "full_data",
         | 
| 41 | 
            +
                            "full_data_exact",
         | 
| 42 | 
            +
                            "title_abstract_only",
         | 
| 43 | 
            +
                            "title_only",
         | 
| 44 | 
            +
                        ],
         | 
| 45 | 
            +
                        index=5,
         | 
| 46 | 
            +
                    )
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                with row1_col4:
         | 
| 49 | 
            +
                    years = st.slider("Select the start and end year:", 1950, 2030, (1980, 2022))
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                with row1_col5:
         | 
| 52 | 
            +
                    limit = st.slider("Select the number of publications to return", 1, 1000, 100)
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                if keywords:
         | 
| 55 | 
            +
                    result = dsl.search_pubs_by_keyword(
         | 
| 56 | 
            +
                        keywords,
         | 
| 57 | 
            +
                        exact_match,
         | 
| 58 | 
            +
                        scope,
         | 
| 59 | 
            +
                        start_year=years[0],
         | 
| 60 | 
            +
                        end_year=years[1],
         | 
| 61 | 
            +
                        limit=limit,
         | 
| 62 | 
            +
                    )
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                    df = scholarpy.json_to_df(result)
         | 
| 65 | 
            +
                    affiliations = result.as_dataframe_authors_affiliations()
         | 
| 66 | 
            +
                    country_df = affiliations.groupby(['pub_id'])['aff_country'].unique()
         | 
| 67 | 
            +
                    df = df.merge(country_df, left_on='id', right_on='pub_id')
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                    countries = [c[c.astype(bool)].size for c in df['aff_country']]
         | 
| 70 | 
            +
                    df['country_count'] = countries
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                    journal_counts = df.copy()["journal.title"].value_counts()
         | 
| 73 | 
            +
                    if limit > result.count_total:
         | 
| 74 | 
            +
                        limit = result.count_total
         | 
| 75 | 
            +
                    markdown = f"""
         | 
| 76 | 
            +
                    Returned Publications: {limit} (total = {result.count_total})        
         | 
| 77 | 
            +
                    
         | 
| 78 | 
            +
                    """
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                    with row2_col1:
         | 
| 81 | 
            +
                        st.markdown(markdown)
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                    with row2_col2:
         | 
| 84 | 
            +
                        filter = st.checkbox("Filter by journal")
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                    if filter:
         | 
| 87 | 
            +
                        df["journal.title"] = df["journal.title"].astype(str)
         | 
| 88 | 
            +
                        journals = df["journal.title"].unique()
         | 
| 89 | 
            +
                        journals.sort()
         | 
| 90 | 
            +
                        with row2_col3:
         | 
| 91 | 
            +
                            journal = st.selectbox("Select a journal", journals)
         | 
| 92 | 
            +
                        df = df[df["journal.title"] == journal]
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                    with row2_col4:
         | 
| 95 | 
            +
                        st.write("")
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                    with row2_col5:
         | 
| 98 | 
            +
                        st.write("")
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                    if df is not None:
         | 
| 101 | 
            +
                        st.dataframe(df)
         | 
| 102 | 
            +
                        leafmap.st_download_button("Download data", df, csv_sep="\t")
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                        summary = pd.DataFrame(
         | 
| 105 | 
            +
                            {"Journal": journal_counts.index, "Count": journal_counts}
         | 
| 106 | 
            +
                        ).reset_index(drop=True)
         | 
| 107 | 
            +
                        markdown = f"""
         | 
| 108 | 
            +
                        - Total number of journals: **{len(summary)}**
         | 
| 109 | 
            +
                        """
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                        row3_col1, row3_col2 = st.columns([1, 1])
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                        with row3_col1:
         | 
| 114 | 
            +
                            st.markdown(markdown)
         | 
| 115 | 
            +
                            st.dataframe(summary)
         | 
| 116 | 
            +
                            leafmap.st_download_button("Download data", summary, csv_sep="\t")
         | 
| 117 | 
            +
             | 
| 118 | 
            +
                        with row3_col2:
         | 
| 119 | 
            +
                            fig = px.box(df, x='year', y='country_count', title='Country Counts')
         | 
| 120 | 
            +
                            st.plotly_chart(fig)
         | 
| 121 | 
            +
             | 
| 122 | 
            +
             | 
    	
        apps/researcher.py
    ADDED
    
    | @@ -0,0 +1,240 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import os
         | 
| 2 | 
            +
            import scholarpy
         | 
| 3 | 
            +
            import pandas as pd
         | 
| 4 | 
            +
            import streamlit as st
         | 
| 5 | 
            +
            import leafmap.foliumap as leafmap
         | 
| 6 | 
            +
            import plotly.express as px
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            if "dsl" not in st.session_state:
         | 
| 9 | 
            +
                st.session_state["dsl"] = scholarpy.Dsl()
         | 
| 10 | 
            +
             | 
| 11 | 
            +
             | 
| 12 | 
            +
            @st.cache(allow_output_mutation=True)
         | 
| 13 | 
            +
            def get_geonames():
         | 
| 14 | 
            +
                return scholarpy.get_geonames()
         | 
| 15 | 
            +
             | 
| 16 | 
            +
             | 
| 17 | 
            +
            def json_to_df(json_data, transpose=False):
         | 
| 18 | 
            +
                df = json_data.as_dataframe()
         | 
| 19 | 
            +
                if not df.empty:
         | 
| 20 | 
            +
                    if transpose:
         | 
| 21 | 
            +
                        df = df.transpose()
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                    out_csv = leafmap.temp_file_path(".csv")
         | 
| 24 | 
            +
                    df.to_csv(out_csv, index=transpose)
         | 
| 25 | 
            +
                    df = pd.read_csv(out_csv)
         | 
| 26 | 
            +
                    os.remove(out_csv)
         | 
| 27 | 
            +
                    return df
         | 
| 28 | 
            +
                else:
         | 
| 29 | 
            +
                    return None
         | 
| 30 | 
            +
             | 
| 31 | 
            +
             | 
| 32 | 
            +
            def annual_pubs(pubs, col="year"):
         | 
| 33 | 
            +
                if pubs is not None:
         | 
| 34 | 
            +
                    df = pubs[col].value_counts().sort_index()
         | 
| 35 | 
            +
                    df2 = pd.DataFrame({"year": df.index, "publications": df.values})
         | 
| 36 | 
            +
                    return df2
         | 
| 37 | 
            +
                else:
         | 
| 38 | 
            +
                    return None
         | 
| 39 | 
            +
             | 
| 40 | 
            +
             | 
| 41 | 
            +
            def annual_collaborators(pubs, col="year"):
         | 
| 42 | 
            +
                if pubs is not None:
         | 
| 43 | 
            +
                    df = pubs.groupby([col]).sum()
         | 
| 44 | 
            +
                    df2 = pd.DataFrame(
         | 
| 45 | 
            +
                        {"year": df.index, "collaborators": df["authors_count"].values}
         | 
| 46 | 
            +
                    )
         | 
| 47 | 
            +
                    fig = px.bar(
         | 
| 48 | 
            +
                        df2,
         | 
| 49 | 
            +
                        x="year",
         | 
| 50 | 
            +
                        y="collaborators",
         | 
| 51 | 
            +
                    )
         | 
| 52 | 
            +
                    return fig
         | 
| 53 | 
            +
                else:
         | 
| 54 | 
            +
                    return None
         | 
| 55 | 
            +
             | 
| 56 | 
            +
             | 
| 57 | 
            +
            def annual_citations(pubs, col="year"):
         | 
| 58 | 
            +
                if pubs is not None:
         | 
| 59 | 
            +
                    df = pubs.groupby([col]).sum()
         | 
| 60 | 
            +
                    df2 = pd.DataFrame(
         | 
| 61 | 
            +
                        {"year": df.index, "citations": df["times_cited"].values})
         | 
| 62 | 
            +
                    fig = px.bar(
         | 
| 63 | 
            +
                        df2,
         | 
| 64 | 
            +
                        x="year",
         | 
| 65 | 
            +
                        y="citations",
         | 
| 66 | 
            +
                    )
         | 
| 67 | 
            +
                    return fig
         | 
| 68 | 
            +
                else:
         | 
| 69 | 
            +
                    return None
         | 
| 70 | 
            +
             | 
| 71 | 
            +
             | 
| 72 | 
            +
            def the_H_function(sorted_citations_list, n=1):
         | 
| 73 | 
            +
                """from a list of integers [n1, n2 ..] representing publications citations,
         | 
| 74 | 
            +
                return the max list-position which is >= integer
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                eg
         | 
| 77 | 
            +
                >>> the_H_function([10, 8, 5, 4, 3]) => 4
         | 
| 78 | 
            +
                >>> the_H_function([25, 8, 5, 3, 3]) => 3
         | 
| 79 | 
            +
                >>> the_H_function([1000, 20]) => 2
         | 
| 80 | 
            +
                """
         | 
| 81 | 
            +
                if sorted_citations_list and sorted_citations_list[0] >= n:
         | 
| 82 | 
            +
                    return the_H_function(sorted_citations_list[1:], n + 1)
         | 
| 83 | 
            +
                else:
         | 
| 84 | 
            +
                    return n - 1
         | 
| 85 | 
            +
             | 
| 86 | 
            +
             | 
| 87 | 
            +
            def app():
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                st.title("Search Researchers")
         | 
| 90 | 
            +
                dsl = st.session_state["dsl"]
         | 
| 91 | 
            +
                row1_col1, row1_col2 = st.columns([1, 1])
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                with row1_col1:
         | 
| 94 | 
            +
                    name = st.text_input("Enter a researcher name:", "")
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                if name:
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                    ids, names = dsl.search_researcher_by_name(name, return_list=True)
         | 
| 99 | 
            +
                    if ids.count_total > 0:
         | 
| 100 | 
            +
                        # options = ids.as_dataframe()["id"].values.tolist()
         | 
| 101 | 
            +
                        with row1_col1:
         | 
| 102 | 
            +
                            name = st.selectbox("Select a researcher id:", names)
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                        if name:
         | 
| 105 | 
            +
                            id = name.split("|")[1].strip()
         | 
| 106 | 
            +
                            id_info = dsl.search_researcher_by_id(id, return_df=False)
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                            info_df = json_to_df(id_info, transpose=True)
         | 
| 109 | 
            +
                            info_df.rename(
         | 
| 110 | 
            +
                                columns={info_df.columns[0]: "Type",
         | 
| 111 | 
            +
                                         info_df.columns[1]: "Value"},
         | 
| 112 | 
            +
                                inplace=True,
         | 
| 113 | 
            +
                            )
         | 
| 114 | 
            +
                            with row1_col1:
         | 
| 115 | 
            +
                                st.header("Researcher Information")
         | 
| 116 | 
            +
                                if not info_df.empty:
         | 
| 117 | 
            +
                                    st.dataframe(info_df)
         | 
| 118 | 
            +
                                    leafmap.st_download_button(
         | 
| 119 | 
            +
                                        "Download data", info_df, csv_sep="\t"
         | 
| 120 | 
            +
                                    )
         | 
| 121 | 
            +
                                else:
         | 
| 122 | 
            +
                                    st.text("No information found")
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                            pubs = dsl.search_pubs_by_researcher_id(id)
         | 
| 125 | 
            +
                            df = json_to_df(pubs)
         | 
| 126 | 
            +
                            # annual_df = annual_pubs(df)
         | 
| 127 | 
            +
                            if df is not None:
         | 
| 128 | 
            +
                                df1, df2 = dsl.researcher_annual_stats(
         | 
| 129 | 
            +
                                    pubs, geonames_df=get_geonames()
         | 
| 130 | 
            +
                                )
         | 
| 131 | 
            +
                                df3 = scholarpy.collaborator_locations(df2)
         | 
| 132 | 
            +
             | 
| 133 | 
            +
                                with row1_col2:
         | 
| 134 | 
            +
                                    st.header("Researcher statistics")
         | 
| 135 | 
            +
                                    columns = ["pubs", "collaborators",
         | 
| 136 | 
            +
                                               "institutions", "cities"]
         | 
| 137 | 
            +
                                    selected_columns = st.multiselect(
         | 
| 138 | 
            +
                                        "Select attributes to display:", columns, columns
         | 
| 139 | 
            +
                                    )
         | 
| 140 | 
            +
                                    if selected_columns:
         | 
| 141 | 
            +
                                        fig = scholarpy.annual_stats_barplot(
         | 
| 142 | 
            +
                                            df1, selected_columns)
         | 
| 143 | 
            +
                                        st.plotly_chart(fig)
         | 
| 144 | 
            +
                                    leafmap.st_download_button(
         | 
| 145 | 
            +
                                        "Download data",
         | 
| 146 | 
            +
                                        df1,
         | 
| 147 | 
            +
                                        file_name="data.csv",
         | 
| 148 | 
            +
                                        csv_sep="\t",
         | 
| 149 | 
            +
                                    )
         | 
| 150 | 
            +
             | 
| 151 | 
            +
                                    st.header("Map of collaborator institutions")
         | 
| 152 | 
            +
                                    markdown = f"""
         | 
| 153 | 
            +
                                    - Total number of collaborator institutions: **{len(df3)}**
         | 
| 154 | 
            +
                                    """
         | 
| 155 | 
            +
                                    st.markdown(markdown)
         | 
| 156 | 
            +
                                    m = leafmap.Map(
         | 
| 157 | 
            +
                                        center=[0, 0],
         | 
| 158 | 
            +
                                        zoom_start=1,
         | 
| 159 | 
            +
                                        latlon_control=False,
         | 
| 160 | 
            +
                                        draw_control=False,
         | 
| 161 | 
            +
                                        measure_control=False,
         | 
| 162 | 
            +
                                        locate_control=True,
         | 
| 163 | 
            +
                                    )
         | 
| 164 | 
            +
                                    m.add_points_from_xy(df3)
         | 
| 165 | 
            +
                                    m.to_streamlit(height=420)
         | 
| 166 | 
            +
                                    leafmap.st_download_button(
         | 
| 167 | 
            +
                                        "Download data",
         | 
| 168 | 
            +
                                        df3,
         | 
| 169 | 
            +
                                        file_name="data.csv",
         | 
| 170 | 
            +
                                        csv_sep="\t",
         | 
| 171 | 
            +
                                    )
         | 
| 172 | 
            +
             | 
| 173 | 
            +
                                    st.header("Publication counts with collaborators")
         | 
| 174 | 
            +
                                    collaborators = dsl.search_researcher_collaborators(
         | 
| 175 | 
            +
                                        id, pubs)
         | 
| 176 | 
            +
                                    markdown = f"""
         | 
| 177 | 
            +
                                    - Total number of collaborators: **{len(collaborators)}**
         | 
| 178 | 
            +
                                    """
         | 
| 179 | 
            +
                                    st.markdown(markdown)
         | 
| 180 | 
            +
                                    st.dataframe(collaborators)
         | 
| 181 | 
            +
                                    leafmap.st_download_button(
         | 
| 182 | 
            +
                                        "Download data",
         | 
| 183 | 
            +
                                        collaborators,
         | 
| 184 | 
            +
                                        file_name="data.csv",
         | 
| 185 | 
            +
                                        csv_sep="\t",
         | 
| 186 | 
            +
                                    )
         | 
| 187 | 
            +
                            else:
         | 
| 188 | 
            +
                                st.text("No publications found")
         | 
| 189 | 
            +
             | 
| 190 | 
            +
                            with row1_col1:
         | 
| 191 | 
            +
                                st.header("Publications")
         | 
| 192 | 
            +
                                if df is not None:
         | 
| 193 | 
            +
                                    citations = df["times_cited"].values.tolist()
         | 
| 194 | 
            +
                                    citations.sort(reverse=True)
         | 
| 195 | 
            +
                                    h_index = the_H_function(citations)
         | 
| 196 | 
            +
                                    markdown = f"""
         | 
| 197 | 
            +
                                    - Total number of publications: **{len(df)}**
         | 
| 198 | 
            +
                                    - Total number of citations: **{df["times_cited"].sum()}**
         | 
| 199 | 
            +
                                    - i10-index: **{len(df[df["times_cited"]>=10])}**
         | 
| 200 | 
            +
                                    - h-index: **{h_index}**
         | 
| 201 | 
            +
                                    """
         | 
| 202 | 
            +
                                    st.markdown(markdown)
         | 
| 203 | 
            +
                                    st.dataframe(df)
         | 
| 204 | 
            +
                                    leafmap.st_download_button(
         | 
| 205 | 
            +
                                        "Download data", df, file_name="data.csv", csv_sep="\t"
         | 
| 206 | 
            +
                                    )
         | 
| 207 | 
            +
             | 
| 208 | 
            +
                                    if "journal.title" in df.columns:
         | 
| 209 | 
            +
                                        st.header("Publication counts by journal")
         | 
| 210 | 
            +
                                        journals = df["journal.title"].value_counts()
         | 
| 211 | 
            +
                                        summary = pd.DataFrame(
         | 
| 212 | 
            +
                                            {"Journal": journals.index, "Count": journals}
         | 
| 213 | 
            +
                                        ).reset_index(drop=True)
         | 
| 214 | 
            +
                                        markdown = f"""
         | 
| 215 | 
            +
                                        - Total number of journals: **{len(summary)}**
         | 
| 216 | 
            +
                                        """
         | 
| 217 | 
            +
                                        st.markdown(markdown)
         | 
| 218 | 
            +
                                        st.dataframe(summary)
         | 
| 219 | 
            +
                                        leafmap.st_download_button(
         | 
| 220 | 
            +
                                            "Download data",
         | 
| 221 | 
            +
                                            summary,
         | 
| 222 | 
            +
                                            file_name="data.csv",
         | 
| 223 | 
            +
                                            csv_sep="\t",
         | 
| 224 | 
            +
                                        )
         | 
| 225 | 
            +
                                    else:
         | 
| 226 | 
            +
                                        st.text("No journal publications")
         | 
| 227 | 
            +
             | 
| 228 | 
            +
                                else:
         | 
| 229 | 
            +
                                    st.text("No publications found")
         | 
| 230 | 
            +
             | 
| 231 | 
            +
                                grants = dsl.search_grants_by_researcher(id)
         | 
| 232 | 
            +
                                df = grants.as_dataframe()
         | 
| 233 | 
            +
                                if not df.empty:
         | 
| 234 | 
            +
                                    st.header("Grants")
         | 
| 235 | 
            +
                                    st.dataframe(df)
         | 
| 236 | 
            +
                                    leafmap.st_download_button(
         | 
| 237 | 
            +
                                        "Download data", df, file_name="data.csv", csv_sep="\t"
         | 
| 238 | 
            +
                                    )
         | 
| 239 | 
            +
                    else:
         | 
| 240 | 
            +
                        st.text("No results found.")
         | 
    	
        data/journals.json
    ADDED
    
    | @@ -0,0 +1,280 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            {
         | 
| 2 | 
            +
                "All Categories": {
         | 
| 3 | 
            +
                    "Nature": "jour.1018957",
         | 
| 4 | 
            +
                    "The New England Journal of Medicine": "jour.1014075",
         | 
| 5 | 
            +
                    "Science": "jour.1346339",
         | 
| 6 | 
            +
                    "IEEE/CVF Conference on Computer Vision and Pattern Recognition": null,
         | 
| 7 | 
            +
                    "The Lancet": "jour.1077219",
         | 
| 8 | 
            +
                    "Advanced Materials": "jour.1129018",
         | 
| 9 | 
            +
                    "Cell": "jour.1019114",
         | 
| 10 | 
            +
                    "Nature Communications": null,
         | 
| 11 | 
            +
                    "Chemical Reviews": "jour.1077147",
         | 
| 12 | 
            +
                    "International Conference on Learning Representations": null,
         | 
| 13 | 
            +
                    "JAMA": "jour.1081531",
         | 
| 14 | 
            +
                    "Neural Information Processing Systems": null,
         | 
| 15 | 
            +
                    "Proceedings of the National Academy of Sciences": null,
         | 
| 16 | 
            +
                    "Journal of the American Chemical Society": null,
         | 
| 17 | 
            +
                    "Angewandte Chemie": null,
         | 
| 18 | 
            +
                    "Chemical Society Reviews": null,
         | 
| 19 | 
            +
                    "Nucleic Acids Research": null,
         | 
| 20 | 
            +
                    "Renewable and Sustainable Energy Reviews": null,
         | 
| 21 | 
            +
                    "Journal of Clinical Oncology": null,
         | 
| 22 | 
            +
                    "Physical Review Letters": null,
         | 
| 23 | 
            +
                    "Advanced Energy Materials": null,
         | 
| 24 | 
            +
                    "Nature Medicine": null,
         | 
| 25 | 
            +
                    "International Conference on Machine Learning": null,
         | 
| 26 | 
            +
                    "Energy & Environmental Science": null,
         | 
| 27 | 
            +
                    "ACS nullo": null,
         | 
| 28 | 
            +
                    "Scientific Reports": null,
         | 
| 29 | 
            +
                    "European Conference on Computer Vision": null,
         | 
| 30 | 
            +
                    "The Lancet Oncology": null,
         | 
| 31 | 
            +
                    "Advanced Functional Materials": null,
         | 
| 32 | 
            +
                    "PLoS ONE": null,
         | 
| 33 | 
            +
                    "IEEE/CVF International Conference on Computer Vision": null,
         | 
| 34 | 
            +
                    "Nature Genetics": null,
         | 
| 35 | 
            +
                    "Journal of Cleaner Production": null,
         | 
| 36 | 
            +
                    "Nature Materials": null,
         | 
| 37 | 
            +
                    "Science of The Total Environment": null,
         | 
| 38 | 
            +
                    "Circulation": "jour.1009570",
         | 
| 39 | 
            +
                    "BMJ": "jour.1017377",
         | 
| 40 | 
            +
                    "Journal of the American College of Cardiology": null,
         | 
| 41 | 
            +
                    "Applied Catalysis B: Environmental": null,
         | 
| 42 | 
            +
                    "Science Advances": null,
         | 
| 43 | 
            +
                    "nullo Letters": null,
         | 
| 44 | 
            +
                    "Nature Energy": null,
         | 
| 45 | 
            +
                    "ACS Applied Materials & Interfaces": null,
         | 
| 46 | 
            +
                    "Journal of Materials Chemistry A": null,
         | 
| 47 | 
            +
                    "IEEE Access": null,
         | 
| 48 | 
            +
                    "Nature Biotechnology": null,
         | 
| 49 | 
            +
                    "nullo Energy": null,
         | 
| 50 | 
            +
                    "Nature Methods": null,
         | 
| 51 | 
            +
                    "Nature nullotechnology": null,
         | 
| 52 | 
            +
                    "Cochrane Database of Systematic Reviews": null,
         | 
| 53 | 
            +
                    "The Astrophysical Journal": null,
         | 
| 54 | 
            +
                    "The Lancet Infectious Diseases": null,
         | 
| 55 | 
            +
                    "Applied Energy": null,
         | 
| 56 | 
            +
                    "European Heart Journal": null,
         | 
| 57 | 
            +
                    "Blood": "jour.1085025",
         | 
| 58 | 
            +
                    "American Economic Review": null,
         | 
| 59 | 
            +
                    "Immunity": "jour.1112054",
         | 
| 60 | 
            +
                    "Meeting of the Association for Computational Linguistics (ACL)": null,
         | 
| 61 | 
            +
                    "AAAI Conference on Artificial Intelligence": null,
         | 
| 62 | 
            +
                    "Gastroenterology": "jour.1017616",
         | 
| 63 | 
            +
                    "Neuron": "jour.1098485",
         | 
| 64 | 
            +
                    "Journal of High Energy Physics": null,
         | 
| 65 | 
            +
                    "IEEE Communications Surveys & Tutorials": null,
         | 
| 66 | 
            +
                    "Nature Neuroscience": null,
         | 
| 67 | 
            +
                    "Computers in Human Behavior": null,
         | 
| 68 | 
            +
                    "Chemical engineering journal": null,
         | 
| 69 | 
            +
                    "ACS Catalysis": null,
         | 
| 70 | 
            +
                    "Nature Reviews. Molecular Cell Biology": null,
         | 
| 71 | 
            +
                    "International Journal of Molecular Sciences": null,
         | 
| 72 | 
            +
                    "IEEE Transactions on Pattern Analysis and Machine Intelligence": null,
         | 
| 73 | 
            +
                    "Environmental Science & Technology": null,
         | 
| 74 | 
            +
                    "Monthly Notices of the Royal Astronomical Society": null,
         | 
| 75 | 
            +
                    "Cell Metabolism": null,
         | 
| 76 | 
            +
                    "Nature Physics": null,
         | 
| 77 | 
            +
                    "Physical Review D": null,
         | 
| 78 | 
            +
                    "Accounts of Chemical Research": null,
         | 
| 79 | 
            +
                    "Nature Photonics": null,
         | 
| 80 | 
            +
                    "Nature Climate Change": null,
         | 
| 81 | 
            +
                    "Chemistry of Materials": null,
         | 
| 82 | 
            +
                    "Molecular Cell": null,
         | 
| 83 | 
            +
                    "Clinical Infectious Diseases": null,
         | 
| 84 | 
            +
                    "Morbidity and Mortality Weekly Report": null,
         | 
| 85 | 
            +
                    "Nature Reviews Immunology": null,
         | 
| 86 | 
            +
                    "Gut": "jour.1077125",
         | 
| 87 | 
            +
                    "Annals of Oncology": null,
         | 
| 88 | 
            +
                    "Cell Reports": null,
         | 
| 89 | 
            +
                    "Journal of Business Research": null,
         | 
| 90 | 
            +
                    "Clinical Cancer Research": null,
         | 
| 91 | 
            +
                    "Frontiers in Microbiology": null,
         | 
| 92 | 
            +
                    "Journal of Hepatology": null,
         | 
| 93 | 
            +
                    "eLife": "jour.1046517",
         | 
| 94 | 
            +
                    "Bioinformatics": "jour.1345383",
         | 
| 95 | 
            +
                    "The Journal of Clinical Investigation": null,
         | 
| 96 | 
            +
                    "Science Translational Medicine": null,
         | 
| 97 | 
            +
                    "Water Research": null,
         | 
| 98 | 
            +
                    "Frontiers in Immunology": null,
         | 
| 99 | 
            +
                    "Small": "jour.1034711",
         | 
| 100 | 
            +
                    "Nature Immunology": null,
         | 
| 101 | 
            +
                    "JAMA Oncology": null,
         | 
| 102 | 
            +
                    "The Lancet Neurology": null
         | 
| 103 | 
            +
                },
         | 
| 104 | 
            +
                "Business, Economics & Management": {
         | 
| 105 | 
            +
                    "American Economic Review": "jour.1056580",
         | 
| 106 | 
            +
                    "Journal of Business Research": "jour.1028262",
         | 
| 107 | 
            +
                    "Tourism Management": null,
         | 
| 108 | 
            +
                    "Journal of Business Ethics": null,
         | 
| 109 | 
            +
                    "Journal of Finullcial Economics": null,
         | 
| 110 | 
            +
                    "The Quarterly Journal of Economics": null,
         | 
| 111 | 
            +
                    "The Review of Finullcial Studies": null,
         | 
| 112 | 
            +
                    "Technological Forecasting and Social Change": null,
         | 
| 113 | 
            +
                    "International Journal of Information Management": null,
         | 
| 114 | 
            +
                    "Management Science": null,
         | 
| 115 | 
            +
                    "Journal of Political Economy": null,
         | 
| 116 | 
            +
                    "International Journal of Production Economics": null,
         | 
| 117 | 
            +
                    "The Journal of Finullce": null,
         | 
| 118 | 
            +
                    "Journal of Management": null,
         | 
| 119 | 
            +
                    "Strategic Management Journal": null,
         | 
| 120 | 
            +
                    "World Development": null,
         | 
| 121 | 
            +
                    "Journal of Retailing and Consumer Services": null,
         | 
| 122 | 
            +
                    "Academy of Management Journal": null,
         | 
| 123 | 
            +
                    "International Journal of Project Management": null,
         | 
| 124 | 
            +
                    "Energy Economics": null
         | 
| 125 | 
            +
                },
         | 
| 126 | 
            +
                "Chemical & Material Sciences": {
         | 
| 127 | 
            +
                    "Advanced Materials": "jour.1129018",
         | 
| 128 | 
            +
                    "Chemical Reviews": null,
         | 
| 129 | 
            +
                    "Journal of the American Chemical Society": null,
         | 
| 130 | 
            +
                    "Angewandte Chemie": null,
         | 
| 131 | 
            +
                    "Chemical Society Reviews": null,
         | 
| 132 | 
            +
                    "Advanced Energy Materials": null,
         | 
| 133 | 
            +
                    "Energy & Environmental Science": null,
         | 
| 134 | 
            +
                    "ACS nullo": null,
         | 
| 135 | 
            +
                    "Advanced Functional Materials": null,
         | 
| 136 | 
            +
                    "Nature Materials": null,
         | 
| 137 | 
            +
                    "Applied Catalysis B: Environmental": null,
         | 
| 138 | 
            +
                    "nullo Letters": null,
         | 
| 139 | 
            +
                    "Nature Energy": null,
         | 
| 140 | 
            +
                    "ACS Applied Materials & Interfaces": null,
         | 
| 141 | 
            +
                    "Journal of Materials Chemistry A": null,
         | 
| 142 | 
            +
                    "nullo Energy": null,
         | 
| 143 | 
            +
                    "Nature nullotechnology": null,
         | 
| 144 | 
            +
                    "Chemical engineering journal": null,
         | 
| 145 | 
            +
                    "ACS Catalysis": null,
         | 
| 146 | 
            +
                    "Accounts of Chemical Research": null
         | 
| 147 | 
            +
                },
         | 
| 148 | 
            +
                "Engineering & Computer Science": {
         | 
| 149 | 
            +
                    "IEEE/CVF Conference on Computer Vision and Pattern Recognition": null,
         | 
| 150 | 
            +
                    "Advanced Materials": "jour.1129018",
         | 
| 151 | 
            +
                    "International Conference on Learning Representations": null,
         | 
| 152 | 
            +
                    "Neural Information Processing Systems": null,
         | 
| 153 | 
            +
                    "Renewable and Sustainable Energy Reviews": null,
         | 
| 154 | 
            +
                    "Advanced Energy Materials": null,
         | 
| 155 | 
            +
                    "International Conference on Machine Learning": null,
         | 
| 156 | 
            +
                    "Energy & Environmental Science": null,
         | 
| 157 | 
            +
                    "ACS nullo": null,
         | 
| 158 | 
            +
                    "European Conference on Computer Vision": null,
         | 
| 159 | 
            +
                    "Advanced Functional Materials": null,
         | 
| 160 | 
            +
                    "IEEE/CVF International Conference on Computer Vision": null,
         | 
| 161 | 
            +
                    "Journal of Cleaner Production": null,
         | 
| 162 | 
            +
                    "Nature Materials": null,
         | 
| 163 | 
            +
                    "Applied Catalysis B: Environmental": null,
         | 
| 164 | 
            +
                    "nullo Letters": null,
         | 
| 165 | 
            +
                    "Nature Energy": null,
         | 
| 166 | 
            +
                    "ACS Applied Materials & Interfaces": null,
         | 
| 167 | 
            +
                    "Journal of Materials Chemistry A": null,
         | 
| 168 | 
            +
                    "IEEE Access": null
         | 
| 169 | 
            +
                },
         | 
| 170 | 
            +
                "Health & Medical Sciences": {
         | 
| 171 | 
            +
                    "The New England Journal of Medicine": "jour.1014075",
         | 
| 172 | 
            +
                    "The Lancet": "jour.1077219",
         | 
| 173 | 
            +
                    "Cell": "jour.1019114",
         | 
| 174 | 
            +
                    "JAMA": "jour.1081531",
         | 
| 175 | 
            +
                    "Proceedings of the National Academy of Sciences": null,
         | 
| 176 | 
            +
                    "Journal of Clinical Oncology": null,
         | 
| 177 | 
            +
                    "Nature Medicine": null,
         | 
| 178 | 
            +
                    "The Lancet Oncology": null,
         | 
| 179 | 
            +
                    "PLoS ONE": null,
         | 
| 180 | 
            +
                    "Nature Genetics": null,
         | 
| 181 | 
            +
                    "Circulation": "jour.1009570",
         | 
| 182 | 
            +
                    "BMJ": "jour.1017377",
         | 
| 183 | 
            +
                    "Journal of the American College of Cardiology": null,
         | 
| 184 | 
            +
                    "Cochrane Database of Systematic Reviews": null,
         | 
| 185 | 
            +
                    "The Lancet Infectious Diseases": null,
         | 
| 186 | 
            +
                    "European Heart Journal": null,
         | 
| 187 | 
            +
                    "Blood": "jour.1085025",
         | 
| 188 | 
            +
                    "Immunity": "jour.1112054",
         | 
| 189 | 
            +
                    "Gastroenterology": "jour.1017616",
         | 
| 190 | 
            +
                    "Neuron": "jour.1098485"
         | 
| 191 | 
            +
                },
         | 
| 192 | 
            +
                "Humanities, Literature & Arts": {
         | 
| 193 | 
            +
                    "Digital Journalism": null,
         | 
| 194 | 
            +
                    "Journal of Communication": null,
         | 
| 195 | 
            +
                    "Journalism Studies": null,
         | 
| 196 | 
            +
                    "International Journal of Communication": null,
         | 
| 197 | 
            +
                    "Journalism": "jour.1138763",
         | 
| 198 | 
            +
                    "System": "jour.1137434",
         | 
| 199 | 
            +
                    "The Modern Language Journal": null,
         | 
| 200 | 
            +
                    "Media, Culture & Society": null,
         | 
| 201 | 
            +
                    "Synthese": "jour.1284232",
         | 
| 202 | 
            +
                    "Political Communication": null,
         | 
| 203 | 
            +
                    "Applied Linguistics": null,
         | 
| 204 | 
            +
                    "Language Learning": null,
         | 
| 205 | 
            +
                    "Public Opinion Quarterly": null,
         | 
| 206 | 
            +
                    "TESOL Quarterly": null,
         | 
| 207 | 
            +
                    "Journalism Practice": null,
         | 
| 208 | 
            +
                    "Feminist Media Studies": null,
         | 
| 209 | 
            +
                    "Studies in Second Language Acquisition": null,
         | 
| 210 | 
            +
                    "English Language Teaching": null,
         | 
| 211 | 
            +
                    "Language Teaching": null,
         | 
| 212 | 
            +
                    "Race Ethnicity and Education": null
         | 
| 213 | 
            +
                },
         | 
| 214 | 
            +
                "Life Sciences & Earth Sciences": {
         | 
| 215 | 
            +
                    "Nature": "jour.1018957",
         | 
| 216 | 
            +
                    "Science": "jour.1346339",
         | 
| 217 | 
            +
                    "Cell": "jour.1019114",
         | 
| 218 | 
            +
                    "Nature Communications": null,
         | 
| 219 | 
            +
                    "Proceedings of the National Academy of Sciences": null,
         | 
| 220 | 
            +
                    "Nucleic Acids Research": null,
         | 
| 221 | 
            +
                    "Scientific Reports": null,
         | 
| 222 | 
            +
                    "PLoS ONE": null,
         | 
| 223 | 
            +
                    "Nature Genetics": null,
         | 
| 224 | 
            +
                    "Science of The Total Environment": null,
         | 
| 225 | 
            +
                    "Science Advances": null,
         | 
| 226 | 
            +
                    "Nature Biotechnology": null,
         | 
| 227 | 
            +
                    "Nature Methods": null,
         | 
| 228 | 
            +
                    "Neuron": "jour.1098485",
         | 
| 229 | 
            +
                    "Nature Reviews. Molecular Cell Biology": null,
         | 
| 230 | 
            +
                    "International Journal of Molecular Sciences": null,
         | 
| 231 | 
            +
                    "Environmental Science & Technology": null,
         | 
| 232 | 
            +
                    "Cell Metabolism": null,
         | 
| 233 | 
            +
                    "Nature Climate Change": null,
         | 
| 234 | 
            +
                    "Molecular Cell": null
         | 
| 235 | 
            +
                },
         | 
| 236 | 
            +
                "Physics & Mathematics": {
         | 
| 237 | 
            +
                    "Physical Review Letters": null,
         | 
| 238 | 
            +
                    "The Astrophysical Journal": null,
         | 
| 239 | 
            +
                    "Journal of High Energy Physics": null,
         | 
| 240 | 
            +
                    "Monthly Notices of the Royal Astronomical Society": null,
         | 
| 241 | 
            +
                    "Nature Physics": null,
         | 
| 242 | 
            +
                    "Physical Review D": null,
         | 
| 243 | 
            +
                    "Nature Photonics": null,
         | 
| 244 | 
            +
                    "Physical Review B": null,
         | 
| 245 | 
            +
                    "Physical Review X": null,
         | 
| 246 | 
            +
                    "Astronomy & Astrophysics": null,
         | 
| 247 | 
            +
                    "The European Physical Journal C": null,
         | 
| 248 | 
            +
                    "Journal of Molecular Liquids": null,
         | 
| 249 | 
            +
                    "IEEE Transactions on Automatic Control": null,
         | 
| 250 | 
            +
                    "International Journal of Heat and Mass Transfer": null,
         | 
| 251 | 
            +
                    "Physics Letters B": null,
         | 
| 252 | 
            +
                    "IEEE Transactions on Geoscience and Remote Sensing": null,
         | 
| 253 | 
            +
                    "Reviews of Modern Physics": null,
         | 
| 254 | 
            +
                    "IEEE Transactions on Signal Processing": null,
         | 
| 255 | 
            +
                    "Geophysical Research Letters": null,
         | 
| 256 | 
            +
                    "Optica": "jour.1050828"
         | 
| 257 | 
            +
                },
         | 
| 258 | 
            +
                "Social Sciences": {
         | 
| 259 | 
            +
                    "Journal of Business Ethics": null,
         | 
| 260 | 
            +
                    "Computers & Education": null,
         | 
| 261 | 
            +
                    "Research Policy": null,
         | 
| 262 | 
            +
                    "New Media & Society": null,
         | 
| 263 | 
            +
                    "American Journal of Public Health": null,
         | 
| 264 | 
            +
                    "Global Environmental Change": null,
         | 
| 265 | 
            +
                    "Nature Human Behaviour": null,
         | 
| 266 | 
            +
                    "Health Affairs": null,
         | 
| 267 | 
            +
                    "Social Science & Medicine": null,
         | 
| 268 | 
            +
                    "Teaching and Teacher Education": null,
         | 
| 269 | 
            +
                    "Energy Research & Social Science": null,
         | 
| 270 | 
            +
                    "Information, Communication & Society": null,
         | 
| 271 | 
            +
                    "Land Use Policy": null,
         | 
| 272 | 
            +
                    "Academic Medicine": null,
         | 
| 273 | 
            +
                    "Studies in Higher Education": null,
         | 
| 274 | 
            +
                    "American Journal of Political Science": null,
         | 
| 275 | 
            +
                    "Review of Educational Research": null,
         | 
| 276 | 
            +
                    "Annals of Tourism Research": null,
         | 
| 277 | 
            +
                    "Cities": "jour.1027483",
         | 
| 278 | 
            +
                    "Business Strategy and the Environment": null
         | 
| 279 | 
            +
                }
         | 
| 280 | 
            +
            }
         | 
    	
        data/journals.xlsx
    ADDED
    
    | Binary file (25.6 kB). View file | 
|  | 
    	
        multiapp.py
    ADDED
    
    | @@ -0,0 +1,71 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            """Frameworks for running multiple Streamlit applications as a single app.
         | 
| 2 | 
            +
            """
         | 
| 3 | 
            +
            import streamlit as st
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            # app_state = st.experimental_get_query_params()
         | 
| 6 | 
            +
            # app_state = {k: v[0] if isinstance(v, list) else v for k, v in app_state.items()} # fetch the first item in each query string as we don't have multiple values for each query string key in this example
         | 
| 7 | 
            +
             | 
| 8 | 
            +
             | 
| 9 | 
            +
            class MultiApp:
         | 
| 10 | 
            +
                """Framework for combining multiple streamlit applications.
         | 
| 11 | 
            +
                Usage:
         | 
| 12 | 
            +
                    def foo():
         | 
| 13 | 
            +
                        st.title("Hello Foo")
         | 
| 14 | 
            +
                    def bar():
         | 
| 15 | 
            +
                        st.title("Hello Bar")
         | 
| 16 | 
            +
                    app = MultiApp()
         | 
| 17 | 
            +
                    app.add_app("Foo", foo)
         | 
| 18 | 
            +
                    app.add_app("Bar", bar)
         | 
| 19 | 
            +
                    app.run()
         | 
| 20 | 
            +
                It is also possible keep each application in a separate file.
         | 
| 21 | 
            +
                    import foo
         | 
| 22 | 
            +
                    import bar
         | 
| 23 | 
            +
                    app = MultiApp()
         | 
| 24 | 
            +
                    app.add_app("Foo", foo.app)
         | 
| 25 | 
            +
                    app.add_app("Bar", bar.app)
         | 
| 26 | 
            +
                    app.run()
         | 
| 27 | 
            +
                """
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                def __init__(self):
         | 
| 30 | 
            +
                    self.apps = []
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                def add_app(self, title, func):
         | 
| 33 | 
            +
                    """Adds a new application.
         | 
| 34 | 
            +
                    Parameters
         | 
| 35 | 
            +
                    ----------
         | 
| 36 | 
            +
                    func:
         | 
| 37 | 
            +
                        the python function to render this app.
         | 
| 38 | 
            +
                    title:
         | 
| 39 | 
            +
                        title of the app. Appears in the dropdown in the sidebar.
         | 
| 40 | 
            +
                    """
         | 
| 41 | 
            +
                    self.apps.append({"title": title, "function": func})
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                def run(self):
         | 
| 44 | 
            +
                    app_state = st.experimental_get_query_params()
         | 
| 45 | 
            +
                    app_state = {
         | 
| 46 | 
            +
                        k: v[0] if isinstance(v, list) else v for k, v in app_state.items()
         | 
| 47 | 
            +
                    }  # fetch the first item in each query string as we don't have multiple values for each query string key in this example
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                    # st.write('before', app_state)
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                    titles = [a["title"] for a in self.apps]
         | 
| 52 | 
            +
                    functions = [a["function"] for a in self.apps]
         | 
| 53 | 
            +
                    default_radio = titles.index(app_state["page"]) if "page" in app_state else 0
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                    st.sidebar.title("Navigation")
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                    title = st.sidebar.radio("Go To", titles, index=default_radio, key="radio")
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                    app_state["page"] = st.session_state.radio
         | 
| 60 | 
            +
                    # st.write('after', app_state)
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                    st.experimental_set_query_params(**app_state)
         | 
| 63 | 
            +
                    # st.experimental_set_query_params(**st.session_state.to_dict())
         | 
| 64 | 
            +
                    functions[titles.index(title)]()
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                    st.sidebar.title("About")
         | 
| 67 | 
            +
                    st.sidebar.info(
         | 
| 68 | 
            +
                        """
         | 
| 69 | 
            +
                        The web app URL: <https://scholar.gishub.org>. If you have any questions regarding this web app, please contact [Qiusheng Wu](https://wetlands.io) ([email protected]).
         | 
| 70 | 
            +
                    """
         | 
| 71 | 
            +
                    )
         | 
    	
        packages.txt
    ADDED
    
    | 
            File without changes
         | 
    	
        postBuild
    ADDED
    
    | @@ -0,0 +1,6 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            # enable nbserverproxy
         | 
| 2 | 
            +
            jupyter serverextension enable --sys-prefix nbserverproxy
         | 
| 3 | 
            +
            # streamlit launches at startup
         | 
| 4 | 
            +
            mv streamlit_call.py ${NB_PYTHON_PREFIX}/lib/python*/site-packages/
         | 
| 5 | 
            +
            # enable streamlit extension
         | 
| 6 | 
            +
            jupyter serverextension enable --sys-prefix streamlit_call
         | 
    	
        requirements.txt
    ADDED
    
    | @@ -0,0 +1,14 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            dimcli
         | 
| 2 | 
            +
            geopandas
         | 
| 3 | 
            +
            # jupyter-server-proxy
         | 
| 4 | 
            +
            # keplergl
         | 
| 5 | 
            +
            # nbserverproxy
         | 
| 6 | 
            +
            openpyxl
         | 
| 7 | 
            +
            streamlit
         | 
| 8 | 
            +
            streamlit-option-menu
         | 
| 9 | 
            +
            leafmap
         | 
| 10 | 
            +
            scholarpy
         | 
| 11 | 
            +
            geemap
         | 
| 12 | 
            +
            # git+https://github.com/giswqs/leafmap
         | 
| 13 | 
            +
            # git+https://github.com/giswqs/scholarpy
         | 
| 14 | 
            +
            # git+https://github.com/giswqs/geemap
         | 
    	
        setup.sh
    ADDED
    
    | @@ -0,0 +1,8 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            mkdir -p ~/.streamlit/
         | 
| 2 | 
            +
            echo "\
         | 
| 3 | 
            +
            [server]\n\
         | 
| 4 | 
            +
            headless = true\n\
         | 
| 5 | 
            +
            port = $PORT\n\
         | 
| 6 | 
            +
            enableCORS = false\n\
         | 
| 7 | 
            +
            \n\
         | 
| 8 | 
            +
            " > ~/.streamlit/config.toml
         | 
    	
        streamlit_app.py
    ADDED
    
    | @@ -0,0 +1,61 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import scholarpy
         | 
| 2 | 
            +
            import streamlit as st
         | 
| 3 | 
            +
            from streamlit_option_menu import option_menu
         | 
| 4 | 
            +
            from apps import grant, home, google, journal, orcid, organization, publication, researcher
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            st.set_page_config(page_title="Scholar Web App",
         | 
| 7 | 
            +
                               page_icon="chart_with_upwards_trend",
         | 
| 8 | 
            +
                               layout="wide")
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            # A dictionary of apps in the format of {"App title": "App icon"}
         | 
| 11 | 
            +
            # More icons can be found here: https://icons.getbootstrap.com
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            apps = {"home": {"title": "Home", "icon": "house"},
         | 
| 14 | 
            +
                    "grant": {"title": "Grant", "icon": "coin"},
         | 
| 15 | 
            +
                    "journal": {"title": "Journal", "icon": "journals"},
         | 
| 16 | 
            +
                    "publication": {"title": "Publication", "icon": "journal"},
         | 
| 17 | 
            +
                    "researcher": {"title": "Researcher", "icon": "person-circle"},
         | 
| 18 | 
            +
                    "orcid": {"title": "ORCID", "icon": "person-square"},
         | 
| 19 | 
            +
                    "organization": {"title": "Organization", "icon": "building"},
         | 
| 20 | 
            +
                    "google": {"title": "Google Scholar", "icon": "google"},
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                    }
         | 
| 23 | 
            +
             | 
| 24 | 
            +
             | 
| 25 | 
            +
            titles = [app["title"] for app in apps.values()]
         | 
| 26 | 
            +
            icons = [app["icon"] for app in apps.values()]
         | 
| 27 | 
            +
            params = st.experimental_get_query_params()
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            if "page" in params:
         | 
| 30 | 
            +
                default_index = int(titles.index(params["page"][0].lower()))
         | 
| 31 | 
            +
            else:
         | 
| 32 | 
            +
                default_index = 0
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            with st.sidebar:
         | 
| 35 | 
            +
                selected = option_menu(
         | 
| 36 | 
            +
                    "Main Menu",
         | 
| 37 | 
            +
                    options=titles,
         | 
| 38 | 
            +
                    icons=icons,
         | 
| 39 | 
            +
                    menu_icon="cast",
         | 
| 40 | 
            +
                    default_index=default_index,
         | 
| 41 | 
            +
                )
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                # st.sidebar.title("About")
         | 
| 44 | 
            +
                st.sidebar.info(
         | 
| 45 | 
            +
                    """
         | 
| 46 | 
            +
                    **Web App URL:** 
         | 
| 47 | 
            +
                    <https://scholar.streamlit.app>
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                    **Contact:**
         | 
| 50 | 
            +
                    - [Qiusheng Wu](https://geography.utk.edu/about-us/faculty/dr-qiusheng-wu)
         | 
| 51 | 
            +
                """
         | 
| 52 | 
            +
                )
         | 
| 53 | 
            +
                st.image("https://i.imgur.com/2WhANKg.png")
         | 
| 54 | 
            +
             | 
| 55 | 
            +
            if "dsl" not in st.session_state:
         | 
| 56 | 
            +
                st.session_state["dsl"] = scholarpy.Dsl()
         | 
| 57 | 
            +
             | 
| 58 | 
            +
            for app in apps:
         | 
| 59 | 
            +
                if apps[app]["title"] == selected:
         | 
| 60 | 
            +
                    eval(f"{app}.app()")
         | 
| 61 | 
            +
                    break
         | 
    	
        streamlit_call.py
    ADDED
    
    | @@ -0,0 +1,14 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            from subprocess import Popen
         | 
| 2 | 
            +
             | 
| 3 | 
            +
             | 
| 4 | 
            +
            def load_jupyter_server_extension(nbapp):
         | 
| 5 | 
            +
                """serve the streamlit app"""
         | 
| 6 | 
            +
                Popen(
         | 
| 7 | 
            +
                    [
         | 
| 8 | 
            +
                        "streamlit",
         | 
| 9 | 
            +
                        "run",
         | 
| 10 | 
            +
                        "streamlit_app.py",
         | 
| 11 | 
            +
                        "--browser.serverAddress=0.0.0.0",
         | 
| 12 | 
            +
                        "--server.enableCORS=False",
         | 
| 13 | 
            +
                    ]
         | 
| 14 | 
            +
                )
         | 
