├── .Rbuildignore ├── .appveyor.yml ├── .github ├── .gitignore └── workflows │ └── R-CMD-check.yaml ├── .gitignore ├── CITATION.cff ├── DESCRIPTION ├── LICENSE.md ├── NAMESPACE ├── NEWS.md ├── R ├── SGP-class.R ├── abcSGP.R ├── analyzeSGP.R ├── as.splineMatrix.R ├── baselineSGP.R ├── bubblePlot.R ├── bubblePlot_Styles.R ├── capwords.R ├── checkConfig.R ├── checkKnotsBoundaries.R ├── checkSGP.R ├── checksplineMatrix.R ├── combineSGP.R ├── convertScaleScore.R ├── convertTime.R ├── courseProgressionSGP.R ├── createKnotsBoundaries.R ├── createLongCutscores.R ├── createSuperCohortData.R ├── createUniqueLongData.R ├── csemScoreSimulator.R ├── ddcast.R ├── detectSGPCores.R ├── doRNG.R ├── equateSGP.R ├── getAchievementLevel.R ├── getCohortDataInfo.R ├── getErrorReports.R ├── getFirstAndLastInGroup.R ├── getHighNeedStatus.R ├── getJSON.R ├── getKey.R ├── getKnotsBoundaries.R ├── getMaxOrderForProgression.R ├── getMyLabel.R ├── getNewCutscores.R ├── getPanelData.R ├── getPanelDataVnames.R ├── getPercentileTableNames.R ├── getPreferredSGP.R ├── getSGPBaselineConfig.R ├── getSGPColor.R ├── getSGPConfig.R ├── getSGPSRSBaselineConfig.R ├── getSGPtNames.R ├── getStateAbbreviation.R ├── getTableNameYear.R ├── getTargetAchievementLevels.R ├── getTargetInitialStatus.R ├── getTargetName.R ├── getTargetSGP.R ├── getTargetSGPContentArea.R ├── getTargetSGPLevel.R ├── getTargetScaleScore.R ├── getTargetScaleScoreTableNames.R ├── getTimeShiftIndex.R ├── getVersion.R ├── getYearsContentAreasGrades.R ├── getsplineMatrices.R ├── gofPrint.R ├── gofSGP.R ├── growthAchievementPlot.R ├── is.SGP.R ├── is.splineMatrix.R ├── linkagePlot.R ├── mergeSGP.R ├── mergeScaleScoreTarget.R ├── messageSGP.R ├── outputSGP.R ├── piecewiseTransform.R ├── prepareSGP.R ├── prettyDate.R ├── rliCutscoreCreation.R ├── rliSGP.R ├── setNamesSGP.R ├── splineMatrix-class.R ├── sqliteSGP.R ├── startParallel.R ├── stopParallel.R ├── stratifiedRandomSampleSGP.R ├── studentGrowthPercentiles.R ├── studentGrowthPlot.R ├── studentGrowthPlot_Styles.R ├── studentGrowthProjections.R ├── summarizeSGP.R ├── summarizeSGP_Utilities.R ├── testSGP.R ├── timetakenSGP.R ├── transformScaleScore.R ├── unfoldstudentGrowthPlots.R ├── uniquesplineMatrix.R ├── updateSGP.R ├── visualizeSGP.R ├── yearIncrement.R └── zzz.R ├── README.md ├── _pkgdown.yml ├── data ├── SGPstateData.rda └── datalist ├── docs ├── CNAME ├── articles │ ├── SGP.html │ ├── SGP_Data_Analysis.html │ ├── SGP_Data_Analysis_files │ │ ├── anchor-sections-1.1.0 │ │ │ ├── anchor-sections-hash.css │ │ │ ├── anchor-sections-icon.css │ │ │ ├── anchor-sections-symbol.css │ │ │ ├── anchor-sections.css │ │ │ └── anchor-sections.js │ │ ├── header-attrs-2.13 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.14 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.22 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.25 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.7 │ │ │ └── header-attrs.js │ │ └── header-attrs-2.8 │ │ │ └── header-attrs.js │ ├── SGP_Data_Preparation.html │ ├── SGP_Data_Preparation_files │ │ ├── anchor-sections-1.1.0 │ │ │ ├── anchor-sections-hash.css │ │ │ ├── anchor-sections-icon.css │ │ │ ├── anchor-sections-symbol.css │ │ │ ├── anchor-sections.css │ │ │ └── anchor-sections.js │ │ ├── crosstalk-1.1.0.1 │ │ │ ├── css │ │ │ │ └── crosstalk.css │ │ │ └── js │ │ │ │ ├── crosstalk.js │ │ │ │ ├── crosstalk.js.map │ │ │ │ ├── crosstalk.min.js │ │ │ │ └── crosstalk.min.js.map │ │ ├── crosstalk-1.1.1 │ │ │ ├── css │ │ │ │ └── crosstalk.css │ │ │ └── js │ │ │ │ ├── crosstalk.js │ │ │ │ ├── crosstalk.js.map │ │ │ │ ├── crosstalk.min.js │ │ │ │ └── crosstalk.min.js.map │ │ ├── crosstalk-1.2.0 │ │ │ ├── css │ │ │ │ └── crosstalk.min.css │ │ │ ├── js │ │ │ │ ├── crosstalk.js │ │ │ │ ├── crosstalk.js.map │ │ │ │ ├── crosstalk.min.js │ │ │ │ └── crosstalk.min.js.map │ │ │ └── scss │ │ │ │ └── crosstalk.scss │ │ ├── header-attrs-2.13 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.14 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.22 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.25 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.7 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.8 │ │ │ └── header-attrs.js │ │ ├── htmlwidgets-1.5.1 │ │ │ └── htmlwidgets.js │ │ ├── htmlwidgets-1.5.3 │ │ │ └── htmlwidgets.js │ │ ├── htmlwidgets-1.5.4 │ │ │ └── htmlwidgets.js │ │ ├── htmlwidgets-1.6.2 │ │ │ └── htmlwidgets.js │ │ ├── jquery-1.11.3 │ │ │ ├── jquery-AUTHORS.txt │ │ │ ├── jquery.js │ │ │ ├── jquery.min.js │ │ │ └── jquery.min.map │ │ ├── jquery-3.5.1 │ │ │ ├── jquery-AUTHORS.txt │ │ │ ├── jquery.js │ │ │ ├── jquery.min.js │ │ │ └── jquery.min.map │ │ ├── plotly-binding-4.10.0 │ │ │ └── plotly.js │ │ ├── plotly-binding-4.10.1 │ │ │ └── plotly.js │ │ ├── plotly-binding-4.10.2 │ │ │ └── plotly.js │ │ ├── plotly-binding-4.9.2.1 │ │ │ └── plotly.js │ │ ├── plotly-binding-4.9.3 │ │ │ └── plotly.js │ │ ├── plotly-htmlwidgets-css-1.52.2 │ │ │ └── plotly-htmlwidgets.css │ │ ├── plotly-htmlwidgets-css-1.57.1 │ │ │ └── plotly-htmlwidgets.css │ │ ├── plotly-htmlwidgets-css-2.11.1 │ │ │ └── plotly-htmlwidgets.css │ │ ├── plotly-htmlwidgets-css-2.5.1 │ │ │ └── plotly-htmlwidgets.css │ │ ├── plotly-main-1.52.2 │ │ │ └── plotly-latest.min.js │ │ ├── plotly-main-1.57.1 │ │ │ └── plotly-latest.min.js │ │ ├── plotly-main-2.11.1 │ │ │ └── plotly-latest.min.js │ │ ├── plotly-main-2.5.1 │ │ │ └── plotly-latest.min.js │ │ └── typedarray-0.1 │ │ │ └── typedarray.min.js │ ├── SGP_files │ │ ├── anchor-sections-1.1.0 │ │ │ ├── anchor-sections-hash.css │ │ │ ├── anchor-sections-icon.css │ │ │ ├── anchor-sections-symbol.css │ │ │ ├── anchor-sections.css │ │ │ └── anchor-sections.js │ │ ├── header-attrs-2.13 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.14 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.22 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.25 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.7 │ │ │ └── header-attrs.js │ │ └── header-attrs-2.8 │ │ │ └── header-attrs.js │ ├── index.html │ └── releases │ │ ├── SGP-1.4-0.0.html │ │ ├── SGP-1.4-0.0_files │ │ ├── anchor-sections-1.1.0 │ │ │ ├── anchor-sections-hash.css │ │ │ ├── anchor-sections-icon.css │ │ │ ├── anchor-sections-symbol.css │ │ │ ├── anchor-sections.css │ │ │ └── anchor-sections.js │ │ ├── header-attrs-2.13 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.14 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.22 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.25 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.7 │ │ │ └── header-attrs.js │ │ └── header-attrs-2.8 │ │ │ └── header-attrs.js │ │ ├── SGP-1.5-0.0.html │ │ ├── SGP-1.5-0.0_files │ │ ├── anchor-sections-1.1.0 │ │ │ ├── anchor-sections-hash.css │ │ │ ├── anchor-sections-icon.css │ │ │ ├── anchor-sections-symbol.css │ │ │ ├── anchor-sections.css │ │ │ └── anchor-sections.js │ │ ├── header-attrs-2.13 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.14 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.22 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.25 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.7 │ │ │ └── header-attrs.js │ │ └── header-attrs-2.8 │ │ │ └── header-attrs.js │ │ ├── SGP-1.6-0.0.html │ │ ├── SGP-1.6-0.0_files │ │ ├── anchor-sections-1.1.0 │ │ │ ├── anchor-sections-hash.css │ │ │ ├── anchor-sections-icon.css │ │ │ ├── anchor-sections-symbol.css │ │ │ ├── anchor-sections.css │ │ │ └── anchor-sections.js │ │ ├── header-attrs-2.13 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.14 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.22 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.25 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.7 │ │ │ └── header-attrs.js │ │ └── header-attrs-2.8 │ │ │ └── header-attrs.js │ │ ├── SGP-1.7-0.0.html │ │ ├── SGP-1.7-0.0_files │ │ ├── anchor-sections-1.1.0 │ │ │ ├── anchor-sections-hash.css │ │ │ ├── anchor-sections-icon.css │ │ │ ├── anchor-sections-symbol.css │ │ │ ├── anchor-sections.css │ │ │ └── anchor-sections.js │ │ ├── header-attrs-2.13 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.14 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.22 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.25 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.7 │ │ │ └── header-attrs.js │ │ └── header-attrs-2.8 │ │ │ └── header-attrs.js │ │ ├── SGP-1.8-0.0.html │ │ ├── SGP-1.8-0.0_files │ │ ├── anchor-sections-1.1.0 │ │ │ ├── anchor-sections-hash.css │ │ │ ├── anchor-sections-icon.css │ │ │ ├── anchor-sections-symbol.css │ │ │ ├── anchor-sections.css │ │ │ └── anchor-sections.js │ │ ├── header-attrs-2.13 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.14 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.22 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.25 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.7 │ │ │ └── header-attrs.js │ │ └── header-attrs-2.8 │ │ │ └── header-attrs.js │ │ ├── SGP-1.9-0.0.html │ │ ├── SGP-1.9-0.0_files │ │ ├── anchor-sections-1.1.0 │ │ │ ├── anchor-sections-hash.css │ │ │ ├── anchor-sections-icon.css │ │ │ ├── anchor-sections-symbol.css │ │ │ ├── anchor-sections.css │ │ │ └── anchor-sections.js │ │ ├── header-attrs-2.13 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.14 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.22 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.25 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.7 │ │ │ └── header-attrs.js │ │ └── header-attrs-2.8 │ │ │ └── header-attrs.js │ │ ├── SGP-1.9-5.0.html │ │ ├── SGP-1.9-5.0_files │ │ ├── anchor-sections-1.1.0 │ │ │ ├── anchor-sections-hash.css │ │ │ ├── anchor-sections-icon.css │ │ │ ├── anchor-sections-symbol.css │ │ │ ├── anchor-sections.css │ │ │ └── anchor-sections.js │ │ ├── header-attrs-2.13 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.14 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.22 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.25 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.7 │ │ │ └── header-attrs.js │ │ └── header-attrs-2.8 │ │ │ └── header-attrs.js │ │ ├── SGP-2.0-0.0.html │ │ ├── SGP-2.0-0.0_files │ │ ├── anchor-sections-1.1.0 │ │ │ ├── anchor-sections-hash.css │ │ │ ├── anchor-sections-icon.css │ │ │ ├── anchor-sections-symbol.css │ │ │ ├── anchor-sections.css │ │ │ └── anchor-sections.js │ │ ├── header-attrs-2.22 │ │ │ └── header-attrs.js │ │ └── header-attrs-2.25 │ │ │ └── header-attrs.js │ │ ├── SGP-2.1-0.0.html │ │ └── SGP-2.1-0.0_files │ │ ├── anchor-sections-1.1.0 │ │ ├── anchor-sections-hash.css │ │ ├── anchor-sections-icon.css │ │ ├── anchor-sections-symbol.css │ │ ├── anchor-sections.css │ │ └── anchor-sections.js │ │ ├── header-attrs-2.22 │ │ └── header-attrs.js │ │ └── header-attrs-2.25 │ │ └── header-attrs.js ├── authors.html ├── img │ ├── REPO_CARD_image.png │ ├── favicon.png │ ├── link.svg │ ├── logo.png │ ├── logo.svg │ ├── logo_grey.png │ ├── logo_white.png │ └── tocBullet.svg ├── index.html ├── jquery.sticky-kit.min.js ├── link.svg ├── news │ └── index.html ├── packagePages.css ├── pkgdown.css ├── pkgdown.js └── reference │ ├── SGP-class.html │ ├── SGP-package.html │ ├── SGPstateData.html │ ├── abcSGP.html │ ├── analyzeSGP.html │ ├── baselineSGP.html │ ├── bubblePlot.html │ ├── bubblePlot_Styles.html │ ├── capwords.html │ ├── combineSGP.html │ ├── courseProgressionSGP.html │ ├── createKnotsBoundaries.html │ ├── getStateAbbreviation.html │ ├── gofPrint.html │ ├── gofSGP.html │ ├── growthAchievementPlot.html │ ├── index.html │ ├── outputSGP.html │ ├── prepareSGP.html │ ├── rliSGP.html │ ├── setNamesSGP.html │ ├── splineMatrix-class.html │ ├── studentGrowthPercentiles.html │ ├── studentGrowthPlot.html │ ├── studentGrowthPlot_Styles.html │ ├── studentGrowthProjections.html │ ├── summarizeSGP.html │ ├── testSGP.html │ ├── updateSGP.html │ └── visualizeSGP.html ├── inst ├── CITATION ├── NEWS └── doc │ ├── SGP.R │ ├── SGP.Rmd │ ├── SGP.html │ ├── SGP_Data_Analysis.R │ ├── SGP_Data_Analysis.Rmd │ ├── SGP_Data_Analysis.html │ ├── SGP_Data_Preparation.R │ ├── SGP_Data_Preparation.Rmd │ └── SGP_Data_Preparation.html ├── man ├── SGP-class.Rd ├── SGP-package.Rd ├── SGPstateData.Rd ├── abcSGP.Rd ├── analyzeSGP.Rd ├── baselineSGP.Rd ├── bubblePlot.Rd ├── bubblePlot_Styles.Rd ├── capwords.Rd ├── combineSGP.Rd ├── courseProgressionSGP.Rd ├── createKnotsBoundaries.Rd ├── createSuperCohortData.Rd ├── getStateAbbreviation.Rd ├── gofPrint.Rd ├── gofSGP.Rd ├── growthAchievementPlot.Rd ├── outputSGP.Rd ├── prepareSGP.Rd ├── rliSGP.Rd ├── setNamesSGP.Rd ├── splineMatrix-class.Rd ├── studentGrowthPercentiles.Rd ├── studentGrowthPlot.Rd ├── studentGrowthPlot_Styles.Rd ├── studentGrowthProjections.Rd ├── summarizeSGP.Rd ├── testSGP.Rd ├── updateSGP.Rd └── visualizeSGP.Rd └── vignettes ├── SGP.Rmd ├── SGP_Data_Analysis.Rmd ├── SGP_Data_Preparation.Rmd └── releases ├── SGP-1.4-0.0.Rmd ├── SGP-1.5-0.0.Rmd ├── SGP-1.6-0.0.Rmd ├── SGP-1.7-0.0.Rmd ├── SGP-1.8-0.0.Rmd ├── SGP-1.9-0.0.Rmd ├── SGP-1.9-5.0.Rmd ├── SGP-2.0-0.0.Rmd └── SGP-2.1-0.0.Rmd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^docs$ 2 | ^README\.md$ 3 | ^LICENSE.md 4 | ^\.appveyor\.yml$ 5 | ^vignettes/releases$ 6 | ^\.github$ 7 | ^CITATION\.cff$ 8 | ^_pkgdown\.yml$ 9 | ^\.git$ 10 | -------------------------------------------------------------------------------- /.appveyor.yml: -------------------------------------------------------------------------------- 1 | # DO NOT CHANGE the "init" and "install" sections below 2 | 3 | # Download script file from GitHub 4 | init: 5 | ps: | 6 | $ErrorActionPreference = "Stop" 7 | Invoke-WebRequest http://raw.github.com/krlmlr/r-appveyor/master/scripts/appveyor-tool.ps1 -OutFile "..\appveyor-tool.ps1" 8 | Import-Module '..\appveyor-tool.ps1' 9 | 10 | install: 11 | ps: Bootstrap 12 | 13 | cache: 14 | - C:\RLibrary 15 | 16 | # Adapt as necessary starting from here 17 | 18 | build_script: 19 | - travis-tool.sh install_deps 20 | 21 | test_script: 22 | - travis-tool.sh run_tests 23 | 24 | on_failure: 25 | - 7z a failure.zip *.Rcheck\* 26 | - appveyor PushArtifact failure.zip 27 | 28 | artifacts: 29 | - path: '*.Rcheck\**\*.log' 30 | name: Logs 31 | 32 | - path: '*.Rcheck\**\*.out' 33 | name: Logs 34 | 35 | - path: '*.Rcheck\**\*.fail' 36 | name: Logs 37 | 38 | - path: '*.Rcheck\**\*.Rout' 39 | name: Logs 40 | 41 | - path: '\*_*.tar.gz' 42 | name: Bits 43 | 44 | - path: '\*_*.zip' 45 | name: Bits 46 | -------------------------------------------------------------------------------- /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: [main, master] 4 | pull_request: 5 | branches: [main, master] 6 | 7 | name: R-CMD-check 8 | 9 | jobs: 10 | R-CMD-check: 11 | runs-on: ${{ matrix.config.os }} 12 | 13 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 14 | 15 | strategy: 16 | fail-fast: false 17 | matrix: 18 | config: 19 | - {os: macos-latest, r: 'release'} 20 | - {os: windows-latest, r: 'release'} 21 | - {os: ubuntu-latest, r: 'devel'} 22 | - {os: ubuntu-latest, r: 'release'} 23 | - {os: ubuntu-latest, r: 'oldrel-1'} 24 | 25 | env: 26 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 27 | R_KEEP_PKG_SOURCE: yes 28 | 29 | steps: 30 | - name: Install Homebrew 31 | if: runner.os == 'macOS' 32 | run: | 33 | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" 34 | 35 | - name: Install XQUARTZ dependencies on MacOS 36 | if: runner.os == 'macOS' 37 | run: | 38 | brew install --cask xquartz 39 | 40 | - uses: actions/checkout@v3 41 | 42 | - uses: r-lib/actions/setup-pandoc@v2 43 | 44 | - uses: r-lib/actions/setup-r@v2 45 | with: 46 | r-version: ${{ matrix.config.r }} 47 | http-user-agent: ${{ matrix.config.http-user-agent }} 48 | use-public-rspm: true 49 | 50 | # Cache R packages to speed up builds 51 | - name: Cache R packages 52 | uses: actions/cache@v3 53 | with: 54 | path: ~/.cache/R 55 | key: ${{ runner.os }}-r-${{ matrix.config.r }}-${{ hashFiles('**/DESCRIPTION') }} 56 | restore-keys: ${{ runner.os }}-r-${{ matrix.config.r }} 57 | 58 | - uses: r-lib/actions/setup-r-dependencies@v2 59 | with: 60 | extra-packages: any::rcmdcheck 61 | needs: check 62 | 63 | - uses: r-lib/actions/check-r-package@v2 64 | with: 65 | upload-snapshots: true -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | data/.DS_Store 2 | R/.Rhistory 3 | R/.DS_Store 4 | .DS_Store 5 | SGP.wiki 6 | .vscode 7 | -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | cff-version: 1.1.0 2 | message: "If you use the SGP Package, please cite it using these metadata." 3 | authors: 4 | - family-names: "Betebenner" 5 | given-names: "Damian" 6 | orcid: "https://orcid.org/0000-0003-0476-5599" 7 | - family-names: "VanIwaarden" 8 | given-names: "Adam" 9 | - family-names: "Domingue" 10 | given-names: "Ben" 11 | - family-names: "Shang" 12 | given-names: "Yi" 13 | title: "SGP: Student Growth Percentiles & Percentile Growth Trajectories" 14 | version: 2.2-1.9998 15 | doi: 10.5281/zenodo.10037891 16 | date-released: 2025-6-19 17 | url: "https://sgp.io" 18 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | export(abcSGP) 2 | export(analyzeSGP) 3 | export(as.splineMatrix) 4 | export(baselineSGP) 5 | export(bubblePlot) 6 | export(bubblePlot_Styles) 7 | export(capwords) 8 | export(combineSGP) 9 | export(courseProgressionSGP) 10 | export(createKnotsBoundaries) 11 | export(getStateAbbreviation) 12 | export(gofPrint) 13 | export(gofSGP) 14 | export(growthAchievementPlot) 15 | export(is.splineMatrix) 16 | export(is.SGP) 17 | export(outputSGP) 18 | export(prepareSGP) 19 | export(rliSGP) 20 | export(setNamesSGP) 21 | export(studentGrowthPercentiles) 22 | export(studentGrowthPlot) 23 | export(studentGrowthPlot_Styles) 24 | export(studentGrowthProjections) 25 | export(summarizeSGP) 26 | export(testSGP) 27 | export(updateSGP) 28 | export(visualizeSGP) 29 | exportClasses(SGP) 30 | exportClasses(splineMatrix) 31 | import(data.table) 32 | import(datasets) 33 | import(grid) 34 | import(methods) 35 | importFrom(Cairo,Cairo,CairoSVG) 36 | importFrom(callr,r_bg) 37 | importFrom(collapse, add_stub, add_vars, collapv, ffirst, fmean, fmedian, fnrow, fsd, ftransform, ftransformv, fvar, get_vars, join, na_omit, pivot, .quantile, replace_outliers, roworderv, rm_stub) 38 | importFrom(colorspace,rainbow_hcl,diverge_hcl) 39 | importFrom(crayon,bold,cyan,green,magenta,red,yellow) 40 | importFrom(curl,curl_fetch_memory,new_handle) 41 | importFrom(digest,digest) 42 | importFrom(doParallel,registerDoParallel) 43 | importFrom(equate,freqtab,equate) 44 | importFrom(foreach,'%dopar%',foreach,registerDoSEQ,getDoParName,setDoPar) 45 | importFrom(graphics,par,plot,text) 46 | importFrom(grDevices,colorRampPalette,col2rgb,dev.off,extendrange,hsv,pdf,rgb,rgb2hsv) 47 | importFrom(gridBase,gridFIG) 48 | importFrom(gtools,mixedsort) 49 | importFrom(iterators,iter) 50 | importFrom(jsonlite,toJSON) 51 | importFrom(matrixStats,weightedMedian) 52 | importFrom(parallel,clusterApplyLB,clusterEvalQ,clusterExport,detectCores,makeCluster,makePSOCKcluster,mclapply,parLapplyLB,parLapply,stopCluster) 53 | importFrom(quantreg,rq) 54 | importFrom(randomNames,randomNames) 55 | importFrom(rngtools,getRNG,setRNG,RNGseed,RNGseq,RNGtype,showRNG) 56 | importFrom(RSQLite,dbGetQuery,dbWriteTable,dbConnect,dbDisconnect,dbListFields,dbSendQuery,dbListResults,dbClearResult,SQLite) 57 | importFrom(sn,rsn) 58 | importFrom(splines,bs) 59 | importFrom(svglite,svglite) 60 | importFrom(stats,approx,approxfun,lm,median,na.omit,ppoints,predict,quantile,reshape,rnorm,runif,sd,spline,splinefun,stepfun,var,weighted.mean,cor) 61 | importFrom(toOrdinal,toOrdinal) 62 | importFrom(utils,compareVersion,Rprof,head,object.size,packageVersion,read.table,recover,tail,type.convert,unzip,write.table,zip) 63 | -------------------------------------------------------------------------------- /R/SGP-class.R: -------------------------------------------------------------------------------- 1 | setClassUnion("list.null", c("list","NULL")) 2 | 3 | setOldClass(c('data.frame')) 4 | setOldClass(c('data.table', 'data.frame')) 5 | setClass("SGP", representation(Data="data.table", Data_Supplementary="list.null", Names="list.null", SGP="list.null", Summary="list.null", Version="list.null")) 6 | 7 | .Valid.SGP <- function(object) { 8 | out <- NULL 9 | 10 | ## RUN A SET OF CHECKS ON THE SPECIFIED VARIABLES TO ENSURE THAT THE 11 | ## SCORES ARE WITHIN ACCEPTABLE LIMITS AND THE VARIABLES HAVE THE 12 | ## PROPER VARIABLE TYPE 13 | 14 | if (is.null(out)) out <- TRUE 15 | return(out) 16 | 17 | } 18 | setValidity("SGP", .Valid.SGP) 19 | -------------------------------------------------------------------------------- /R/capwords.R: -------------------------------------------------------------------------------- 1 | `capwords` <- 2 | function( 3 | x, 4 | special.words = c("ELA", "I", "II", "III", "IV", "CCSD", "CUSD", "CUD", "USD", "PSD", "UD", "ESD", "DCYF", "EMH", "HS", "MS", "ES", "SES", "IEP", "ELL", "MAD", "PARCC", "SBAC", "SD", "SWD", "US", "SGP", "SIMEX", "SS", "SAT", "PSAT", "WIDA", "ACCESS", "WIDA-ACCESS") 5 | ) { 6 | if (is.null(x)) return(NULL) 7 | if (is.na(x)) return(NA) 8 | if (identical(x, " ")) return(" ") 9 | 10 | # Basic cleaning: replace underscores, periods, and extra spaces 11 | x <- gsub("[_.]", " ", x) 12 | x <- gsub("\\s+", " ", trimws(x)) # Trim and reduce multiple spaces 13 | 14 | # Helper function to capitalize while respecting special words and numbers 15 | capitalize_words <- function(word) { 16 | # Handle special words 17 | if (word %in% special.words) { 18 | return(word) 19 | } else if (grepl("^[0-9]+(\\.[0-9]+)?$", word)) { # Check for numbers 20 | return(word) 21 | } else { 22 | # Capitalize the first letter only 23 | return(paste0(toupper(substring(word, 1, 1)), tolower(substring(word, 2)))) 24 | } 25 | } 26 | 27 | # Split words and process each, handling punctuation (hyphens, apostrophes) 28 | words <- unlist(strsplit(x, "(?=[\\s'-])|(?<=[\\s'-])", perl = TRUE)) 29 | result <- sapply(words, capitalize_words) 30 | 31 | # Combine processed words and fix spacing around punctuation 32 | s.new <- paste(result, collapse = "") 33 | s.new <- gsub("\\s+([)-])", "\\1", gsub("([(])\\s+", "\\1", s.new)) 34 | 35 | return(s.new) 36 | } ### END capwords -------------------------------------------------------------------------------- /R/checksplineMatrix.R: -------------------------------------------------------------------------------- 1 | `checksplineMatrix` <- 2 | function(list.of.splineMatrix, 3 | sgp_object=NULL, 4 | state=NULL, 5 | content_area=NULL, 6 | year=NULL) { 7 | 8 | if (is.splineMatrix(list.of.splineMatrix)) { 9 | list.of.splineMatrix <- list(list.of.splineMatrix) 10 | } 11 | for (i in names(list.of.splineMatrix)) { 12 | if (!grepl("SIMEX", i)) { 13 | if (!grepl("BASELINE", i) || is.null(state) || is.null(SGP::SGPstateData[[state]][['Baseline_splineMatrix']])) { 14 | splineMatrix.tf <- sapply(list.of.splineMatrix[[i]], validObject, test=TRUE)==TRUE 15 | if (!all(splineMatrix.tf)) { 16 | content_area <- unlist(strsplit(i, "[.]"))[1]; year <- unlist(strsplit(i, "[.]"))[2] 17 | for (j in names(list.of.splineMatrix[[i]])[!splineMatrix.tf]) { 18 | message(paste("\tNOTE: Updating Coefficient Matrix", i, j, "to new splineMatrix class.")) 19 | list.of.splineMatrix[[i]][[j]] <- 20 | as.splineMatrix(matrix_argument=list.of.splineMatrix[[i]][[j]], matrix_argument_name=j, content_area=content_area, year=year, sgp_object=sgp_object) 21 | } 22 | } 23 | list.of.splineMatrix[[i]] <- uniquesplineMatrix(list.of.splineMatrix[[i]]) 24 | } else { 25 | list.of.splineMatrix[[i]] <- SGP::SGPstateData[[state]][['Baseline_splineMatrix']][['Coefficient_Matrices']][[i]] 26 | } 27 | } else { 28 | for (grd_ord in names(list.of.splineMatrix[[i]])) { 29 | for (lambda in grep("lambda", names(list.of.splineMatrix[[i]][[grd_ord]]), value=TRUE)) { 30 | splineMatrix.tf <- sapply(list.of.splineMatrix[[i]][[grd_ord]][[lambda]], validObject, test=TRUE)==TRUE 31 | if (!all(splineMatrix.tf)) { 32 | content_area <- unlist(strsplit(i, "[.]"))[1]; year <- unlist(strsplit(i, "[.]"))[2] 33 | for (j in names(list.of.splineMatrix[[i]][[grd_ord]][[lambda]])[!splineMatrix.tf]) { 34 | message(paste("\tNOTE: Updating Coefficient Matrix", i, grd_ord, lambda, j, "to new splineMatrix class.")) 35 | list.of.splineMatrix[[i]][[grd_ord]][[lambda]][[j]] <- 36 | as.splineMatrix(matrix_argument=list.of.splineMatrix[[i]][[grd_ord]][[lambda]][[j]], matrix_argument_name=j, content_area=content_area, year=year, sgp_object=sgp_object) 37 | } 38 | } 39 | list.of.splineMatrix[[i]][[grd_ord]][[lambda]] <- uniquesplineMatrix(list.of.splineMatrix[[i]][[grd_ord]][[lambda]]) 40 | } 41 | } 42 | } 43 | } 44 | return(list.of.splineMatrix) 45 | } ### END checksplineMatrix 46 | -------------------------------------------------------------------------------- /R/convertScaleScore.R: -------------------------------------------------------------------------------- 1 | `convertScaleScore` <- 2 | function(tmp.data.for.equate, 3 | tmp.year.for.equate, 4 | equate.list, 5 | conversion.type, 6 | equating.method, 7 | state) { 8 | 9 | SCALE_SCORE <- TEMP_SCALE_SCORE_EQUATED <- GRADE <- CONTENT_AREA <- YEAR <- NULL 10 | 11 | ### Define variables 12 | 13 | tmp.unique.years <- unique(tmp.data.for.equate[['YEAR']]) 14 | 15 | if (conversion.type=="NEW_TO_OLD") { 16 | tmp.years.for.equate <- sort(tmp.unique.years[tmp.unique.years >= tmp.year.for.equate]) 17 | } else { 18 | tmp.years.for.equate <- sort(tmp.unique.years[tmp.unique.years < tmp.year.for.equate]) 19 | } 20 | if (paste("SCALE_SCORE_EQUATED", equating.method, conversion.type, sep="_") %in% names(tmp.data.for.equate)) tmp.data.for.equate[,paste("SCALE_SCORE_EQUATED", equating.method, conversion.type, sep="_"):=NULL] 21 | 22 | if (!is.null(SGP::SGPstateData[[state]][["Assessment_Program_Information"]][["Assessment_Transition"]][["Equated_Content_Areas_and_Grades"]])) { 23 | equating.content_areas.grades <- SGP::SGPstateData[[state]][["Assessment_Program_Information"]][["Assessment_Transition"]][["Equated_Content_Areas_and_Grades"]] 24 | } else { 25 | equating.content_areas.grades <- lapply(equate.list, names) 26 | names(equating.content_areas.grades) <- sapply(strsplit(names(equating.content_areas.grades), '[.]'), '[', 1) 27 | for (tmp.iter in seq_along(equating.content_areas.grades)) { 28 | equating.content_areas.grades[[tmp.iter]] <- gsub("GRADE_", "", equating.content_areas.grades[[tmp.iter]]) 29 | } 30 | } 31 | 32 | 33 | ### Create scale.score.concordance lookup 34 | 35 | for (content_area.iter in names(equating.content_areas.grades)) { 36 | for (grade.iter in equating.content_areas.grades[[content_area.iter]]) { 37 | tmp.data.for.equate[YEAR %in% tmp.years.for.equate & CONTENT_AREA==content_area.iter & GRADE==grade.iter, 38 | TEMP_SCALE_SCORE_EQUATED:=equate.list[[paste(content_area.iter, tmp.year.for.equate, sep=".")]][[paste("GRADE", grade.iter, sep="_")]][[toupper(equating.method)]][[conversion.type]][['interpolated_function']](SCALE_SCORE)] 39 | } 40 | } 41 | 42 | tmp.data.for.equate[!YEAR %in% tmp.years.for.equate, TEMP_SCALE_SCORE_EQUATED:=SCALE_SCORE] 43 | tmp.data.for.equate[is.na(TEMP_SCALE_SCORE_EQUATED) & !is.na(SCALE_SCORE), TEMP_SCALE_SCORE_EQUATED:=SCALE_SCORE] 44 | setnames(tmp.data.for.equate, "TEMP_SCALE_SCORE_EQUATED", paste("SCALE_SCORE_EQUATED", toupper(equating.method), conversion.type, sep="_")) 45 | 46 | return(tmp.data.for.equate) 47 | } ### END convertScaleScore function 48 | -------------------------------------------------------------------------------- /R/convertTime.R: -------------------------------------------------------------------------------- 1 | `convertTime` <- 2 | function(tmp.time) { 3 | tmp <- tail(c(0, 0, 0, as.numeric(unlist(strsplit(tmp.time, ":")))), 4) 4 | tmp.label <- c("Day", "Hour", "Minute", "Second") 5 | tmp.label[which(tmp!=1)] <- paste0(tmp.label, "s")[which(tmp!=1)] 6 | return(paste(paste(tmp[tmp!=0], tmp.label[tmp!=0]), collapse=", ")) 7 | } ### END convertTime 8 | -------------------------------------------------------------------------------- /R/createKnotsBoundaries.R: -------------------------------------------------------------------------------- 1 | `createKnotsBoundaries` <- 2 | function(tmp.data, 3 | knot.cut.percentiles=c(0.2,0.4,0.6,0.8)) { 4 | 5 | CONTENT_AREA <- GRADE <- VALID_CASE <- NULL 6 | 7 | tmp.grade.list <- tmp.list <- list() 8 | 9 | setkeyv(tmp.data, c("VALID_CASE", "CONTENT_AREA", "GRADE")) 10 | 11 | for (my.list.label in unique(tmp.data["VALID_CASE"], by="CONTENT_AREA")[["CONTENT_AREA"]]) { 12 | tmp.grade.list[[my.list.label]] <- sort(unique(tmp.data[SJ("VALID_CASE", my.list.label)], by="GRADE")[["GRADE"]]) 13 | for (j in seq_along(tmp.grade.list[[my.list.label]])) { 14 | tmp.list[[my.list.label]][[3*j-2]] <- 15 | round(quantile(tmp.data[list("VALID_CASE", my.list.label, tmp.grade.list[[my.list.label]][j])][["SCALE_SCORE"]], 16 | probs=knot.cut.percentiles, na.rm=TRUE, names=FALSE), digits=3) 17 | tmp.list[[my.list.label]][[3*j-1]] <- 18 | round(extendrange(tmp.data[list("VALID_CASE", my.list.label, tmp.grade.list[[my.list.label]][j])][["SCALE_SCORE"]], f=0.1), digits=3) 19 | tmp.list[[my.list.label]][[3*j]] <- 20 | round(extendrange(tmp.data[list("VALID_CASE", my.list.label, tmp.grade.list[[my.list.label]][j])][["SCALE_SCORE"]], f=0.0), digits=3) 21 | } 22 | setattr(tmp.list[[my.list.label]], "names", paste0(rep(c("knots_", "boundaries_", "loss.hoss_"), length(tmp.grade.list[[my.list.label]])), 23 | rep(tmp.grade.list[[my.list.label]], each=3))) 24 | } 25 | 26 | return(tmp.list) 27 | } ## END createKnotsBoundaries 28 | -------------------------------------------------------------------------------- /R/createSuperCohortData.R: -------------------------------------------------------------------------------- 1 | `createSuperCohortData` <- 2 | function( 3 | base_data, 4 | sgp.config, 5 | supercohort_base_years, ## Subset of years of supplied_base data to use for super-cohort construction 6 | indicate_cohort=FALSE 7 | ) { 8 | 9 | YEAR <- CONTENT_AREA <- GRADE <- YEAR_NEW <- COHORT <- ID <- NULL 10 | 11 | ### Parameters 12 | data.years <- sort(unique(base_data$YEAR)) 13 | tmp.cohort.list <- list() 14 | 15 | ### Test parameters 16 | if (!missing(supercohort_base_years) && !all(supercohort_base_years %in% data.years)) stop("Note: supercohort_base_years supplied not all in years provided in base_data.") 17 | 18 | ### Use supercohort_base_years to filter data if it is provided. 19 | if (!missing(supercohort_base_years)) base_data <- base_data[YEAR %in% supercohort_base_years] 20 | 21 | ### Loop over configurations 22 | for (sgp.config.iter in sgp.config) { 23 | tmp.list <- list() 24 | for (data.years.iter in 1:(length(data.years) - sum(sgp.config.iter[['sgp.grade.sequences.lags']]))) { 25 | grade_year_content_area_map <- data.table( 26 | CONTENT_AREA = sgp.config.iter[['sgp.content.areas']], 27 | YEAR = data.years[c(data.years.iter, data.years.iter + (cumsum(sgp.config.iter[['sgp.grade.sequences.lags']])))], 28 | GRADE = sgp.config.iter[['sgp.grade.sequences']], 29 | YEAR_NEW = tail(data.years, length(sgp.config.iter[['sgp.content.areas']]))) 30 | 31 | tmp.list[[data.years.iter]] <- base_data[grade_year_content_area_map, on=list(CONTENT_AREA, YEAR, GRADE)][,YEAR:=YEAR_NEW][,YEAR_NEW:=NULL] 32 | 33 | if (indicate_cohort) { 34 | tmp.list[[data.years.iter]][,COHORT:=paste(unlist(grade_year_content_area_map[,1:3]), collapse="_")] 35 | } 36 | 37 | tmp.dt <- rbindlist(tmp.list) 38 | setkey(tmp.dt, YEAR, GRADE, ID) 39 | tmp.dt <- tmp.dt[unique(tmp.dt[, .(YEAR, GRADE, ID)]), mult="last"] ### Remove duplicates created by collapsing data into YEAR_NEW taking LAST (most recent) case 40 | } 41 | 42 | tmp.cohort.list[[paste(sgp.config.iter[['sgp.content.areas']][1], paste(sgp.config.iter[['sgp.grade.sequences']], collapse=""), sep="_")]] <- tmp.dt 43 | } 44 | return(rbindlist(tmp.cohort.list)) 45 | } ### END createSuperCohortData 46 | -------------------------------------------------------------------------------- /R/csemScoreSimulator.R: -------------------------------------------------------------------------------- 1 | csemScoreSimulator <- 2 | function( 3 | scale_scores, 4 | grade, 5 | content_area, 6 | year, 7 | state, 8 | variable=NULL, 9 | distribution=NULL, 10 | round.digits=NULL) { 11 | 12 | GRADE <- CONTENT_AREA <- YEAR <- SIM <- V1 <- NULL 13 | 14 | get.my.knots.boundaries <- function(content_area, year) { 15 | tmp.knots.boundaries.names <- grep(content_area, names(SGP::SGPstateData[[state]][["Achievement"]][["Knots_Boundaries"]]), value=TRUE) 16 | tmp.knots.boundaries <- tmp.knots.boundaries.names[grep(paste0("^", content_area, "$"), sapply(strsplit(tmp.knots.boundaries.names, "[.]"), '[', 1L))] 17 | if (length(tmp.knots.boundaries)==1L) { 18 | return(content_area) 19 | } else { 20 | tmp.knots.boundaries.years <- sapply(strsplit(tmp.knots.boundaries, "[.]"), '[', 2L) 21 | tmp.index <- sum(year >= tmp.knots.boundaries.years, na.rm=TRUE) 22 | return(paste(c(content_area, sort(tmp.knots.boundaries.years)[tmp.index]), collapse=".")) 23 | } 24 | } 25 | 26 | ### Define relevant variables 27 | 28 | if (is.null(round.digits)) round.digits <- 1L 29 | if (is.null(distribution)) distribution <- "Normal" 30 | if (!is.null(state)) { 31 | min.max <- SGP::SGPstateData[[state]][["Achievement"]][["Knots_Boundaries"]][[get.my.knots.boundaries(content_area, year)]][[paste0("loss.hoss_", grade)]] 32 | } else { 33 | min.max <- range(scale_scores, na.rm=TRUE) 34 | } 35 | Interpolation_Function <- function(scale_score, variance, round.digits) return(splinefun(scale_score, variance/sqrt(round.digits), method="natural")) 36 | 37 | ### Create scale score dependent CSEMs 38 | 39 | if (is.null(variable) && !is.null(state)) { 40 | if ("YEAR" %in% names(SGP::SGPstateData[[state]][["Assessment_Program_Information"]][["CSEM"]])) { 41 | Interpolation_Data <- SGP::SGPstateData[[state]][["Assessment_Program_Information"]][["CSEM"]][GRADE==grade & CONTENT_AREA==content_area & YEAR==year] 42 | } else { 43 | Interpolation_Data <- SGP::SGPstateData[[state]][["Assessment_Program_Information"]][["CSEM"]][GRADE==grade & CONTENT_AREA==content_area] 44 | } 45 | tmp.omega <- Interpolation_Function(Interpolation_Data[['SCALE_SCORE']], Interpolation_Data[['SCALE_SCORE_CSEM']], round.digits)(scale_scores) 46 | } 47 | if (!is.null(variable)) { 48 | tmp.dt <- setkey(unique(data.table(V1=scale_scores, V2=variable), by="V1"), V1) 49 | tmp.omega <- Interpolation_Function(tmp.dt[['V1']], tmp.dt[['V2']], round.digits)(scale_scores) 50 | } 51 | if (distribution=="Skew-Normal") { 52 | tmp.scores <- data.table(SIM=round(rsn(length(scale_scores), xi=scale_scores, omega=tmp.omega, 53 | alpha=tan((pi/2)*((min.max[1]+min.max[2]) - 2*scale_scores)/(min.max[2]-min.max[1]))), digits=round.digits)) 54 | } else { 55 | tmp.scores <- data.table(SIM=round(rnorm(length(scale_scores), scale_scores, tmp.omega), digits=round.digits)) 56 | } 57 | 58 | tmp.scores[SIM < min.max[1L] | SIM > min.max[2L], SIM:=fifelse(SIM < min.max[1L], min.max[1L], min.max[2L])] 59 | return(tmp.scores[['SIM']]) 60 | } ### END csemScoreSimulator 61 | -------------------------------------------------------------------------------- /R/ddcast.R: -------------------------------------------------------------------------------- 1 | `ddcast` <- 2 | function(tmp.dt, ...) { 3 | if (dim(tmp.dt)[1L]==0L) { 4 | return(data.table(NULL)) 5 | } else { 6 | dcast(tmp.dt, ...) 7 | } 8 | } ### END ddcast Function 9 | -------------------------------------------------------------------------------- /R/detectSGPCores.R: -------------------------------------------------------------------------------- 1 | `detectSGPCores` <- 2 | function(logical=TRUE) { 3 | return(min(detectCores(logical=logical), 50L)) 4 | } ### END detectSGPCores Function 5 | -------------------------------------------------------------------------------- /R/getCohortDataInfo.R: -------------------------------------------------------------------------------- 1 | `getCohortDataInfo` <- 2 | function(sgp.data, 3 | par.sgp.config) { 4 | 5 | for (sgp.iter in seq(length(par.sgp.config))) { 6 | tmp.grades.names <- paste("GRADE", tail(par.sgp.config[[sgp.iter]][['sgp.panel.years']], 2), tail(par.sgp.config[[sgp.iter]][['sgp.content.areas']], 2), sep=".") 7 | tmp.scale_scores.names <- paste("SCALE_SCORE", tail(par.sgp.config[[sgp.iter]][['sgp.panel.years']], 2), tail(par.sgp.config[[sgp.iter]][['sgp.content.areas']], 2), sep=".") 8 | tmp.data <- getPanelData(sgp.data, "sgp.percentiles", par.sgp.config[[sgp.iter]]) 9 | if (all(c(tmp.grades.names, tmp.scale_scores.names) %in% names(tmp.data))) { 10 | par.sgp.config[[sgp.iter]][['number_of_1_prior_cases']] <- dim(na.omit(tmp.data[,c("ID", tmp.grades.names, tmp.scale_scores.names), with=FALSE]))[1] 11 | } else { 12 | par.sgp.config[[sgp.iter]][['number_of_1_prior_cases']] <- 0 13 | } 14 | } 15 | return(par.sgp.config) 16 | } ### END getCohortDataInfo 17 | -------------------------------------------------------------------------------- /R/getErrorReports.R: -------------------------------------------------------------------------------- 1 | `getErrorReports` <- 2 | function(tmp, 3 | tmp.tf, 4 | par.sgp.config) { 5 | 6 | tmp.errors <- tmp[tmp.tf] 7 | tmp.config <- par.sgp.config[tmp.tf] 8 | tmp.error.report <- list() 9 | for (i in 1:length(tmp.errors)) tmp.error.report[[i]] <- list(Error=tmp.errors[[i]], Analysis=tmp.config[[i]]) 10 | return(tmp.error.report) 11 | 12 | } ### END getErrorReports 13 | -------------------------------------------------------------------------------- /R/getFirstAndLastInGroup.R: -------------------------------------------------------------------------------- 1 | `getFirstAndLastInGroup` <- 2 | function(DT) { 3 | VALID_CASE <- YEAR <- CONTENT_AREA <- FIRST_OBSERVATION <- LAST_OBSERVATION <- ID <- GRADE <- YEAR_WITHIN <- NULL 4 | setkey(DT, VALID_CASE, CONTENT_AREA, YEAR, GRADE, ID, YEAR_WITHIN) 5 | setkey(DT, VALID_CASE, CONTENT_AREA, YEAR, GRADE, ID) 6 | DT[DT[unique(DT["VALID_CASE"], by=key(DT)),,mult="first", which=TRUE], FIRST_OBSERVATION:=1L] 7 | DT[DT[unique(DT["VALID_CASE"], by=key(DT)),,mult="last", which=TRUE], LAST_OBSERVATION:=1L] 8 | return(DT) 9 | } ### END getFirstAndLastInGroup 10 | -------------------------------------------------------------------------------- /R/getHighNeedStatus.R: -------------------------------------------------------------------------------- 1 | `getHighNeedStatus` <- 2 | function(sgp_object) { 3 | 4 | ID <- CONTENT_AREA <- YEAR_INT <- PRIOR_GRADE <- GRADE <- SCALE_SCORE <- PRIOR_SCALE_SCORE <- HIGH_NEED_STATUS <- VALID_CASE <- SCHOOL_NUMBER <- YEAR <- NULL 5 | 6 | # my.quantile.function producing HIGH_NEED_STATUS variable 7 | 8 | my.quantile.function <- function(x, invalid_cases, quantiles=c(0.25, 0.75)) { 9 | high.needs.status.labels <- c(paste0("High Needs Status: Prior Achievement Below ", 100*quantiles[1], "th Percentile"), 10 | NA, paste0("High Needs Status: Prior Achievement Above ", 100*quantiles[2], "th Percentiles")) 11 | if (invalid_cases) { 12 | return(rep(NA_character_, length(x))) 13 | } 14 | if (all(is.na(x))) { 15 | return(rep(NA_character_, length(x))) 16 | } else { 17 | if (any(diff(quantile(x, probs=c(0, quantiles, 1), na.rm=TRUE))==0)) { 18 | return(rep(NA_character_, length(x))) 19 | } else { 20 | return(high.needs.status.labels[cut(x, quantile(x, probs=c(0, quantiles, 1), na.rm=TRUE), include.lowest=TRUE, labels=FALSE)]) 21 | } 22 | } 23 | } ### END my.quantile.function 24 | 25 | 26 | slot.data <- copy(sgp_object@Data) 27 | slot.data[,YEAR_INT:=as.integer(factor(YEAR))] 28 | setkeyv(slot.data, c("ID", "CONTENT_AREA", "YEAR_INT", "VALID_CASE")) 29 | slot.data[,c("PRIOR_SCALE_SCORE", "PRIOR_GRADE"):=slot.data[SJ(ID, CONTENT_AREA, YEAR_INT-1L), mult="last"][,list(SCALE_SCORE, GRADE)]] 30 | setkeyv(slot.data, c("VALID_CASE", "CONTENT_AREA", "YEAR_INT", "SCHOOL_NUMBER", "PRIOR_GRADE", "ID")) 31 | slot.data[,HIGH_NEED_STATUS:=slot.data[,my.quantile.function(PRIOR_SCALE_SCORE, !VALID_CASE[1]=="VALID_CASE"), 32 | keyby=list(VALID_CASE, CONTENT_AREA, YEAR_INT, SCHOOL_NUMBER, PRIOR_GRADE)][['V1']]] 33 | slot.data[,HIGH_NEED_STATUS:=as.factor(HIGH_NEED_STATUS)] 34 | slot.data[,c("PRIOR_SCALE_SCORE", "PRIOR_GRADE", "YEAR_INT"):=NULL] 35 | setkey(slot.data, VALID_CASE, CONTENT_AREA, YEAR, ID) 36 | sgp_object@Data <- slot.data 37 | if (!is.null(sgp_object@Names) && !"HIGH_NEED_STATUS" %in% sgp_object@Names[['names.sgp']]) { 38 | sgp_object@Names <- rbind(sgp_object@Names, c("HIGH_NEED_STATUS", "HIGH_NEED_STATUS", "demographic", "High need status flag", TRUE)) 39 | } 40 | messageSGP("\tNOTE: Added variable HIGH_NEED_STATUS to @Data.") 41 | return(sgp_object) 42 | } ### END getHighNeedStatus 43 | -------------------------------------------------------------------------------- /R/getKey.R: -------------------------------------------------------------------------------- 1 | `getKey` <- 2 | function(sgp_object) { 3 | if (is.SGP(sgp_object)) { 4 | if ("YEAR_WITHIN" %in% names(sgp_object@Data)) return(c("VALID_CASE", "CONTENT_AREA", "YEAR", "GRADE", "ID", "YEAR_WITHIN")) else return(c("VALID_CASE", "CONTENT_AREA", "YEAR", "GRADE", "ID")) 5 | } 6 | if (is.data.table(sgp_object)) { 7 | if ("YEAR_WITHIN" %in% names(sgp_object)) return(c("VALID_CASE", "CONTENT_AREA", "YEAR", "GRADE", "ID", "YEAR_WITHIN")) else return(c("VALID_CASE", "CONTENT_AREA", "YEAR", "GRADE", "ID")) 8 | } 9 | } ### END getKey 10 | -------------------------------------------------------------------------------- /R/getMaxOrderForProgression.R: -------------------------------------------------------------------------------- 1 | `getMaxOrderForProgression` <- 2 | function(year, 3 | content_area, 4 | state, 5 | sgp.projections.equated) { 6 | 7 | if (is.null(SGP::SGPstateData[[state]][["Assessment_Program_Information"]][["Scale_Change"]][[content_area]])) { 8 | return(SGP::SGPstateData[[state]][["SGP_Configuration"]][["max.order.for.projection"]]) ## Returns NULL if it doesn't exist 9 | } else { 10 | if (is.null(sgp.projections.equated)) { 11 | tmp <- as.numeric(tail(unlist(strsplit(as.character(year), "_")), 1)) - 12 | as.numeric(tail(unlist(strsplit(as.character(SGP::SGPstateData[[state]][["Assessment_Program_Information"]][["Scale_Change"]][[content_area]]), "_")), 1)) 13 | if (tmp < 0) return(SGP::SGPstateData[[state]][["SGP_Configuration"]][["max.order.for.projection"]]) 14 | if (tmp > 0) return(min(c(as.numeric(tmp), SGP::SGPstateData[[state]][["SGP_Configuration"]][["max.order.for.projection"]]))) 15 | if (tmp==0 && 16 | !identical(SGP::SGPstateData[[state]][["Assessment_Program_Information"]][["Assessment_Transition"]][["Baseline_Projections_in_Transition_Year"]], TRUE)) { 17 | message(paste0("\tNOTE: Based upon state scale changes in ", year, ". student growth projections are not possible. No student growth projections will be generated")) 18 | } 19 | } else { 20 | return(SGP::SGPstateData[[state]][["SGP_Configuration"]][["max.order.for.projection"]]) ## Returns NULL if it doesn't exist 21 | } 22 | } 23 | } ### getMaxOrderForProgression 24 | -------------------------------------------------------------------------------- /R/getMyLabel.R: -------------------------------------------------------------------------------- 1 | `getMyLabel` <- 2 | function(state, 3 | content_area, 4 | year, 5 | label="Cutscores") { 6 | 7 | tmp.cutscore.years <- unlist(lapply(sapply(strsplit(grep(content_area, names(SGP::SGPstateData[[state]][["Achievement"]][[label]]), value=TRUE), "[.]"), tail, -1), paste, collapse=".")) 8 | tmp.cutscore.years[tmp.cutscore.years==""] <- NA 9 | if (any(!is.na(tmp.cutscore.years))) { 10 | if (year %in% tmp.cutscore.years) { 11 | return(paste(content_area, year, sep=".")) 12 | } else { 13 | if (year==sort(c(year, tmp.cutscore.years))[1]) { 14 | return(content_area) 15 | } else { 16 | return(paste(content_area, sort(tmp.cutscore.years)[which(year==sort(c(year, tmp.cutscore.years)))-1], sep=".")) 17 | } 18 | } 19 | } else { 20 | return(content_area) 21 | } 22 | } ## END getMyLabel Function 23 | -------------------------------------------------------------------------------- /R/getNewCutscores.R: -------------------------------------------------------------------------------- 1 | `getNewCutscores` <- 2 | function(content_area, 3 | content_area_label, 4 | year, 5 | grade, 6 | state, 7 | Cutscores) { 8 | 9 | 10 | ### Utility function 11 | 12 | get.cutscore.year <- function(year, cutscore.years) { 13 | if (year %in% cutscore.years) return(year) 14 | if (year==sort(c(year, cutscore.years))[1]) return(as.character(NA)) 15 | return(sort(cutscore.years)[which(year==sort(c(year, cutscore.years)))-1]) 16 | } 17 | 18 | 19 | ### Define variables 20 | 21 | if (!is.na(tmp.index <- match(content_area, names(SGP::SGPstateData[[state]][["Student_Report_Information"]][["Content_Areas_Domains"]])))) { 22 | content_area_domain <- SGP::SGPstateData[[state]][["Student_Report_Information"]][["Content_Areas_Domains"]][[tmp.index]] 23 | } else { 24 | content_area_domain <- content_area 25 | } 26 | 27 | cutscore.year <- get.cutscore.year(year, unique(Cutscores[[content_area_domain]][content_area][['YEAR']])) 28 | 29 | if (year %in% SGP::SGPstateData[[state]][["Student_Report_Information"]][["Transformed_Achievement_Level_Cutscores"]][[content_area]]) { 30 | tmp.cutscore.label <- "CUTSCORES_TRANSFORMED" 31 | } else { 32 | tmp.cutscore.label <- "CUTSCORES" 33 | } 34 | 35 | 36 | ### Return result 37 | 38 | if (is.na(content_area) | is.na(grade)) { 39 | return(NULL) 40 | } else { 41 | return(sort(Cutscores[[content_area_domain]][list(content_area_label, cutscore.year, grade)][[tmp.cutscore.label]])) 42 | } 43 | } ### END getNewCutscores function 44 | -------------------------------------------------------------------------------- /R/getSGPColor.R: -------------------------------------------------------------------------------- 1 | `getSGPColor` <- 2 | function( 3 | sgp, 4 | type) { 5 | 6 | if (toupper(type)=="PRESENTATION") { 7 | return(colorRampPalette(c("red","yellow3","springgreen","royalblue"))(99)[sgp]) 8 | } 9 | if (toupper(type)=="PRINT") { 10 | return(colorRampPalette(c("red","yellow3","springgreen","royalblue"))(99)[sgp]) 11 | } 12 | } ### END getSGPColor function 13 | -------------------------------------------------------------------------------- /R/getSGPtNames.R: -------------------------------------------------------------------------------- 1 | `getSGPtNames` <- 2 | function(sgp.iter, 3 | SGPt=NULL, 4 | type) { 5 | 6 | if (is.null(SGPt)) { 7 | return(NULL) 8 | } 9 | 10 | if (type %in% c("sgp.percentiles", "sgp.percentiles.equated", "sgp.percentiles.baseline")) { 11 | tmp.list <- as.list(paste(c("TIME", "TIME_LAG"), tail(sgp.iter[["sgp.panel.years"]], 1), tail(sgp.iter[["sgp.content.areas"]], 1), sep=".")) 12 | names(tmp.list) <- c("TIME", "TIME_LAG") 13 | return(tmp.list) 14 | } 15 | 16 | if (type=="sgp.projections") { 17 | return(paste("DATE", tail(sgp.iter[["sgp.projection.panel.years"]], 1), tail(sgp.iter[["sgp.projection.content.areas"]], 1), sep=".")) 18 | } 19 | 20 | if (type=="sgp.projections.baseline") { 21 | return(paste("DATE", tail(sgp.iter[["sgp.projection.baseline.panel.years"]], 1), tail(sgp.iter[["sgp.projection.baseline.content.areas"]], 1), sep=".")) 22 | } 23 | 24 | if (type %in% c("sgp.projections.lagged", "sgp.projections.lagged.baseline")) { 25 | return(paste("DATE", tail(sgp.iter[["sgp.panel.years"]], 1), tail(sgp.iter[["sgp.content.areas"]], 1), sep=".")) 26 | } 27 | } ## END getSGPtNames 28 | -------------------------------------------------------------------------------- /R/getTableNameYear.R: -------------------------------------------------------------------------------- 1 | `getTableNameYear` <- 2 | function(year) { 3 | if (is.numeric(type.convert(unlist(strsplit(year, "[.]"))[3], as.is=TRUE))) { 4 | return(paste(unlist(strsplit(year, "[.]"))[2:3], collapse=".")) 5 | } else { 6 | return(unlist(strsplit(year, "[.]"))[2]) 7 | } 8 | } ### END getTableNameYear 9 | -------------------------------------------------------------------------------- /R/getTargetAchievementLevels.R: -------------------------------------------------------------------------------- 1 | `getTargetAchievementLevels` <- 2 | function(state, 3 | status.type="CATCH_UP_KEEP_UP") { 4 | 5 | tmp.list <- list() 6 | 7 | if (status.type=="CATCH_UP_KEEP_UP") { 8 | if (!is.null(SGP::SGPstateData[[state]][["Assessment_Program_Information"]][["Assessment_Transition"]])) { 9 | tmp.index <- grep("Achievement_Levels", names(SGP::SGPstateData[[state]][["Assessment_Program_Information"]][["Assessment_Transition"]])) 10 | levels.that.are.proficient <- 11 | sort(unlist(sapply(SGP::SGPstateData[[state]][["Assessment_Program_Information"]][["Assessment_Transition"]][tmp.index], function(x) x[['Labels']]))[ 12 | unlist(sapply(SGP::SGPstateData[[state]][["Assessment_Program_Information"]][["Assessment_Transition"]][tmp.index], function(x) x[['Proficient']]))=="Proficient"]) 13 | levels.that.are.not.proficient <- 14 | sort(unlist(sapply(SGP::SGPstateData[[state]][["Assessment_Program_Information"]][["Assessment_Transition"]][tmp.index], function(x) x[['Labels']]))[ 15 | unlist(sapply(SGP::SGPstateData[[state]][["Assessment_Program_Information"]][["Assessment_Transition"]][tmp.index], function(x) x[['Proficient']]))=="Not Proficient"]) 16 | } else { 17 | levels.that.are.proficient <- SGP::SGPstateData[[state]][["Achievement"]][["Levels"]][["Labels"]][ 18 | which(SGP::SGPstateData[[state]][["Achievement"]][["Levels"]][["Proficient"]]=="Proficient")] 19 | levels.that.are.not.proficient <- SGP::SGPstateData[[state]][["Achievement"]][["Levels"]][["Labels"]][ 20 | which(SGP::SGPstateData[[state]][["Achievement"]][["Levels"]][["Proficient"]]=="Not Proficient")] 21 | } 22 | return(list(NO=as.character(levels.that.are.not.proficient), YES=as.character(levels.that.are.proficient))) 23 | } 24 | 25 | if (status.type=="MOVE_UP_STAY_UP") { 26 | if (!is.null(SGP::SGPstateData[[state]][["Assessment_Program_Information"]][["Assessment_Transition"]])) { 27 | levels.that.are.advanced <- levels.that.are.not.advanced <- list() 28 | for (i in grep("Achievement_Levels", names(SGP::SGPstateData[[state]][["Assessment_Program_Information"]][["Assessment_Transition"]]), value=TRUE)) { 29 | levels.that.are.advanced[[i]] <- SGP::SGPstateData[[state]][["Assessment_Program_Information"]][["Assessment_Transition"]][[i]][['Labels']][ 30 | tail(which(SGP::SGPstateData[[state]][["Assessment_Program_Information"]][["Assessment_Transition"]][[i]][["Proficient"]]=="Proficient"), -1)] 31 | levels.that.are.not.advanced[[i]] <- SGP::SGPstateData[[state]][["Assessment_Program_Information"]][["Assessment_Transition"]][[i]][['Labels']][ 32 | c(which(SGP::SGPstateData[[state]][["Assessment_Program_Information"]][["Assessment_Transition"]][[i]][["Proficient"]]=="Not Proficient"), 33 | head(which(SGP::SGPstateData[[state]][["Assessment_Program_Information"]][["Assessment_Transition"]][[i]][["Proficient"]]=="Proficient"), 1))] 34 | } 35 | } else { 36 | levels.that.are.advanced <- SGP::SGPstateData[[state]][["Achievement"]][["Levels"]][["Labels"]][ 37 | tail(which(SGP::SGPstateData[[state]][["Achievement"]][["Levels"]][["Proficient"]]=="Proficient"), -1)] 38 | levels.that.are.not.advanced <- SGP::SGPstateData[[state]][["Achievement"]][["Levels"]][["Labels"]][ 39 | c(which(SGP::SGPstateData[[state]][["Achievement"]][["Levels"]][["Proficient"]]=="Not Proficient"), 40 | head(which(SGP::SGPstateData[[state]][["Achievement"]][["Levels"]][["Proficient"]]=="Proficient"), 1))] 41 | } 42 | return(list(NO=as.character(unlist(levels.that.are.not.advanced)), YES=as.character(unlist(levels.that.are.advanced)))) 43 | } 44 | } ### END getTargetAchievementLevels 45 | -------------------------------------------------------------------------------- /R/getTargetName.R: -------------------------------------------------------------------------------- 1 | `getTargetName` <- 2 | function(state, 3 | target.type="sgp.projections.lagged", 4 | target.level="CATCH_UP_KEEP_UP", 5 | target.years=NULL, 6 | target.label="SGP_TARGET", 7 | projection.unit.label="YEAR", 8 | projection_group.iter=NULL) { 9 | 10 | if (target.level=="CATCH_UP_KEEP_UP") target.level <- NULL 11 | if (target.type %in% c("sgp.projections", "sgp.projections.baseline")) target.period <- "CURRENT" else target.period <- NULL 12 | if (target.type %in% c("sgp.projections.baseline", "sgp.projections.lagged.baseline")) sgp.type <- "BASELINE" else sgp.type <- NULL 13 | if (is.null(target.years) && !is.null(projection_group.iter) && projection_group.iter %in% names(SGP::SGPstateData[[state]][['SGP_Configuration']][['grade.projection.sequence']])) { 14 | tmp.target.years <- SGP::SGPstateData[[state]][['SGP_Configuration']][['max.forward.projection.sequence']][[projection_group.iter]] 15 | if (!is.null(tmp.target.years)) target.years <- tmp.target.years 16 | } 17 | 18 | return(paste(c(target.label, sgp.type, target.level, target.years, projection.unit.label, target.period), collapse="_")) 19 | } ### END getTargetName 20 | -------------------------------------------------------------------------------- /R/getTargetSGPContentArea.R: -------------------------------------------------------------------------------- 1 | `getTargetSGPContentArea` <- 2 | function(grade, 3 | content_area, 4 | state, 5 | max.sgp.target.years.forward, 6 | my.sgp.target.content_area) { 7 | 8 | if (is.null(SGP::SGPstateData[[state]][["SGP_Configuration"]][["content_area.projection.sequence"]][[content_area]])) { 9 | return(content_area) 10 | } else { 11 | tmp.content_areas.by.grade <- paste(SGP::SGPstateData[[state]][["SGP_Configuration"]][["content_area.projection.sequence"]][[content_area]], 12 | SGP::SGPstateData[[state]][["SGP_Configuration"]][["grade.projection.sequence"]][[content_area]], sep=".") 13 | tmp.index <- match(paste(content_area, grade, sep="."), tmp.content_areas.by.grade) 14 | if (is.na(tmp.index)) { 15 | message(paste0("\tNOTE: '", content_area, "', GRADE '", grade, "' combination is not in current @Data. Will return ", content_area, " for '", my.sgp.target.content_area, "'.")) 16 | return(content_area) 17 | } else { 18 | return(SGP::SGPstateData[[state]][["SGP_Configuration"]][["content_area.projection.sequence"]][[content_area]][ 19 | min(tmp.index+max.sgp.target.years.forward, length(SGP::SGPstateData[[state]][["SGP_Configuration"]][["grade.projection.sequence"]][[content_area]]))]) 20 | } 21 | } 22 | } ### END getTargetSGPContentArea 23 | -------------------------------------------------------------------------------- /R/getTargetSGPLevel.R: -------------------------------------------------------------------------------- 1 | `getTargetSGPLevel` <- 2 | function(state, 3 | state.iter=NULL, 4 | target.level){ 5 | 6 | if (!is.null(SGP::SGPstateData[[state]][['Achievement']][['Cutscore_Information']])) { 7 | tmp.state.level <- which(sapply(lapply(SGP::SGPstateData[[state]][["Achievement"]][["Cutscore_Information"]][['State_Levels']], '[[', 1), function(x) state.iter %in% x)) 8 | if (target.level=="CATCH_UP_KEEP_UP") { 9 | level.to.get <- which.max(SGP::SGPstateData[[state]][["Achievement"]][["Cutscore_Information"]][['State_Levels']][[tmp.state.level]][['Levels']]=="Proficient")-1 10 | } 11 | if (target.level=="MOVE_UP_STAY_UP") { 12 | if (length(which(SGP::SGPstateData[[state]][["Achievement"]][["Cutscore_Information"]][['State_Levels']][[tmp.state.level]][['Levels']]=="Proficient")) <= 1) { 13 | message(paste0("\tNOTE: MOVE_UP_STAY_UP Targets cannot be calculated because no achievement levels above PROFICIENT exist in ", state, "/", state.iter, ".")) 14 | level.to.get <- NULL 15 | } else { 16 | level.to.get <- which.max(SGP::SGPstateData[[state]][["Achievement"]][["Cutscore_Information"]][['State_Levels']][[tmp.state.level]][['Levels']]=="Proficient") 17 | } 18 | } 19 | } else { 20 | if (target.level=="CATCH_UP_KEEP_UP") level.to.get <- which.max(SGP::SGPstateData[[state]][["Achievement"]][["Levels"]][["Proficient"]]=="Proficient")-1 21 | if (target.level=="MOVE_UP_STAY_UP") { 22 | if (length(which(SGP::SGPstateData[[state]][["Achievement"]][["Levels"]][["Proficient"]]=="Proficient")) <= 1) { 23 | stop(paste0("\tNOTE: MOVE_UP_STAY_UP Targets cannot be calculated because no achievement levels above PROFICIENT exist in ", state, ".")) 24 | } else { 25 | level.to.get <- which.max(SGP::SGPstateData[[state]][["Achievement"]][["Levels"]][["Proficient"]]=="Proficient") 26 | } 27 | } 28 | } 29 | return(level.to.get) 30 | } ### END getTargetSGPLevel 31 | -------------------------------------------------------------------------------- /R/getTargetScaleScoreTableNames.R: -------------------------------------------------------------------------------- 1 | `getTargetScaleScoreTableNames` <- 2 | function( 3 | table_names, 4 | years) { 5 | if (is.null(years)) { 6 | return(grep("TARGET_SCALE_SCORES", table_names, value=TRUE)) 7 | } else { 8 | return(grep(paste(years, collapse="|"), grep("TARGET_SCALE_SCORES", table_names, value=TRUE), value=TRUE)) 9 | } 10 | } ### END getTargetScaleScoreTableNames 11 | -------------------------------------------------------------------------------- /R/getTimeShiftIndex.R: -------------------------------------------------------------------------------- 1 | getTimeShiftIndex <- 2 | function(my.time.data, 3 | my.matrix, 4 | time.shift=365, 5 | time.buffer=30) { 6 | (-20:20)[which.max(sapply(-20:20, function(x) my.matrix@Version[['Matrix_Information']][['SGPt']][['MAX_TIME']]+time.buffer+time.shift*x - my.time.data) > 0)] 7 | } ### END getTimeShiftIndex 8 | -------------------------------------------------------------------------------- /R/getVersion.R: -------------------------------------------------------------------------------- 1 | `getVersion` <- 2 | function(data=NULL) { 3 | if (is.SGP(data) && .hasSlot(data, "Version")) { 4 | existing <- data@Version 5 | return( 6 | Filter(Negate(is.null), 7 | list( 8 | SGP_Package_Version = 9 | c(existing[["SGP_Package_Version"]], as.character(packageVersion("SGP"))), 10 | Date_Prepared = 11 | c(existing[["Date_Prepared"]], prettyDate()), 12 | session_platform = if ("session_platform" %in% names(existing)) { 13 | existing[["session_platform"]] 14 | } else NULL, 15 | attached_pkgs = if ("attached_pkgs" %in% names(existing)) { 16 | existing[["attached_pkgs"]] 17 | } else NULL, 18 | namespace_pkgs = if ("namespace_pkgs" %in% names(existing)) { 19 | existing[["namespace_pkgs"]] 20 | } else NULL 21 | )) 22 | ) 23 | } else { 24 | return( 25 | list( 26 | SGP_Package_Version = as.character(packageVersion("SGP")), 27 | Date_Prepared = prettyDate() 28 | ) 29 | ) 30 | } 31 | } ### END getVersion function 32 | -------------------------------------------------------------------------------- /R/getYearsContentAreasGrades.R: -------------------------------------------------------------------------------- 1 | `getYearsContentAreasGrades` <- 2 | function(state, 3 | years, 4 | content_areas=NULL, 5 | content_areas_domains=NULL, 6 | earliest_year_reported=NULL) { 7 | 8 | CONTENT_AREA <- NULL 9 | 10 | tmp.list <- list() 11 | if (is.null(content_areas)) tmp.content_areas <- content_areas_domains else tmp.content_areas <- content_areas 12 | for (i in intersect(names(SGP::SGPstateData[[state]][["Student_Report_Information"]][["Grades_Reported"]]), tmp.content_areas)) { 13 | if (!is.null(content_areas_domains) && !is.null(SGP::SGPstateData[[state]][["Student_Report_Information"]][['Content_Areas_Domains']])) { 14 | tmp.dt <- data.table(GRADE=as.character(unique(unlist(SGP::SGPstateData[[state]][["Student_Report_Information"]][["Grades_Reported"]][ 15 | grep(i, SGP::SGPstateData[[state]][["Student_Report_Information"]][['Content_Areas_Domains']])])))) 16 | } else { 17 | tmp.dt <- data.table(GRADE=as.character(SGP::SGPstateData[[state]][["Student_Report_Information"]][["Grades_Reported"]][[i]])) 18 | } 19 | 20 | if (!is.null(earliest_year_reported[[i]])) { 21 | tmp.years.diff <- as.numeric(tail(unlist(strsplit(tail(sort(years), 1L), "_")), 1L))-as.numeric(tail(unlist(strsplit(earliest_year_reported[[i]], "_")), 1L)) 22 | tmp.dt <- CJ(tmp.dt$GRADE, intersect(yearIncrement(tail(sort(years), 1L), c(-seq(tmp.years.diff), 0)), years)) 23 | } else { 24 | tmp.dt <- CJ(tmp.dt$GRADE, years) 25 | } 26 | 27 | setnames(tmp.dt, c("GRADE", "YEAR")) 28 | tmp.list[[i]] <- data.table(CONTENT_AREA=i, tmp.dt) 29 | } 30 | tmp.dt <- rbindlist(tmp.list, fill=TRUE) 31 | setkeyv(tmp.dt, c("CONTENT_AREA", "GRADE", "YEAR")) 32 | return(na.omit(tmp.dt, cols="CONTENT_AREA")) 33 | } ## END getYearsContentAreasGrades 34 | -------------------------------------------------------------------------------- /R/is.SGP.R: -------------------------------------------------------------------------------- 1 | `is.SGP` <- 2 | function(x) { 3 | inherits(x, "SGP") 4 | } 5 | -------------------------------------------------------------------------------- /R/is.splineMatrix.R: -------------------------------------------------------------------------------- 1 | `is.splineMatrix` <- 2 | function(x) { 3 | inherits(x, "splineMatrix") 4 | } 5 | -------------------------------------------------------------------------------- /R/mergeSGP.R: -------------------------------------------------------------------------------- 1 | `mergeSGP` <- 2 | function(list_1, 3 | list_2) { 4 | 5 | ### Merge lists 6 | 7 | if (is.null(names(list_1))) return(list_2) 8 | if (!is.null(names(list_2))) { 9 | for (j in c("Coefficient_Matrices", "Cutscores", "Goodness_of_Fit", "Knots_Boundaries", "Linkages", "SGPercentiles", "SGProjections", "Simulated_SGPs", "Error_Reports")) { 10 | list_1[[j]] <- c(list_1[[j]], list_2[[j]])[!duplicated(names(c(list_1[[j]], list_2[[j]])))] 11 | } 12 | 13 | ### SGPercentiles, SGProjections, Simulated_SGPs 14 | 15 | for (j in c("SGPercentiles", "SGProjections", "Simulated_SGPs")) { 16 | if (all(names(list_2[[j]]) %in% names(list_1[[j]]))) { 17 | for (k in names(list_2[[j]])) { # merging list_2 in with list_1, so use it here 18 | if (!identical(list_1[[j]][[k]], list_2[[j]][[k]])) { # keeps it from copying first set of results 19 | list_1[[j]][[k]] <- rbindlist(list(list_1[[j]][[k]], list_2[[j]][[k]]), fill=TRUE) 20 | } 21 | } 22 | } 23 | } 24 | 25 | ### Goodness_of_Fit, Knots_Boundaries 26 | 27 | for (j in c("Goodness_of_Fit", "Knots_Boundaries")) { 28 | for (k in names(list_2[[j]])) { 29 | if (!identical(list_1[[j]][[k]], list_2[[j]][[k]])) { 30 | names.list <- c(unique(names(list_1[[j]][[k]])), unique(names(list_2[[j]][[k]]))) # Get list of (unique) names first. 31 | list_1[[j]][[k]] <- c(list_1[[j]][[k]], list_2[[j]][[k]][!names(list_2[[j]][[k]]) %in% names(list_1[[j]][[k]])]) #new.elements 32 | if (any(duplicated(names.list))) { 33 | dups <- names.list[which(duplicated(names.list))] 34 | for (l in seq(dups)) { 35 | if (!identical(list_1[[j]][[k]][[dups[l]]], list_2[[j]][[k]][[dups[l]]])) { # could be same matrices, different @Version (???) 36 | x <- length(list_1[[j]][[k]])+1 37 | list_1[[j]][[k]][[x]] <- list_2[[j]][[k]][[dups[l]]] 38 | names(list_1[[j]][[k]]) <- c(names(list_1[[j]][[k]])[-x], dups[l]) 39 | } 40 | } 41 | } 42 | } 43 | } 44 | } # j in c("Goodness_of_Fit", "Knots_Boundaries") 45 | 46 | ### Coefficient_Matrices 47 | 48 | j <- "Coefficient_Matrices" 49 | for (k in names(list_2[[j]])) { 50 | if (!grepl("SIMEX", k)) { 51 | if (!identical(list_1[[j]][[k]], list_2[[j]][[k]])) { 52 | list_1[[j]][[k]] <- uniquesplineMatrix(c(list_1[[j]][[k]], list_2[[j]][[k]])) 53 | } 54 | } else { 55 | for (grd_ord in names(list_2[[j]][[k]])) { 56 | for (lambda in grep("lambda", names(list_2[[j]][[k]][[grd_ord]]), value=TRUE)) { 57 | if (!identical(list_1[[j]][[k]][[grd_ord]][[lambda]], list_2[[j]][[k]][[grd_ord]][[lambda]])) { 58 | list_1[[j]][[k]][[grd_ord]][[lambda]] <- uniquesplineMatrix(c(list_1[[j]][[k]][[grd_ord]][[lambda]], list_2[[j]][[k]][[grd_ord]][[lambda]])) 59 | } 60 | } 61 | for (rst in grep("ranked_simex_table", names(list_2[[j]][[k]][[grd_ord]]), value=TRUE)) { 62 | # if (!is.null(list_1[[j]][[k]][[grd_ord]][[rst]]))stop("FmeN@$$") 63 | if (!identical(list_1[[j]][[k]][[grd_ord]][[rst]], list_2[[j]][[k]][[grd_ord]][[rst]])) { 64 | list_1[[j]][[k]][[grd_ord]][[rst]] <- c(list_1[[j]][[k]][[grd_ord]][[rst]], list_2[[j]][[k]][[grd_ord]][[rst]]) 65 | } 66 | } 67 | # for (rst in grep("ranked_simex_table|n_records", names(list_2[[j]][[k]][[grd_ord]]), value=TRUE)) { 68 | # if (!identical(list_1[[j]][[k]][[grd_ord]][[rst]], list_2[[j]][[k]][[grd_ord]][[rst]])) { 69 | # list_1[[j]][[k]][[grd_ord]][[rst]] <- c(list_1[[j]][[k]][[grd_ord]][[rst]], list_2[[j]][[k]][[grd_ord]][[rst]]) 70 | # } 71 | # } 72 | } 73 | } 74 | } # j <- "Coefficient_Matrices" 75 | } 76 | list_1[which(names(list_1) != "Panel_Data")] 77 | } ### END mergeSGP 78 | -------------------------------------------------------------------------------- /R/messageSGP.R: -------------------------------------------------------------------------------- 1 | `messageSGP` <- 2 | function(tmp.message, 3 | domain=NULL, 4 | appendLF=TRUE) { 5 | 6 | PrintLogMessage <- function(tmp.message, domain=NULL) { 7 | # print log message to file 8 | dir.create("Logs", showWarnings = FALSE) 9 | logfile <- paste0("Logs/SGP-", packageVersion("SGP"), "_", Sys.Date(), ".txt") 10 | 11 | if (is.call(tmp.message)) { 12 | tmp.message2 <- c(paste0("\n\n\t", as.character(tmp.message)[1L], "(\n\t\t"), paste(names(tmp.message)[-1L], as.character(tmp.message)[-1L], sep=" = ", collapse="\n\t\t"), ")\n\n") 13 | cat(tmp.message2, file = logfile, append=appendLF) 14 | } else cat(tmp.message, "\n", file=logfile, sep="", append=appendLF) 15 | } 16 | 17 | if (!is.call(tmp.message)) { 18 | base::message(tmp.message) 19 | } 20 | PrintLogMessage(tmp.message) 21 | invisible() 22 | } 23 | -------------------------------------------------------------------------------- /R/piecewiseTransform.R: -------------------------------------------------------------------------------- 1 | `piecewiseTransform` <- 2 | function(scale_score, 3 | state, 4 | content_area, 5 | year, 6 | grade, 7 | output.digits=1, 8 | sgp.projections.equated=NULL, 9 | new.cutscores=NULL, 10 | equating.method="equipercentile", 11 | vertical_scale_for_projections=NULL) { 12 | 13 | if (all(is.na(scale_score))) return(scale_score) 14 | if (is.null(vertical_scale_for_projections)) vertical_scale_for_projections <- TRUE 15 | 16 | ### Test to deal with assessment transition scenario 17 | 18 | if (!is.null(SGP::SGPstateData[[state]][["Assessment_Program_Information"]][["Assessment_Transition"]])) { 19 | equate.year <- SGP::SGPstateData[[state]][["Assessment_Program_Information"]][["Assessment_Transition"]][["Year"]] 20 | if (is.null(equate.year)) equate.year <- 0 21 | if (year < equate.year) { 22 | tmp.test <- "Transformed_Achievement_Level_Cutscores" 23 | } else { 24 | if (!is.null(new.cutscores) && length(new.cutscores) > 0) { 25 | tmp.test <- "NOT_NULL" 26 | } else { 27 | tmp.test <- NULL 28 | } 29 | } 30 | } else { 31 | tmp.test <- NULL 32 | } 33 | 34 | 35 | if (is.null(sgp.projections.equated) | !is.null(tmp.test)) { 36 | if (((year %in% SGP::SGPstateData[[state]][["Student_Report_Information"]][["Transformed_Achievement_Level_Cutscores"]][[content_area]] | !vertical_scale_for_projections) && 37 | grade %in% unlist(lapply(strsplit(names(SGP::SGPstateData[[state]][["Achievement"]][["Knots_Boundaries"]][[getMyLabel(state, content_area, year, "Knots_Boundaries")]]), "_"), '[', 2))) || !is.null(tmp.test)) { 38 | 39 | my.knots_boundaries.label <- getMyLabel(state, content_area, year, "Knots_Boundaries") 40 | tmp.loss.hoss <- SGP::SGPstateData[[state]][["Achievement"]][["Knots_Boundaries"]][[my.knots_boundaries.label]][[paste0("loss.hoss_", grade)]] 41 | scale_score[scale_score < tmp.loss.hoss[1]] <- tmp.loss.hoss[1]; scale_score[scale_score > tmp.loss.hoss[2]] <- tmp.loss.hoss[2] 42 | my.cutscores.label <- getMyLabel(state, content_area, year) 43 | old.cutscores <- c(tmp.loss.hoss[1], SGP::SGPstateData[[state]][["Achievement"]][["Cutscores"]][[my.cutscores.label]][[paste0("GRADE_", grade)]], 44 | tmp.loss.hoss[2]) 45 | if (is.null(new.cutscores)) new.cutscores <- seq(0, by=100, length.out=length(old.cutscores)) 46 | tmp.index <- findInterval(scale_score, old.cutscores, rightmost.closed=TRUE) 47 | tmp.diff <- diff(new.cutscores)/diff(old.cutscores) 48 | round(new.cutscores[tmp.index] + (scale_score - old.cutscores[tmp.index]) * (diff(new.cutscores)/diff(old.cutscores))[tmp.index], digits=output.digits) 49 | } else { 50 | as.numeric(scale_score) 51 | } 52 | } else { 53 | if (!is.na(content_area) & !is.na(grade)) { 54 | sgp.projections.equated[['Linkages']][[paste(content_area, sgp.projections.equated[['Year']], sep=".")]][[paste("GRADE", grade, sep="_")]][[toupper(equating.method)]][['OLD_TO_NEW']][['interpolated_function']](scale_score) 55 | } else { 56 | as.numeric(scale_score) 57 | } 58 | } 59 | } ## END piecewiseTransform Function 60 | -------------------------------------------------------------------------------- /R/prettyDate.R: -------------------------------------------------------------------------------- 1 | `prettyDate` <- 2 | function() { 3 | format(Sys.time(), "%A %B %d %H:%M:%S %Y") 4 | } 5 | -------------------------------------------------------------------------------- /R/setNamesSGP.R: -------------------------------------------------------------------------------- 1 | `setNamesSGP` <- 2 | function( 3 | data, 4 | state=NULL) { 5 | 6 | ### Get state (if possible) 7 | if (is.null(state)) { 8 | tmp.name <- toupper(gsub("_", " ", deparse(substitute(data)))) 9 | state <- getStateAbbreviation(tmp.name, "prepareSGP") 10 | } 11 | 12 | variable.name.lookup <- SGP::SGPstateData[[state]][["Variable_Name_Lookup"]] 13 | if (is.null(variable.name.lookup)) stop("Variable name lookup must be in SGPstateData for ", state, " to use setNamesSGP") 14 | names.in.data <- which(variable.name.lookup[["names.provided"]] %in% names(data)) 15 | setnames(data, variable.name.lookup[['names.provided']][names.in.data], variable.name.lookup[['names.sgp']][names.in.data]) 16 | } ### END setNamesSGP 17 | -------------------------------------------------------------------------------- /R/splineMatrix-class.R: -------------------------------------------------------------------------------- 1 | setClassUnion("list.null", c("list","NULL")) 2 | .Valid.splineMatrix <- function(object) { 3 | 4 | errors <- NULL 5 | 6 | tmp.test.null <- 7 | all(!is.null(object@Knots) & 8 | !is.null(object@Boundaries) & 9 | !is.null(object@Content_Areas) & 10 | !is.null(object@Grade_Progression) & 11 | !is.null(object@Time) & 12 | !is.null(object@Time_Lags) & 13 | !is.null(object@Version)) 14 | 15 | tmp.test.length <- length(object@Content_Areas[[1]]) == length(object@Grade_Progression[[1]]) & length(object@Grade_Progression[[1]]) == length(object@Time[[1]]) 16 | 17 | if (!is.null(object@Content_Areas) & !is.null(object@Grade_Progression) & !is.null(object@Time)) { 18 | tmp.test.character <- is.character(object@Content_Areas[[1]]) & is.character(object@Grade_Progression[[1]]) & is.character(object@Time[[1]]) 19 | } 20 | 21 | if (!is.null(object@Time)) { 22 | if (any(object@Time[[1]]=="BASELINE")) { 23 | tmp.test.time <- TRUE 24 | } else { 25 | tmp.test.time <- all(yearIncrement(head(object@Time[[1]], 1), c(0, cumsum(object@Time_Lags[[1]]))) == object@Time[[1]]) 26 | } 27 | } 28 | 29 | if (!is.null(object@Time_Lags)) { 30 | tmp.test.numeric.lags <- is.numeric(object@Time_Lags[[1]]) 31 | } 32 | 33 | if (!tmp.test.null) errors <- c(errors, "\tError in splineMatrix construction: Slots in splineMatrix are not all non-null.") 34 | if (!tmp.test.length) errors <- c(errors, "\tError in splineMatrix construction: Slots @Grade_Progression, @Content_Areas, and @Time are not all the same length.") 35 | if (!tmp.test.character) errors <- c(errors, "\tError in splineMatrix construction: Slots @Grade_Progression, @Content_Areas, and @Time are not all characters.") 36 | if (!tmp.test.time) errors <- c(errors, "\tError in splineMatrix construction: Slots @Time and @Time_Lags are not commensurate with one another.") 37 | if (!tmp.test.numeric.lags) errors <- c(errors, "\tError in splineMatrix construction: Slot @Time_Lags is not numeric.") 38 | 39 | if (is.null(errors)) TRUE else errors 40 | } 41 | setClass("splineMatrix", 42 | contains='matrix', 43 | representation( 44 | Knots='list.null', 45 | Boundaries='list.null', 46 | Content_Areas='list.null', 47 | Grade_Progression='list.null', 48 | Time='list.null', 49 | Time_Lags='list.null', 50 | Version="list.null"), 51 | validity=.Valid.splineMatrix) 52 | setValidity("splineMatrix", .Valid.splineMatrix) 53 | -------------------------------------------------------------------------------- /R/stopParallel.R: -------------------------------------------------------------------------------- 1 | `stopParallel` <- 2 | function(parallel.config, 3 | par.start) { 4 | 5 | if (toupper(parallel.config[['BACKEND']]) == 'FOREACH') { 6 | if (is.na(parallel.config[['TYPE']])) parallel.config[['TYPE']] <- "NA" # Stop checks on NA below. 7 | 8 | # if (parallel.config[['TYPE']]=="doMPI") { 9 | # closeCluster(par.start$doPar.cl) 10 | # return() 11 | # } 12 | 13 | if (parallel.config[['TYPE']]=="doParallel" & par.start$par.type=='SNOW') { 14 | stopCluster(par.start$doPar.cl) 15 | return() 16 | } 17 | 18 | # if (parallel.config[['TYPE']]=="doSNOW") { 19 | # stopCluster(par.start$doPar.cl) 20 | # return() 21 | # } 22 | 23 | # if (parallel.config[['TYPE']]=="doRedis") { 24 | # removeQueue(par.start$jobs) 25 | # return() 26 | # } 27 | } # END FOREACH 28 | 29 | # Nothing required for MULTICORE (or doMC) 30 | # if (toupper(parallel.config[['BACKEND']]) == 'MULTICORE') { 31 | # } 32 | 33 | if (par.start$par.type == 'SNOW') { 34 | if (is.null(parallel.config[['CLUSTER.OBJECT']])) { 35 | stopCluster(par.start$internal.cl) 36 | } 37 | } 38 | } ### END stopParallel Function 39 | -------------------------------------------------------------------------------- /R/stratifiedRandomSampleSGP.R: -------------------------------------------------------------------------------- 1 | `stratifiedRandomSampleSGP` <- 2 | function( 3 | norm_group_data, 4 | strata_variable, 5 | strata_proportions, 6 | sample_size=NULL) { 7 | 8 | CONTENT_AREA <- GRADE <- ID <- VALID_CASE <- YEAR <- NULL ### To prevent R CMD check warnings 9 | 10 | tmp.years <- unique(norm_group_data[['YEAR']]) 11 | sample_data <- norm_group_data[YEAR==tail(tmp.years, 1)] 12 | if (is.null(sample_size)) sample_size=nrow(sample_data) 13 | stopifnot(length(strata_proportions) == uniqueN(norm_group_data[[strata_variable]])) 14 | tmp.replications <- ceiling(max((strata_proportions*sample_size)/table(sample_data[[strata_variable]]))) 15 | setkey(norm_group_data, VALID_CASE, CONTENT_AREA, YEAR, GRADE, ID) 16 | tmp.replicated_norm_group_data <- rbindlist(replicate(tmp.replications, return(norm_group_data), simplify=FALSE))[,ID:=paste(ID, rep(seq.int(tmp.replications), each=nrow(norm_group_data)), sep="_")] 17 | tmp.sample_data <- tmp.replicated_norm_group_data[YEAR==tail(tmp.years, 1)][, .SD[sample(.N, ceiling(sample_size*strata_proportions[[unlist(.BY)]]))], keyby = strata_variable] 18 | return(rbindlist(list(tmp.replicated_norm_group_data[YEAR %in% head(tmp.years, -1) & ID %in% tmp.sample_data[['ID']]], tmp.sample_data), use.names=TRUE)) 19 | } ### END stratifiedRandomSamplSGP 20 | -------------------------------------------------------------------------------- /R/timetakenSGP.R: -------------------------------------------------------------------------------- 1 | timetakenSGP <- 2 | function(started.at) { 3 | 4 | format = function(secs) { 5 | secs.integer = as.integer(secs) 6 | sprintf("%02d:%02d:%02d:%.3f", secs.integer%/%86400L, (secs.integer%/%3600L)%%24L, (secs.integer%/%60L)%%60L, secs%%60L) 7 | } 8 | tt = proc.time() - started.at 9 | format(tt[3L]) 10 | } ### END timetakenSGP function 11 | -------------------------------------------------------------------------------- /R/unfoldstudentGrowthPlots.R: -------------------------------------------------------------------------------- 1 | `unfoldstudentGrowthPlots` <- 2 | function(directory="Visualizations"){ 3 | 4 | tmp.directory <- file.path(directory, "studentGrowthPlots_FLAT") 5 | dir.create(tmp.directory, recursive=TRUE, showWarnings=FALSE) 6 | 7 | ### Get list of zip files 8 | 9 | list.of.zip.files <- list.files(file.path(directory, "studentGrowthPlots"), recursive=TRUE, pattern="zip") 10 | list.of.zip.files <- paste(getwd(), file.path(directory, "studentGrowthPlots"), list.of.zip.files, sep="/") 11 | 12 | ### unzip the files 13 | 14 | setwd(tmp.directory) 15 | 16 | for (i in list.of.zip.files) { 17 | system(paste("unzip -oq", i)) 18 | } 19 | 20 | ### Get new list of individual files 21 | 22 | list.of.directories <- list.files() 23 | list.of.pdf.files <- list.files(recursive=TRUE) 24 | list.of.pdf.files <- paste(getwd(), list.of.pdf.files, sep="/") 25 | list.of.studentGrowthPlots <- list.of.pdf.files[-grep("Catalog", list.of.pdf.files)] 26 | list.of.pdf.catalogs <- grep("Catalog", list.of.pdf.files, value=TRUE) 27 | 28 | ### Create directory for School Catalogs 29 | 30 | dir.create("School_Catalogs", recursive=TRUE, showWarnings=FALSE) 31 | dir.create("studentGrowthPlots", recursive=TRUE, showWarnings=FALSE) 32 | 33 | for (i in list.of.pdf.catalogs) { 34 | file.rename(i, file.path("School_Catalogs", sapply(strsplit(i, "/"), tail, 1))) 35 | } 36 | 37 | for (i in list.of.studentGrowthPlots) { 38 | file.rename(i, file.path("studentGrowthPlots", sapply(strsplit(i, "/"), tail, 1))) 39 | } 40 | 41 | ### Remove empty directories 42 | 43 | for (i in list.of.directories) { 44 | unlink(file.path(getwd(), i), recursive=TRUE) 45 | } 46 | } ### END unfoldstudentGrowthPlots function 47 | -------------------------------------------------------------------------------- /R/uniquesplineMatrix.R: -------------------------------------------------------------------------------- 1 | `uniquesplineMatrix` <- 2 | function(list.of.splineMatrices) { 3 | 4 | ### First identify/remove exact duplicates (not newer/older Versions). Fixes issue of mergeSGP with existing SIMEX Baseline Matrices - 10/8/14 5 | tmp.list.1 <- lapply(list.of.splineMatrices, 6 | function(x) list(Data = x@.Data, Content_Areas=x@Content_Areas, Grade_Progression=x@Grade_Progression, Time=x@Time, Time_Lags=x@Time_Lags, Version=x@Version)) 7 | if (any(duplicated(tmp.list.1))) { 8 | list.of.splineMatrices <- list.of.splineMatrices[!duplicated(tmp.list.1)] 9 | } 10 | 11 | tmp.list.1 <- lapply(list.of.splineMatrices, 12 | function(x) list(Data = x@.Data, Content_Areas=x@Content_Areas, Grade_Progression=x@Grade_Progression, Time=x@Time, Time_Lags=x@Time_Lags)) 13 | tmp.list.2 <- lapply(list.of.splineMatrices, 14 | function(x) list(Data = x@.Data, Content_Areas=x@Content_Areas, Grade_Progression=x@Grade_Progression, Time=x@Time, Time_Lags=x@Time_Lags, Version=x@Version)) 15 | if (any(duplicated(tmp.list.1))) { 16 | list.of.splineMatrices[!duplicated(tmp.list.1[order(as.character(unlist(sapply(tmp.list.2, function(x) x$Version[1]))), decreasing=TRUE)])] 17 | } else { 18 | list.of.splineMatrices 19 | } 20 | } ### END uniquesplineMatrix 21 | -------------------------------------------------------------------------------- /R/yearIncrement.R: -------------------------------------------------------------------------------- 1 | `yearIncrement` <- 2 | function(year, 3 | increment, 4 | lag=0) { 5 | 6 | if (is.null(year)) return(NULL) 7 | 8 | if (identical(year, "BASELINE")) { 9 | return(rep("BASELINE", length(increment))) 10 | } else { 11 | if (grepl("_", year[1L])) { 12 | tmp1 <- sapply(seq_along(increment), function(i) as.numeric(sapply(strsplit(as.character(year), "_"), '[', 2L)) + increment[i] - lag) 13 | paste(floor(tmp1)-1L, tmp1, sep="_") 14 | } else { 15 | as.character(sapply(seq_along(increment), function(i) as.numeric(year) + increment[i] - lag)) 16 | } 17 | } 18 | } ### End yearIncrement 19 | -------------------------------------------------------------------------------- /R/zzz.R: -------------------------------------------------------------------------------- 1 | `.onLoad` <- 2 | function(libname, pkgname) { 3 | available_threads <- data.table::getDTthreads() 4 | data.table::setDTthreads(available_threads) 5 | utils::globalVariables(c(".")) 6 | } 7 | 8 | `.onAttach` <- function(libname, pkgname) { 9 | if (interactive()) { 10 | # Utility function with timeout 11 | get_dev_version <- function(package, timeout = 2) { 12 | url <- paste0("https://raw.githubusercontent.com/CenterForAssessment/", package, "/refs/heads/master/DESCRIPTION") 13 | tryCatch({ 14 | # Use curl with timeout 15 | response <- curl::curl_fetch_memory(url, handle = curl::new_handle(timeout = timeout)) 16 | if (response$status_code == 200) { 17 | lines <- strsplit(rawToChar(response$content), "\n")[[1]] 18 | version_line <- grep("^Version:", lines, value = TRUE) 19 | if (length(version_line) > 0) { 20 | return(cyan("v", strsplit(version_line, ": ")[[1]][2], sep="")) 21 | } 22 | } 23 | return(red("Not Available")) 24 | }, error = function(e) { 25 | return(red("Not Available")) 26 | }, warning = function(w) { 27 | return(red("Not Available")) 28 | }) 29 | } 30 | 31 | # Extract version information with timeout 32 | installed.version <- utils::packageDescription("SGP")[['Version']] 33 | cran.version <- tryCatch({ 34 | # Add timeout to CRAN check 35 | curl::curl_fetch_memory("https://cran.r-project.org/web/packages/SGP/index.html", 36 | handle = curl::new_handle(timeout = 2)) 37 | green("v", pkgsearch::cran_package("SGP")[['Version']], sep="") 38 | }, error = function(e) red("Not Available"), 39 | warning = function(w) red("Not Available")) 40 | dev.version <- get_dev_version("SGP") 41 | 42 | # Define a friendly startup message 43 | message_text <- paste0( 44 | magenta(bold("\uD83C\uDF89 SGP v", installed.version, sep="")), " - ", toOrdinal::toOrdinalDate("2025-6-17"), "\n", 45 | strrep("\u2501", 40), "\n", 46 | bold("\U1F4E6 CRAN: "), cran.version, "\n", 47 | bold("\U1F527 Dev: "), dev.version, "\n", 48 | strrep("\u2501", 40), "\n", 49 | "\U1F4A1 Tip: ", magenta(bold("> help(package=\"SGP\")")), "\n", 50 | "\U1F310 Docs: ", magenta(bold("https://sgp.io")), "\n", 51 | strrep("\u2501", 40), "\n", 52 | "\u2728 Happy SGPing!", "\n") 53 | 54 | # Display the startup message 55 | packageStartupMessage(message_text) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SGP 2 | === 3 | 4 | [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.6471237.svg)](https://doi.org/10.5281/zenodo.6471237) 5 | [![R-CMD-check](https://github.com/CenterForAssessment/SGP/workflows/R-CMD-check/badge.svg)](https://github.com/CenterForAssessment/SGP/actions) 6 | [![CRAN_Status_Badge](https://www.r-pkg.org/badges/version/SGP)](https://cran.r-project.org/package=SGP) 7 | [![Development Version](https://img.shields.io/badge/devel-2.2--1.9998-brightgreen.svg)](https://github.com/CenterForAssessment/SGP) 8 | [![Rstudio mirror downloads](https://cranlogs.r-pkg.org/badges/grand-total/SGP)](https://github.com/metacran/cranlogs.app) 9 | [![License](https://img.shields.io/badge/license-GPL%203-brightgreen.svg?style=flat)](https://github.com/CenterForAssessment/SGP/blob/master/LICENSE.md) 10 | 11 | 12 | # Overview 13 | 14 | The SGP Package is open source software built for the [**R** software environment](https://www.r-project.org/). The classes, functions and data within the SGP package are used to calculate student growth percentiles and percentile growth projections/trajectories using large scale, longitudinal assessment data. Quantile regression is used to estimate the conditional density associated with each student's achievement history. Percentile growth projections/trajectories are calculated using the derived coefficient matrices and show the percentile growth needed to reach future achievement targets. 15 | 16 | 17 | # Installation 18 | 19 | ## From [CRAN](https://CRAN.R-project.org/package=SGP) 20 | 21 | To install the latest stable release of SGP from [CRAN](https://CRAN.R-project.org/package=SGP) 22 | 23 | ```R 24 | > install.packages("SGP") 25 | ``` 26 | 27 | ## From [Github](https://github.com/CenterForAssessment/SGP/) 28 | 29 | To install the development release of SGP from [GitHub](https://github.com/CenterForAssessment/SGP/): 30 | 31 | ```R 32 | > devtools::install_github("CenterForAssessment/SGP") 33 | ``` 34 | 35 | 36 | # Resources 37 | 38 | * [SGP GitHub Pages](https://sgp.io) 39 | * [CRAN Repo](https://CRAN.R-project.org/package=SGP) 40 | * [Norm- and Criterion-Referenced Student Growth](https://github.com/CenterForAssessment/SGP_Resources/blob/master/articles/Betebenner_EMIP_2009.pdf) 41 | 42 | 43 | # Contributors 44 | 45 | The SGP Package is crafted with :heart: by: 46 | 47 | * [Damian Betebenner](https://github.com/dbetebenner) 48 | * [Adam R. Van Iwaarden](https://github.com/adamvi) 49 | * [Ben Domingue](https://github.com/ben-domingue) 50 | * [Yi Shang](https://github.com/shangyi) 51 | 52 | We love feedback and are happy to answer questions. 53 | 54 | 55 | # References 56 | 57 | Betebenner, D. W., VanIwaarden, A., Domingue, B., and Shang, Y. (2025). SGP: Student Growth Percentiles & Percentile Growth Trajectories. 58 | 59 | R Core Team (2025). R: A language and environment for statistical computing. R Foundation for Statistical Computing, Vienna, Austria. URL 60 | https://www.R-project.org/. 61 | -------------------------------------------------------------------------------- /_pkgdown.yml: -------------------------------------------------------------------------------- 1 | template: 2 | package: centerPackageTemplate 3 | default_assets: false 4 | 5 | 6 | home: 7 | strip_header: true 8 | links: 9 | - text: Other Center stuff 10 | href: https://centerforassessment.github.io/ 11 | 12 | 13 | navbar: 14 | title: ~ 15 | type: default 16 | left: 17 | - text: Getting Started 18 | href: articles/SGP.html 19 | - text: Vignettes 20 | menu: 21 | - text: "SGP Data Preparation" 22 | href: articles/SGP_Data_Preparation.html 23 | - text: "SGP Data Analysis" 24 | href: articles/SGP_Data_Analysis.html 25 | - text: Reference 26 | href: reference/index.html 27 | - text: News 28 | menu: 29 | - text: "Release notes" 30 | - text: "SGP 2.1-0.0" 31 | href: articles/releases/SGP-2.1-0.0.html 32 | - text: "SGP 2.0-0.0" 33 | href: articles/releases/SGP-2.0-0.0.html 34 | - text: "SGP 1.9-5.0" 35 | href: articles/releases/SGP-1.9-5.0.html 36 | - text: "SGP 1.9-0.0" 37 | href: articles/releases/SGP-1.9-0.0.html 38 | - text: "SGP 1.8-0.0" 39 | href: articles/releases/SGP-1.8-0.0.html 40 | - text: "SGP 1.7-0.0" 41 | href: articles/releases/SGP-1.7-0.0.html 42 | - text: "SGP 1.6-0.0" 43 | href: articles/releases/SGP-1.6-0.0.html 44 | - text: "SGP 1.5-0.0" 45 | href: articles/releases/SGP-1.5-0.0.html 46 | - text: "SGP 1.4-0.0" 47 | href: articles/releases/SGP-1.4-0.0.html 48 | - text: "------------------" 49 | - text: "Change log" 50 | href: news/index.html 51 | right: 52 | - icon: 'fab fa-github' 53 | href: https://github.com/centerforassessment/SGP 54 | - icon: 'fab fa-twitter' 55 | href: https://twitter.com/intent/tweet?url=https%3A%2F%2Fsgp.io&via=NCIEA1&text=SGP%3A%20Student%20Growth%20Percentiles%20%26%20Percentile%20Growth%20Trajectories&hashtags=rstats%2CSGP 56 | 57 | 58 | reference: 59 | - title: Low level SGP functions 60 | desc: These functions are responsible for all student growth percentile and student growth projection calculation. 61 | contents: 62 | - studentGrowthPercentiles 63 | - studentGrowthProjections 64 | - title: High level SGP functions 65 | desc: These functions simplify operation SGP calculations as wrappers for low level functions. 66 | contents: 67 | - abcSGP 68 | - analyzeSGP 69 | - baselineSGP 70 | - combineSGP 71 | - outputSGP 72 | - prepareSGP 73 | - rliSGP 74 | - summarizeSGP 75 | - testSGP 76 | - updateSGP 77 | - visualizeSGP 78 | - title: SGP utility functions 79 | desc: These functions are used in various ways as part SGP analyses. 80 | contents: 81 | - bubblePlot 82 | - bubblePlot_Styles 83 | - courseProgressionSGP 84 | - createKnotsBoundaries 85 | - capwords 86 | - getStateAbbreviation 87 | - gofSGP 88 | - growthAchievementPlot 89 | - is.splineMatrix 90 | - is.SGP 91 | - studentGrowthPlot 92 | - studentGrowthPlot_Styles 93 | - title: SGP meta-data for state/organization level analyses 94 | desc: This internal data set contains meta-data and configurations used as part of state/organization level analyses. 95 | contents: 96 | - SGPstateData 97 | -------------------------------------------------------------------------------- /data/SGPstateData.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CenterForAssessment/SGP/aab195e7a06c11778837a3db1b683923d5c01174/data/SGPstateData.rda -------------------------------------------------------------------------------- /data/datalist: -------------------------------------------------------------------------------- 1 | SGPstateData 2 | -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | sgp.io 2 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Analysis_files/anchor-sections-1.1.0/anchor-sections-hash.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors */ 2 | a.anchor-section::before {content: '#';font-size: 80%;} 3 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Analysis_files/anchor-sections-1.1.0/anchor-sections-icon.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors content */ 2 | /* From https://icons.getbootstrap.com/icons/link-45deg/ 3 | Licence: https://github.com/twbs/icons/blob/main/LICENSE.md */ 4 | 5 | a.anchor-section:before { 6 | display: inline-block; 7 | content: url("data:image/svg+xml,"); 8 | } 9 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Analysis_files/anchor-sections-1.1.0/anchor-sections-symbol.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors content */ 2 | /* Link symbol : https://codepoints.net/U+1F517 3 | with variation selector https://graphemica.com/FE0E */ 4 | a.anchor-section::before{content: '\01F517\00FE0E';font-size: 20px;} 5 | /* deactivate underline for link symbol */ 6 | a.anchor-section:hover {text-decoration: none;} 7 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Analysis_files/anchor-sections-1.1.0/anchor-sections.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors */ 2 | a.anchor-section {margin-left: 10px; visibility: hidden; color: inherit;} 3 | .hasAnchor:hover a.anchor-section {visibility: visible;} 4 | ul > li > .anchor-section {display: none;} 5 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Analysis_files/anchor-sections-1.1.0/anchor-sections.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', function () { 2 | // If section divs is used, we need to put the anchor in the child header 3 | const headers = document.querySelectorAll("div.hasAnchor.section[class*='level'] > :first-child") 4 | 5 | headers.forEach(function (x) { 6 | // Add to the header node 7 | if (!x.classList.contains('hasAnchor')) x.classList.add('hasAnchor') 8 | // Remove from the section or div created by Pandoc 9 | x.parentElement.classList.remove('hasAnchor') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Analysis_files/header-attrs-2.13/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Analysis_files/header-attrs-2.14/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Analysis_files/header-attrs-2.22/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Analysis_files/header-attrs-2.25/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Analysis_files/header-attrs-2.7/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Analysis_files/header-attrs-2.8/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Preparation_files/anchor-sections-1.1.0/anchor-sections-hash.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors */ 2 | a.anchor-section::before {content: '#';font-size: 80%;} 3 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Preparation_files/anchor-sections-1.1.0/anchor-sections-icon.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors content */ 2 | /* From https://icons.getbootstrap.com/icons/link-45deg/ 3 | Licence: https://github.com/twbs/icons/blob/main/LICENSE.md */ 4 | 5 | a.anchor-section:before { 6 | display: inline-block; 7 | content: url("data:image/svg+xml,"); 8 | } 9 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Preparation_files/anchor-sections-1.1.0/anchor-sections-symbol.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors content */ 2 | /* Link symbol : https://codepoints.net/U+1F517 3 | with variation selector https://graphemica.com/FE0E */ 4 | a.anchor-section::before{content: '\01F517\00FE0E';font-size: 20px;} 5 | /* deactivate underline for link symbol */ 6 | a.anchor-section:hover {text-decoration: none;} 7 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Preparation_files/anchor-sections-1.1.0/anchor-sections.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors */ 2 | a.anchor-section {margin-left: 10px; visibility: hidden; color: inherit;} 3 | .hasAnchor:hover a.anchor-section {visibility: visible;} 4 | ul > li > .anchor-section {display: none;} 5 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Preparation_files/anchor-sections-1.1.0/anchor-sections.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', function () { 2 | // If section divs is used, we need to put the anchor in the child header 3 | const headers = document.querySelectorAll("div.hasAnchor.section[class*='level'] > :first-child") 4 | 5 | headers.forEach(function (x) { 6 | // Add to the header node 7 | if (!x.classList.contains('hasAnchor')) x.classList.add('hasAnchor') 8 | // Remove from the section or div created by Pandoc 9 | x.parentElement.classList.remove('hasAnchor') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Preparation_files/crosstalk-1.1.0.1/css/crosstalk.css: -------------------------------------------------------------------------------- 1 | /* Adjust margins outwards, so column contents line up with the edges of the 2 | parent of container-fluid. */ 3 | .container-fluid.crosstalk-bscols { 4 | margin-left: -30px; 5 | margin-right: -30px; 6 | white-space: normal; 7 | } 8 | 9 | /* But don't adjust the margins outwards if we're directly under the body, 10 | i.e. we were the top-level of something at the console. */ 11 | body > .container-fluid.crosstalk-bscols { 12 | margin-left: auto; 13 | margin-right: auto; 14 | } 15 | 16 | .crosstalk-input-checkboxgroup .crosstalk-options-group .crosstalk-options-column { 17 | display: inline-block; 18 | padding-right: 12px; 19 | vertical-align: top; 20 | } 21 | 22 | @media only screen and (max-width:480px) { 23 | .crosstalk-input-checkboxgroup .crosstalk-options-group .crosstalk-options-column { 24 | display: block; 25 | padding-right: inherit; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Preparation_files/crosstalk-1.1.1/css/crosstalk.css: -------------------------------------------------------------------------------- 1 | /* Adjust margins outwards, so column contents line up with the edges of the 2 | parent of container-fluid. */ 3 | .container-fluid.crosstalk-bscols { 4 | margin-left: -30px; 5 | margin-right: -30px; 6 | white-space: normal; 7 | } 8 | 9 | /* But don't adjust the margins outwards if we're directly under the body, 10 | i.e. we were the top-level of something at the console. */ 11 | body > .container-fluid.crosstalk-bscols { 12 | margin-left: auto; 13 | margin-right: auto; 14 | } 15 | 16 | .crosstalk-input-checkboxgroup .crosstalk-options-group .crosstalk-options-column { 17 | display: inline-block; 18 | padding-right: 12px; 19 | vertical-align: top; 20 | } 21 | 22 | @media only screen and (max-width:480px) { 23 | .crosstalk-input-checkboxgroup .crosstalk-options-group .crosstalk-options-column { 24 | display: block; 25 | padding-right: inherit; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Preparation_files/crosstalk-1.2.0/css/crosstalk.min.css: -------------------------------------------------------------------------------- 1 | .container-fluid.crosstalk-bscols{margin-left:-30px;margin-right:-30px;white-space:normal}body>.container-fluid.crosstalk-bscols{margin-left:auto;margin-right:auto}.crosstalk-input-checkboxgroup .crosstalk-options-group .crosstalk-options-column{display:inline-block;padding-right:12px;vertical-align:top}@media only screen and (max-width: 480px){.crosstalk-input-checkboxgroup .crosstalk-options-group .crosstalk-options-column{display:block;padding-right:inherit}}.crosstalk-input{margin-bottom:15px}.crosstalk-input .control-label{margin-bottom:0;vertical-align:middle}.crosstalk-input input[type="checkbox"]{margin:4px 0 0;margin-top:1px;line-height:normal}.crosstalk-input .checkbox{position:relative;display:block;margin-top:10px;margin-bottom:10px}.crosstalk-input .checkbox>label{padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.crosstalk-input .checkbox input[type="checkbox"],.crosstalk-input .checkbox-inline input[type="checkbox"]{position:absolute;margin-top:2px;margin-left:-20px}.crosstalk-input .checkbox+.checkbox{margin-top:-5px}.crosstalk-input .checkbox-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.crosstalk-input .checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px} 2 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Preparation_files/crosstalk-1.2.0/scss/crosstalk.scss: -------------------------------------------------------------------------------- 1 | /* Adjust margins outwards, so column contents line up with the edges of the 2 | parent of container-fluid. */ 3 | .container-fluid.crosstalk-bscols { 4 | margin-left: -30px; 5 | margin-right: -30px; 6 | white-space: normal; 7 | } 8 | 9 | /* But don't adjust the margins outwards if we're directly under the body, 10 | i.e. we were the top-level of something at the console. */ 11 | body > .container-fluid.crosstalk-bscols { 12 | margin-left: auto; 13 | margin-right: auto; 14 | } 15 | 16 | .crosstalk-input-checkboxgroup .crosstalk-options-group .crosstalk-options-column { 17 | display: inline-block; 18 | padding-right: 12px; 19 | vertical-align: top; 20 | } 21 | 22 | @media only screen and (max-width:480px) { 23 | .crosstalk-input-checkboxgroup .crosstalk-options-group .crosstalk-options-column { 24 | display: block; 25 | padding-right: inherit; 26 | } 27 | } 28 | 29 | /* Relevant BS3 styles to make filter_checkbox() look reasonable without Bootstrap */ 30 | .crosstalk-input { 31 | margin-bottom: 15px; /* a la .form-group */ 32 | .control-label { 33 | margin-bottom: 0; 34 | vertical-align: middle; 35 | } 36 | input[type="checkbox"] { 37 | margin: 4px 0 0; 38 | margin-top: 1px; 39 | line-height: normal; 40 | } 41 | .checkbox { 42 | position: relative; 43 | display: block; 44 | margin-top: 10px; 45 | margin-bottom: 10px; 46 | } 47 | .checkbox > label{ 48 | padding-left: 20px; 49 | margin-bottom: 0; 50 | font-weight: 400; 51 | cursor: pointer; 52 | } 53 | .checkbox input[type="checkbox"], 54 | .checkbox-inline input[type="checkbox"] { 55 | position: absolute; 56 | margin-top: 2px; 57 | margin-left: -20px; 58 | } 59 | .checkbox + .checkbox { 60 | margin-top: -5px; 61 | } 62 | .checkbox-inline { 63 | position: relative; 64 | display: inline-block; 65 | padding-left: 20px; 66 | margin-bottom: 0; 67 | font-weight: 400; 68 | vertical-align: middle; 69 | cursor: pointer; 70 | } 71 | .checkbox-inline + .checkbox-inline { 72 | margin-top: 0; 73 | margin-left: 10px; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Preparation_files/header-attrs-2.13/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Preparation_files/header-attrs-2.14/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Preparation_files/header-attrs-2.22/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Preparation_files/header-attrs-2.25/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Preparation_files/header-attrs-2.7/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Preparation_files/header-attrs-2.8/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Preparation_files/plotly-htmlwidgets-css-1.52.2/plotly-htmlwidgets.css: -------------------------------------------------------------------------------- 1 | /* 2 | just here so that plotly works 3 | correctly with ioslides. 4 | see https://github.com/ropensci/plotly/issues/463 5 | */ 6 | 7 | slide:not(.current) .plotly.html-widget{ 8 | display: none; 9 | } 10 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Preparation_files/plotly-htmlwidgets-css-1.57.1/plotly-htmlwidgets.css: -------------------------------------------------------------------------------- 1 | /* 2 | just here so that plotly works 3 | correctly with ioslides. 4 | see https://github.com/ropensci/plotly/issues/463 5 | */ 6 | 7 | slide:not(.current) .plotly.html-widget{ 8 | display: none; 9 | } 10 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Preparation_files/plotly-htmlwidgets-css-2.11.1/plotly-htmlwidgets.css: -------------------------------------------------------------------------------- 1 | /* 2 | just here so that plotly works 3 | correctly with ioslides. 4 | see https://github.com/ropensci/plotly/issues/463 5 | */ 6 | 7 | slide:not(.current) .plotly.html-widget{ 8 | display: none; 9 | } 10 | -------------------------------------------------------------------------------- /docs/articles/SGP_Data_Preparation_files/plotly-htmlwidgets-css-2.5.1/plotly-htmlwidgets.css: -------------------------------------------------------------------------------- 1 | /* 2 | just here so that plotly works 3 | correctly with ioslides. 4 | see https://github.com/ropensci/plotly/issues/463 5 | */ 6 | 7 | slide:not(.current) .plotly.html-widget{ 8 | display: none; 9 | } 10 | -------------------------------------------------------------------------------- /docs/articles/SGP_files/anchor-sections-1.1.0/anchor-sections-hash.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors */ 2 | a.anchor-section::before {content: '#';font-size: 80%;} 3 | -------------------------------------------------------------------------------- /docs/articles/SGP_files/anchor-sections-1.1.0/anchor-sections-icon.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors content */ 2 | /* From https://icons.getbootstrap.com/icons/link-45deg/ 3 | Licence: https://github.com/twbs/icons/blob/main/LICENSE.md */ 4 | 5 | a.anchor-section:before { 6 | display: inline-block; 7 | content: url("data:image/svg+xml,"); 8 | } 9 | -------------------------------------------------------------------------------- /docs/articles/SGP_files/anchor-sections-1.1.0/anchor-sections-symbol.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors content */ 2 | /* Link symbol : https://codepoints.net/U+1F517 3 | with variation selector https://graphemica.com/FE0E */ 4 | a.anchor-section::before{content: '\01F517\00FE0E';font-size: 20px;} 5 | /* deactivate underline for link symbol */ 6 | a.anchor-section:hover {text-decoration: none;} 7 | -------------------------------------------------------------------------------- /docs/articles/SGP_files/anchor-sections-1.1.0/anchor-sections.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors */ 2 | a.anchor-section {margin-left: 10px; visibility: hidden; color: inherit;} 3 | .hasAnchor:hover a.anchor-section {visibility: visible;} 4 | ul > li > .anchor-section {display: none;} 5 | -------------------------------------------------------------------------------- /docs/articles/SGP_files/anchor-sections-1.1.0/anchor-sections.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', function () { 2 | // If section divs is used, we need to put the anchor in the child header 3 | const headers = document.querySelectorAll("div.hasAnchor.section[class*='level'] > :first-child") 4 | 5 | headers.forEach(function (x) { 6 | // Add to the header node 7 | if (!x.classList.contains('hasAnchor')) x.classList.add('hasAnchor') 8 | // Remove from the section or div created by Pandoc 9 | x.parentElement.classList.remove('hasAnchor') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /docs/articles/SGP_files/header-attrs-2.13/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/SGP_files/header-attrs-2.14/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/SGP_files/header-attrs-2.22/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/SGP_files/header-attrs-2.25/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/SGP_files/header-attrs-2.7/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/SGP_files/header-attrs-2.8/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.4-0.0_files/anchor-sections-1.1.0/anchor-sections-hash.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors */ 2 | a.anchor-section::before {content: '#';font-size: 80%;} 3 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.4-0.0_files/anchor-sections-1.1.0/anchor-sections-icon.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors content */ 2 | /* From https://icons.getbootstrap.com/icons/link-45deg/ 3 | Licence: https://github.com/twbs/icons/blob/main/LICENSE.md */ 4 | 5 | a.anchor-section:before { 6 | display: inline-block; 7 | content: url("data:image/svg+xml,"); 8 | } 9 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.4-0.0_files/anchor-sections-1.1.0/anchor-sections-symbol.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors content */ 2 | /* Link symbol : https://codepoints.net/U+1F517 3 | with variation selector https://graphemica.com/FE0E */ 4 | a.anchor-section::before{content: '\01F517\00FE0E';font-size: 20px;} 5 | /* deactivate underline for link symbol */ 6 | a.anchor-section:hover {text-decoration: none;} 7 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.4-0.0_files/anchor-sections-1.1.0/anchor-sections.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors */ 2 | a.anchor-section {margin-left: 10px; visibility: hidden; color: inherit;} 3 | .hasAnchor:hover a.anchor-section {visibility: visible;} 4 | ul > li > .anchor-section {display: none;} 5 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.4-0.0_files/anchor-sections-1.1.0/anchor-sections.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', function () { 2 | // If section divs is used, we need to put the anchor in the child header 3 | const headers = document.querySelectorAll("div.hasAnchor.section[class*='level'] > :first-child") 4 | 5 | headers.forEach(function (x) { 6 | // Add to the header node 7 | if (!x.classList.contains('hasAnchor')) x.classList.add('hasAnchor') 8 | // Remove from the section or div created by Pandoc 9 | x.parentElement.classList.remove('hasAnchor') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.4-0.0_files/header-attrs-2.13/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.4-0.0_files/header-attrs-2.14/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.4-0.0_files/header-attrs-2.22/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.4-0.0_files/header-attrs-2.25/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.4-0.0_files/header-attrs-2.7/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.4-0.0_files/header-attrs-2.8/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.5-0.0_files/anchor-sections-1.1.0/anchor-sections-hash.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors */ 2 | a.anchor-section::before {content: '#';font-size: 80%;} 3 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.5-0.0_files/anchor-sections-1.1.0/anchor-sections-icon.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors content */ 2 | /* From https://icons.getbootstrap.com/icons/link-45deg/ 3 | Licence: https://github.com/twbs/icons/blob/main/LICENSE.md */ 4 | 5 | a.anchor-section:before { 6 | display: inline-block; 7 | content: url("data:image/svg+xml,"); 8 | } 9 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.5-0.0_files/anchor-sections-1.1.0/anchor-sections-symbol.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors content */ 2 | /* Link symbol : https://codepoints.net/U+1F517 3 | with variation selector https://graphemica.com/FE0E */ 4 | a.anchor-section::before{content: '\01F517\00FE0E';font-size: 20px;} 5 | /* deactivate underline for link symbol */ 6 | a.anchor-section:hover {text-decoration: none;} 7 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.5-0.0_files/anchor-sections-1.1.0/anchor-sections.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors */ 2 | a.anchor-section {margin-left: 10px; visibility: hidden; color: inherit;} 3 | .hasAnchor:hover a.anchor-section {visibility: visible;} 4 | ul > li > .anchor-section {display: none;} 5 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.5-0.0_files/anchor-sections-1.1.0/anchor-sections.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', function () { 2 | // If section divs is used, we need to put the anchor in the child header 3 | const headers = document.querySelectorAll("div.hasAnchor.section[class*='level'] > :first-child") 4 | 5 | headers.forEach(function (x) { 6 | // Add to the header node 7 | if (!x.classList.contains('hasAnchor')) x.classList.add('hasAnchor') 8 | // Remove from the section or div created by Pandoc 9 | x.parentElement.classList.remove('hasAnchor') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.5-0.0_files/header-attrs-2.13/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.5-0.0_files/header-attrs-2.14/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.5-0.0_files/header-attrs-2.22/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.5-0.0_files/header-attrs-2.25/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.5-0.0_files/header-attrs-2.7/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.5-0.0_files/header-attrs-2.8/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.6-0.0_files/anchor-sections-1.1.0/anchor-sections-hash.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors */ 2 | a.anchor-section::before {content: '#';font-size: 80%;} 3 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.6-0.0_files/anchor-sections-1.1.0/anchor-sections-icon.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors content */ 2 | /* From https://icons.getbootstrap.com/icons/link-45deg/ 3 | Licence: https://github.com/twbs/icons/blob/main/LICENSE.md */ 4 | 5 | a.anchor-section:before { 6 | display: inline-block; 7 | content: url("data:image/svg+xml,"); 8 | } 9 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.6-0.0_files/anchor-sections-1.1.0/anchor-sections-symbol.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors content */ 2 | /* Link symbol : https://codepoints.net/U+1F517 3 | with variation selector https://graphemica.com/FE0E */ 4 | a.anchor-section::before{content: '\01F517\00FE0E';font-size: 20px;} 5 | /* deactivate underline for link symbol */ 6 | a.anchor-section:hover {text-decoration: none;} 7 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.6-0.0_files/anchor-sections-1.1.0/anchor-sections.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors */ 2 | a.anchor-section {margin-left: 10px; visibility: hidden; color: inherit;} 3 | .hasAnchor:hover a.anchor-section {visibility: visible;} 4 | ul > li > .anchor-section {display: none;} 5 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.6-0.0_files/anchor-sections-1.1.0/anchor-sections.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', function () { 2 | // If section divs is used, we need to put the anchor in the child header 3 | const headers = document.querySelectorAll("div.hasAnchor.section[class*='level'] > :first-child") 4 | 5 | headers.forEach(function (x) { 6 | // Add to the header node 7 | if (!x.classList.contains('hasAnchor')) x.classList.add('hasAnchor') 8 | // Remove from the section or div created by Pandoc 9 | x.parentElement.classList.remove('hasAnchor') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.6-0.0_files/header-attrs-2.13/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.6-0.0_files/header-attrs-2.14/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.6-0.0_files/header-attrs-2.22/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.6-0.0_files/header-attrs-2.25/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.6-0.0_files/header-attrs-2.7/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.6-0.0_files/header-attrs-2.8/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.7-0.0_files/anchor-sections-1.1.0/anchor-sections-hash.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors */ 2 | a.anchor-section::before {content: '#';font-size: 80%;} 3 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.7-0.0_files/anchor-sections-1.1.0/anchor-sections-icon.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors content */ 2 | /* From https://icons.getbootstrap.com/icons/link-45deg/ 3 | Licence: https://github.com/twbs/icons/blob/main/LICENSE.md */ 4 | 5 | a.anchor-section:before { 6 | display: inline-block; 7 | content: url("data:image/svg+xml,"); 8 | } 9 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.7-0.0_files/anchor-sections-1.1.0/anchor-sections-symbol.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors content */ 2 | /* Link symbol : https://codepoints.net/U+1F517 3 | with variation selector https://graphemica.com/FE0E */ 4 | a.anchor-section::before{content: '\01F517\00FE0E';font-size: 20px;} 5 | /* deactivate underline for link symbol */ 6 | a.anchor-section:hover {text-decoration: none;} 7 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.7-0.0_files/anchor-sections-1.1.0/anchor-sections.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors */ 2 | a.anchor-section {margin-left: 10px; visibility: hidden; color: inherit;} 3 | .hasAnchor:hover a.anchor-section {visibility: visible;} 4 | ul > li > .anchor-section {display: none;} 5 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.7-0.0_files/anchor-sections-1.1.0/anchor-sections.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', function () { 2 | // If section divs is used, we need to put the anchor in the child header 3 | const headers = document.querySelectorAll("div.hasAnchor.section[class*='level'] > :first-child") 4 | 5 | headers.forEach(function (x) { 6 | // Add to the header node 7 | if (!x.classList.contains('hasAnchor')) x.classList.add('hasAnchor') 8 | // Remove from the section or div created by Pandoc 9 | x.parentElement.classList.remove('hasAnchor') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.7-0.0_files/header-attrs-2.13/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.7-0.0_files/header-attrs-2.14/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.7-0.0_files/header-attrs-2.22/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.7-0.0_files/header-attrs-2.25/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.7-0.0_files/header-attrs-2.7/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.7-0.0_files/header-attrs-2.8/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.8-0.0_files/anchor-sections-1.1.0/anchor-sections-hash.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors */ 2 | a.anchor-section::before {content: '#';font-size: 80%;} 3 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.8-0.0_files/anchor-sections-1.1.0/anchor-sections-icon.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors content */ 2 | /* From https://icons.getbootstrap.com/icons/link-45deg/ 3 | Licence: https://github.com/twbs/icons/blob/main/LICENSE.md */ 4 | 5 | a.anchor-section:before { 6 | display: inline-block; 7 | content: url("data:image/svg+xml,"); 8 | } 9 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.8-0.0_files/anchor-sections-1.1.0/anchor-sections-symbol.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors content */ 2 | /* Link symbol : https://codepoints.net/U+1F517 3 | with variation selector https://graphemica.com/FE0E */ 4 | a.anchor-section::before{content: '\01F517\00FE0E';font-size: 20px;} 5 | /* deactivate underline for link symbol */ 6 | a.anchor-section:hover {text-decoration: none;} 7 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.8-0.0_files/anchor-sections-1.1.0/anchor-sections.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors */ 2 | a.anchor-section {margin-left: 10px; visibility: hidden; color: inherit;} 3 | .hasAnchor:hover a.anchor-section {visibility: visible;} 4 | ul > li > .anchor-section {display: none;} 5 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.8-0.0_files/anchor-sections-1.1.0/anchor-sections.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', function () { 2 | // If section divs is used, we need to put the anchor in the child header 3 | const headers = document.querySelectorAll("div.hasAnchor.section[class*='level'] > :first-child") 4 | 5 | headers.forEach(function (x) { 6 | // Add to the header node 7 | if (!x.classList.contains('hasAnchor')) x.classList.add('hasAnchor') 8 | // Remove from the section or div created by Pandoc 9 | x.parentElement.classList.remove('hasAnchor') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.8-0.0_files/header-attrs-2.13/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.8-0.0_files/header-attrs-2.14/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.8-0.0_files/header-attrs-2.22/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.8-0.0_files/header-attrs-2.25/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.8-0.0_files/header-attrs-2.7/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.8-0.0_files/header-attrs-2.8/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.9-0.0_files/anchor-sections-1.1.0/anchor-sections-hash.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors */ 2 | a.anchor-section::before {content: '#';font-size: 80%;} 3 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.9-0.0_files/anchor-sections-1.1.0/anchor-sections-icon.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors content */ 2 | /* From https://icons.getbootstrap.com/icons/link-45deg/ 3 | Licence: https://github.com/twbs/icons/blob/main/LICENSE.md */ 4 | 5 | a.anchor-section:before { 6 | display: inline-block; 7 | content: url("data:image/svg+xml,"); 8 | } 9 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.9-0.0_files/anchor-sections-1.1.0/anchor-sections-symbol.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors content */ 2 | /* Link symbol : https://codepoints.net/U+1F517 3 | with variation selector https://graphemica.com/FE0E */ 4 | a.anchor-section::before{content: '\01F517\00FE0E';font-size: 20px;} 5 | /* deactivate underline for link symbol */ 6 | a.anchor-section:hover {text-decoration: none;} 7 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.9-0.0_files/anchor-sections-1.1.0/anchor-sections.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors */ 2 | a.anchor-section {margin-left: 10px; visibility: hidden; color: inherit;} 3 | .hasAnchor:hover a.anchor-section {visibility: visible;} 4 | ul > li > .anchor-section {display: none;} 5 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.9-0.0_files/anchor-sections-1.1.0/anchor-sections.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', function () { 2 | // If section divs is used, we need to put the anchor in the child header 3 | const headers = document.querySelectorAll("div.hasAnchor.section[class*='level'] > :first-child") 4 | 5 | headers.forEach(function (x) { 6 | // Add to the header node 7 | if (!x.classList.contains('hasAnchor')) x.classList.add('hasAnchor') 8 | // Remove from the section or div created by Pandoc 9 | x.parentElement.classList.remove('hasAnchor') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.9-0.0_files/header-attrs-2.13/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.9-0.0_files/header-attrs-2.14/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.9-0.0_files/header-attrs-2.22/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.9-0.0_files/header-attrs-2.25/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.9-0.0_files/header-attrs-2.7/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.9-0.0_files/header-attrs-2.8/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.9-5.0_files/anchor-sections-1.1.0/anchor-sections-hash.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors */ 2 | a.anchor-section::before {content: '#';font-size: 80%;} 3 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.9-5.0_files/anchor-sections-1.1.0/anchor-sections-icon.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors content */ 2 | /* From https://icons.getbootstrap.com/icons/link-45deg/ 3 | Licence: https://github.com/twbs/icons/blob/main/LICENSE.md */ 4 | 5 | a.anchor-section:before { 6 | display: inline-block; 7 | content: url("data:image/svg+xml,"); 8 | } 9 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.9-5.0_files/anchor-sections-1.1.0/anchor-sections-symbol.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors content */ 2 | /* Link symbol : https://codepoints.net/U+1F517 3 | with variation selector https://graphemica.com/FE0E */ 4 | a.anchor-section::before{content: '\01F517\00FE0E';font-size: 20px;} 5 | /* deactivate underline for link symbol */ 6 | a.anchor-section:hover {text-decoration: none;} 7 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.9-5.0_files/anchor-sections-1.1.0/anchor-sections.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors */ 2 | a.anchor-section {margin-left: 10px; visibility: hidden; color: inherit;} 3 | .hasAnchor:hover a.anchor-section {visibility: visible;} 4 | ul > li > .anchor-section {display: none;} 5 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.9-5.0_files/anchor-sections-1.1.0/anchor-sections.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', function () { 2 | // If section divs is used, we need to put the anchor in the child header 3 | const headers = document.querySelectorAll("div.hasAnchor.section[class*='level'] > :first-child") 4 | 5 | headers.forEach(function (x) { 6 | // Add to the header node 7 | if (!x.classList.contains('hasAnchor')) x.classList.add('hasAnchor') 8 | // Remove from the section or div created by Pandoc 9 | x.parentElement.classList.remove('hasAnchor') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.9-5.0_files/header-attrs-2.13/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.9-5.0_files/header-attrs-2.14/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.9-5.0_files/header-attrs-2.22/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.9-5.0_files/header-attrs-2.25/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.9-5.0_files/header-attrs-2.7/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-1.9-5.0_files/header-attrs-2.8/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-2.0-0.0_files/anchor-sections-1.1.0/anchor-sections-hash.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors */ 2 | a.anchor-section::before {content: '#';font-size: 80%;} 3 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-2.0-0.0_files/anchor-sections-1.1.0/anchor-sections-icon.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors content */ 2 | /* From https://icons.getbootstrap.com/icons/link-45deg/ 3 | Licence: https://github.com/twbs/icons/blob/main/LICENSE.md */ 4 | 5 | a.anchor-section:before { 6 | display: inline-block; 7 | content: url("data:image/svg+xml,"); 8 | } 9 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-2.0-0.0_files/anchor-sections-1.1.0/anchor-sections-symbol.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors content */ 2 | /* Link symbol : https://codepoints.net/U+1F517 3 | with variation selector https://graphemica.com/FE0E */ 4 | a.anchor-section::before{content: '\01F517\00FE0E';font-size: 20px;} 5 | /* deactivate underline for link symbol */ 6 | a.anchor-section:hover {text-decoration: none;} 7 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-2.0-0.0_files/anchor-sections-1.1.0/anchor-sections.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors */ 2 | a.anchor-section {margin-left: 10px; visibility: hidden; color: inherit;} 3 | .hasAnchor:hover a.anchor-section {visibility: visible;} 4 | ul > li > .anchor-section {display: none;} 5 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-2.0-0.0_files/anchor-sections-1.1.0/anchor-sections.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', function () { 2 | // If section divs is used, we need to put the anchor in the child header 3 | const headers = document.querySelectorAll("div.hasAnchor.section[class*='level'] > :first-child") 4 | 5 | headers.forEach(function (x) { 6 | // Add to the header node 7 | if (!x.classList.contains('hasAnchor')) x.classList.add('hasAnchor') 8 | // Remove from the section or div created by Pandoc 9 | x.parentElement.classList.remove('hasAnchor') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-2.0-0.0_files/header-attrs-2.22/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-2.0-0.0_files/header-attrs-2.25/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-2.1-0.0_files/anchor-sections-1.1.0/anchor-sections-hash.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors */ 2 | a.anchor-section::before {content: '#';font-size: 80%;} 3 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-2.1-0.0_files/anchor-sections-1.1.0/anchor-sections-icon.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors content */ 2 | /* From https://icons.getbootstrap.com/icons/link-45deg/ 3 | Licence: https://github.com/twbs/icons/blob/main/LICENSE.md */ 4 | 5 | a.anchor-section:before { 6 | display: inline-block; 7 | content: url("data:image/svg+xml,"); 8 | } 9 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-2.1-0.0_files/anchor-sections-1.1.0/anchor-sections-symbol.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors content */ 2 | /* Link symbol : https://codepoints.net/U+1F517 3 | with variation selector https://graphemica.com/FE0E */ 4 | a.anchor-section::before{content: '\01F517\00FE0E';font-size: 20px;} 5 | /* deactivate underline for link symbol */ 6 | a.anchor-section:hover {text-decoration: none;} 7 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-2.1-0.0_files/anchor-sections-1.1.0/anchor-sections.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors */ 2 | a.anchor-section {margin-left: 10px; visibility: hidden; color: inherit;} 3 | .hasAnchor:hover a.anchor-section {visibility: visible;} 4 | ul > li > .anchor-section {display: none;} 5 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-2.1-0.0_files/anchor-sections-1.1.0/anchor-sections.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', function () { 2 | // If section divs is used, we need to put the anchor in the child header 3 | const headers = document.querySelectorAll("div.hasAnchor.section[class*='level'] > :first-child") 4 | 5 | headers.forEach(function (x) { 6 | // Add to the header node 7 | if (!x.classList.contains('hasAnchor')) x.classList.add('hasAnchor') 8 | // Remove from the section or div created by Pandoc 9 | x.parentElement.classList.remove('hasAnchor') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-2.1-0.0_files/header-attrs-2.22/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/releases/SGP-2.1-0.0_files/header-attrs-2.25/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/img/REPO_CARD_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CenterForAssessment/SGP/aab195e7a06c11778837a3db1b683923d5c01174/docs/img/REPO_CARD_image.png -------------------------------------------------------------------------------- /docs/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CenterForAssessment/SGP/aab195e7a06c11778837a3db1b683923d5c01174/docs/img/favicon.png -------------------------------------------------------------------------------- /docs/img/link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /docs/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CenterForAssessment/SGP/aab195e7a06c11778837a3db1b683923d5c01174/docs/img/logo.png -------------------------------------------------------------------------------- /docs/img/logo_grey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CenterForAssessment/SGP/aab195e7a06c11778837a3db1b683923d5c01174/docs/img/logo_grey.png -------------------------------------------------------------------------------- /docs/img/logo_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CenterForAssessment/SGP/aab195e7a06c11778837a3db1b683923d5c01174/docs/img/logo_white.png -------------------------------------------------------------------------------- /docs/img/tocBullet.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /docs/jquery.sticky-kit.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net 3 | */ 4 | (function(){var b,f;b=this.jQuery||window.jQuery;f=b(window);b.fn.stick_in_parent=function(d){var A,w,J,n,B,K,p,q,k,E,t;null==d&&(d={});t=d.sticky_class;B=d.inner_scrolling;E=d.recalc_every;k=d.parent;q=d.offset_top;p=d.spacer;w=d.bottoming;null==q&&(q=0);null==k&&(k=void 0);null==B&&(B=!0);null==t&&(t="is_stuck");A=b(document);null==w&&(w=!0);J=function(a,d,n,C,F,u,r,G){var v,H,m,D,I,c,g,x,y,z,h,l;if(!a.data("sticky_kit")){a.data("sticky_kit",!0);I=A.height();g=a.parent();null!=k&&(g=g.closest(k)); 5 | if(!g.length)throw"failed to find stick parent";v=m=!1;(h=null!=p?p&&a.closest(p):b("
"))&&h.css("position",a.css("position"));x=function(){var c,f,e;if(!G&&(I=A.height(),c=parseInt(g.css("border-top-width"),10),f=parseInt(g.css("padding-top"),10),d=parseInt(g.css("padding-bottom"),10),n=g.offset().top+c+f,C=g.height(),m&&(v=m=!1,null==p&&(a.insertAfter(h),h.detach()),a.css({position:"",top:"",width:"",bottom:""}).removeClass(t),e=!0),F=a.offset().top-(parseInt(a.css("margin-top"),10)||0)-q, 6 | u=a.outerHeight(!0),r=a.css("float"),h&&h.css({width:a.outerWidth(!0),height:u,display:a.css("display"),"vertical-align":a.css("vertical-align"),"float":r}),e))return l()};x();if(u!==C)return D=void 0,c=q,z=E,l=function(){var b,l,e,k;if(!G&&(e=!1,null!=z&&(--z,0>=z&&(z=E,x(),e=!0)),e||A.height()===I||x(),e=f.scrollTop(),null!=D&&(l=e-D),D=e,m?(w&&(k=e+u+c>C+n,v&&!k&&(v=!1,a.css({position:"fixed",bottom:"",top:c}).trigger("sticky_kit:unbottom"))),eb&&!v&&(c-=l,c=Math.max(b-u,c),c=Math.min(q,c),m&&a.css({top:c+"px"})))):e>F&&(m=!0,b={position:"fixed",top:c},b.width="border-box"===a.css("box-sizing")?a.outerWidth()+"px":a.width()+"px",a.css(b).addClass(t),null==p&&(a.after(h),"left"!==r&&"right"!==r||h.append(a)),a.trigger("sticky_kit:stick")),m&&w&&(null==k&&(k=e+u+c>C+n),!v&&k)))return v=!0,"static"===g.css("position")&&g.css({position:"relative"}), 8 | a.css({position:"absolute",bottom:d,top:"auto"}).trigger("sticky_kit:bottom")},y=function(){x();return l()},H=function(){G=!0;f.off("touchmove",l);f.off("scroll",l);f.off("resize",y);b(document.body).off("sticky_kit:recalc",y);a.off("sticky_kit:detach",H);a.removeData("sticky_kit");a.css({position:"",bottom:"",top:"",width:""});g.position("position","");if(m)return null==p&&("left"!==r&&"right"!==r||a.insertAfter(h),h.remove()),a.removeClass(t)},f.on("touchmove",l),f.on("scroll",l),f.on("resize", 9 | y),b(document.body).on("sticky_kit:recalc",y),a.on("sticky_kit:detach",H),setTimeout(l,0)}};n=0;for(K=this.length;n 2 | 3 | 5 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /docs/pkgdown.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | $("#sidebar").stick_in_parent({ 3 | offset_top: $("#sidebar").offset().top 4 | }); 5 | $('body').scrollspy({ 6 | target: '#sidebar' 7 | }); 8 | $('[data-toggle="tooltip"]').tooltip(); 9 | 10 | /* Clipboard --------------------------*/ 11 | 12 | function changeTooltipMessage(element, msg) { 13 | var tooltipOriginalTitle=element.getAttribute('data-original-title'); 14 | element.setAttribute('data-original-title', msg); 15 | $(element).tooltip('show'); 16 | element.setAttribute('data-original-title', tooltipOriginalTitle); 17 | } 18 | 19 | if(ClipboardJS.isSupported()) { 20 | $(document).ready(function() { 21 | var copyButton = ""; 22 | 23 | $(".examples, div.sourceCode").addClass("hasCopyButton"); 24 | 25 | // Insert copy buttons: 26 | $(copyButton).prependTo(".hasCopyButton"); 27 | 28 | // Initialize tooltips: 29 | $('.btn-copy-ex').tooltip({container: 'body'}); 30 | 31 | // Initialize clipboard: 32 | var clipboardBtnCopies = new ClipboardJS('[data-clipboard-copy]', { 33 | text: function(trigger) { 34 | return trigger.parentNode.textContent; 35 | } 36 | }); 37 | 38 | clipboardBtnCopies.on('success', function(e) { 39 | changeTooltipMessage(e.trigger, 'Copied!'); 40 | e.clearSelection(); 41 | }); 42 | 43 | clipboardBtnCopies.on('error', function() { 44 | changeTooltipMessage(e.trigger,'Press Ctrl+C or Command+C to copy'); 45 | }); 46 | }); 47 | } 48 | }); 49 | 50 | $(window).scroll(function(){ 51 | if($(window).scrollTop() > 35) { 52 | $('.navbar').addClass("shrink"); 53 | $('.navbar-brand').addClass("shrink"); 54 | $('.navbar-label').addClass("shrink"); 55 | } else { 56 | $('.navbar').removeClass("shrink"); 57 | $('.navbar-brand').removeClass("shrink"); 58 | $('.navbar-label').removeClass("shrink"); 59 | } 60 | }); 61 | -------------------------------------------------------------------------------- /inst/CITATION: -------------------------------------------------------------------------------- 1 | bibentry( 2 | bibtype = "Manual", 3 | header = "To cite the SGP package in publications use:", 4 | title = "{SGP}: Student Growth Percentiles \\& Percentile Growth Trajectories.", 5 | author = c( 6 | person(given = c("Damian", "W."), family = "Betebenner"), 7 | person(given = c("Adam", "R."), family = "Van Iwaarden"), 8 | person(given = c("Benjamin"), family = "Domingue"), 9 | person(given = c("Yi"), family = "Shang") 10 | ), 11 | year = "2025", 12 | note = "R package version 2.2-1.9998", 13 | url = "https://sgp.io", 14 | textVersion = paste( 15 | "Damian W. Betebenner, Adam R. Van Iwaarden, Benjamin Domingue and Yi Shang (2025).", 16 | "SGP: Student Growth Percentiles & Percentile Growth Trajectories.", 17 | "(R package version 2.2-1.9998)", 18 | "URL: https://sgp.io" 19 | ) 20 | ) 21 | -------------------------------------------------------------------------------- /inst/doc/SGP.R: -------------------------------------------------------------------------------- 1 | ## ----include = FALSE------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 2 | library(SGP) 3 | library(SGPdata) 4 | 5 | is_html_output = function() { 6 | knitr::opts_knit$get("rmarkdown.pandoc.to")=="html" 7 | } 8 | 9 | knitr::opts_chunk$set( 10 | collapse=TRUE, 11 | comment="", 12 | prompt=TRUE, 13 | fig.dpi=96) 14 | 15 | if (is_html_output()) { 16 | options(width=1000) 17 | } 18 | 19 | ## ----eval=FALSE----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 20 | # install.packages("SGP") 21 | 22 | ## ----eval=FALSE----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 23 | # install.packages("devtools") ### If the devtool package isn't installed 24 | # devtools::install_github("CenterForAssessment/SGP") 25 | 26 | -------------------------------------------------------------------------------- /inst/doc/SGP_Data_Analysis.R: -------------------------------------------------------------------------------- 1 | ## ----include = FALSE------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 2 | library(SGP) 3 | library(SGPdata) 4 | 5 | is_html_output = function() { 6 | knitr::opts_knit$get("rmarkdown.pandoc.to")=="html" 7 | } 8 | 9 | knitr::opts_chunk$set( 10 | collapse=TRUE, 11 | comment="", 12 | prompt=TRUE, 13 | fig.dpi=96) 14 | 15 | if (is_html_output()) { 16 | options(width=1000) 17 | } 18 | 19 | ## ----eval=FALSE, prompt=FALSE--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 20 | # ##################################################################################### 21 | # ### 22 | # ### R Script for Demonstration SGP analyses 23 | # ### 24 | # ##################################################################################### 25 | # 26 | # ### Load SGP & SGPdata packages 27 | # 28 | # require(SGP) 29 | # require(SGPdata) 30 | # 31 | # 32 | # ### abcSGP 33 | # 34 | # Demonstration_SGP <- abcSGP( 35 | # sgp_object=sgpData_LONG, 36 | # data_supplementary=list(INSTRUCTOR_NUMBER=sgpData_INSTRUCTOR_NUMBER), 37 | # parallel.config=list(BACKEND="PARALLEL", WORKERS=list(PERCENTILES=4, BASELINE_PERCENTILES=4, PROJECTIONS=4, LAGGED_PROJECTIONS=4, SGP_SCALE_SCORE_TARGETS=4, SUMMARY=4, GA_PLOTS=4, SG_PLOTS=1))) 38 | # 39 | # 40 | # ### Save results 41 | # 42 | # save(Demonstration_SGP, file="Data/Demonstration_SGP.Rdata") 43 | 44 | -------------------------------------------------------------------------------- /man/SGP-class.Rd: -------------------------------------------------------------------------------- 1 | \name{SGP-class} 2 | \docType{class} 3 | \alias{SGP-class} 4 | \alias{is.SGP} 5 | \title{Class "SGP"} 6 | \description{The formal S4 class for SGP. This class stores the data object for use with the functions \code{\link{analyzeSGP}}, \code{\link{combineSGP}}, \code{\link{summarizeSGP}}, 7 | and \code{\link{visualizeSGP}}. The SGP class contains and organizes all the results associated with SGP analyses. \code{\link{is.SGP}} tests for membership for this class.} 8 | 9 | \section{Usage}{ 10 | Objects can be created by calls of the form \code{new("SGP", ...)}, but this is not encouraged. To instantiate a new instance of SGP class use the function \code{\link{prepareSGP}} instead. 11 | 12 | \code{is.SGP(x)} 13 | } 14 | 15 | \section{Slots}{ 16 | \describe{ 17 | \item{\code{Data}:}{A data.table including student-level data in a (long) format. For annual testing, each VALID_CASE, CONTENT_AREA, YEAR, ID combination represents a unique case in the data. For 18 | instances with multiple tests within a year, each VALID_CASE, CONTENT_AREA, YEAR, ID, WITHIN_YEAR combination represents a unique case in the data. See sgpData_LONG for an exemplar data set} 19 | \item{\code{Data_Supplementary}:}{A list (possibly NULL) providing additional data.tables containing student level multiple-membership lookup tables. 20 | For example, sgpData_INSTRUCTOR_NUMBER provides student teacher linkages and can be embedded in this slot using a list that contains it.} 21 | \item{\code{Names}:}{A data.frame with five columns: 'names.provided', 'names.sgp', 'names.type', 'names.info', 'names.output'. This data.frame is used as a lookup table to translate 22 | state specific variable names to SGP variable names as well as provide information for summarizeSGP on the types of summary tables to produce.} 23 | \item{\code{SGP}:}{A list including the output from \code{\link{analyzeSGP}}} 24 | \item{\code{Summary}:}{A list including the output from \code{\link{summarizeSGP}}} 25 | \item{\code{Version}:}{A list of meta-data including the version of the SGP package used to construct the SGP object and the date the object was created.} 26 | } 27 | } 28 | 29 | \details{ 30 | \describe{ 31 | \item{list.null:}{combines class \code{list} and class \code{NULL} 32 | } 33 | } 34 | } 35 | 36 | \author{Jonathan P. Weeks \email{weeksjp@gmail.com}, Adam Van Iwaarden \email{avaniwaarden@nciea.org} and Damian W. Betebenner \email{dbetebenner@nciea.org}} 37 | 38 | \seealso{ 39 | \code{\link{prepareSGP}} 40 | } 41 | \keyword{classes} 42 | -------------------------------------------------------------------------------- /man/SGPstateData.Rd: -------------------------------------------------------------------------------- 1 | \name{SGPstateData} 2 | \alias{SGPstateData} 3 | \docType{data} 4 | \title{State assessment program data from large scale state assessments for use with SGP package} 5 | \description{ 6 | An environment (an object of class environment) containing information on state assessment programs, organized by state. Currently the environment contains achievement level cutscores and 7 | labels for the state assessments, assessment name and abbreviation, growth cutscores and labels, information on vertical scaling, conditional standard errors of measurement (CSEMs), 8 | knots and boundaries, and state specific configurations currently being used for SGP analyses at the agency (state, district, national) level. The cutscores, in particular, are used to 9 | calculate growth-to-standard/projection values. States currently included in the data set are Arizona (AZ), Arkansas (AR), California (CA), Colorado (CO), Connecticut (CT), Georgia (GA), Hawaii (HI), 10 | Idaho (ID), Indiana (IN), Kansas (KS), Maine (ME), Massachusetts (MA), Minnesota (MN), Mississippi (MS), Missouri (MO), Nebraska (NE), Nevada (NV), New Hampshire (NH), New Mexico (NM), New Jersey (NJ), 11 | New York (NY), Oregon (OR), Rhode Island (RI), South Dakota (SD), Utah (UT), Vermont (VT), Virginia (VA), West Virginia (WV), Wisconsin (WI), Archdioces of Baltimore (AOB), 12 | Colorado English Language Assessment (CELA), Demonstration (DEMO), Albuquerque (ABQ), Australia NAPLAN (NAPLAN), Guatemala (GUA), Renaissance Learning Incorporated (RLI), 13 | Renaissance Learning Incorporated UK (RLI_UK), and New Haven (NEW_HAVEN). 14 | } 15 | 16 | \author{Damian W. Betebenner \email{dbetebenner@nciea.org} and Adam Van Iwaarden \email{avaniwaarden@nciea.org}} 17 | 18 | \source{State assessment data and technical assessment documentation} 19 | \keyword{datasets} 20 | -------------------------------------------------------------------------------- /man/capwords.Rd: -------------------------------------------------------------------------------- 1 | \name{capwords} 2 | \alias{capwords} 3 | \title{Function for converting all caps to mixed case. Useful in data cleaning.} 4 | \description{ 5 | The function capwords converts characters to mixed case character as intelligently as possible and leading/trailing spaces. 6 | } 7 | 8 | \usage{ 9 | capwords(x, 10 | special.words = c("ELA","I", "II", "III", "IV", "CCSD", "CUSD", "CUD", "USD", "PSD", 11 | "UD", "ESD", "DCYF", "EMH", "HS", "MS", "ES", "SES", "IEP", "ELL", "MAD", 12 | "PARCC", "SBAC", "SD", "SWD", "US", "SGP", "SIMEX", "SS", "SAT", "PSAT", 13 | "WIDA", "ACCESS", "WIDA-ACCESS")) 14 | } 15 | 16 | \arguments{ 17 | \item{x}{A character string to be converted to mixed case. 18 | } 19 | \item{special.words}{A character vector (see default above), specifying words to not convert to mixed case. 20 | } 21 | } 22 | 23 | \value{Returns a mixed case character string. 24 | } 25 | 26 | \author{Damian W. Betebenner \email{dbetebenner@nciea.org}} 27 | 28 | \examples{ 29 | capwords("TEST") ## Test 30 | capwords("TEST1 TEST2") ## Test1 Test2 31 | capwords("O'NEIL") ## O'Neil 32 | capwords("JOHN'S") ## John's 33 | 34 | ## Use sapply for converting character vectors 35 | 36 | test.vector <- paste("TEST", 1:10, sep="") 37 | sapply(test.vector, capwords) 38 | 39 | 40 | ## With factors, convert levels instead of the entire vector 41 | 42 | test.factor <- factor(paste("TEST", rep(letters[1:10], each=50))) 43 | levels(test.factor) <- sapply(levels(test.factor), capwords) 44 | levels(test.factor) 45 | } 46 | 47 | \keyword{documentation} 48 | -------------------------------------------------------------------------------- /man/courseProgressionSGP.Rd: -------------------------------------------------------------------------------- 1 | \name{courseProgressionSGP} 2 | \alias{courseProgressionSGP} 3 | \title{Identify potential course progressions for SGP analyses} 4 | \description{ 5 | Utility function used to analyze supplied long data or an existing SGP class object to identify potential course progressions suitable for analysis with \code{\link{analyzeSGP}}, \code{\link{studentGrowthPercentiles}}, etc. See examples for more information. 6 | } 7 | 8 | \usage{ 9 | courseProgressionSGP( 10 | sgp_object, 11 | lag.direction=c("FORWARD", "BACKWARD"), 12 | year) 13 | } 14 | 15 | \arguments{ 16 | \item{sgp_object}{Either a panel data set in long form or an object of class SGP. See embedded \code{\link[SGPdata]{sgpData_LONG}} data set for an exemplar. 17 | } 18 | \item{lag.direction}{Character string indicating whether the progressions should be produced prospectively or retrospectively. 19 | } 20 | \item{year}{Character indicating the value of YEAR that is the focus of analysis. 21 | } 22 | } 23 | 24 | \value{Function returns a nested \code{list} class object. The final node of each nested list is a \code{data.table} which summarizes the number of students with a particular GRADE by CONTENT_AREA by YEAR course progression 25 | } 26 | 27 | \author{Adam Van Iwaarden \email{avaniwaarden@nciea.org} and Damian W. Betebenner \email{dbetebenner@nciea.org}} 28 | 29 | \seealso{\code{\link[SGPdata]{sgpData_LONG}}} 30 | 31 | \examples{ 32 | \dontrun{ 33 | ## Run courseProgressionSGP on the subset of the long data that contains 34 | ## ONLY mathematics related records (would realistically also contain EOCT math courses) 35 | Math_Data <- subset(SGPdata::sgpData_LONG, CONTENT_AREA == "MATHEMATICS") 36 | Math_Progressions <- courseProgressionSGP(Math_Data, lag.direction= "BACKWARD", year="2015_2016") 37 | 38 | ## Examine results for Adcademic Year 2015-2016, 5th grade Mathematics. 39 | Math_Progressions[['BACKWARD']][['2015_2016']][['MATHEMATICS.05']] 40 | Math_Progressions[['BACKWARD']][['2015_2016']][['MATHEMATICS.05']][COUNT>100] 41 | } 42 | } 43 | 44 | \keyword{documentation} 45 | -------------------------------------------------------------------------------- /man/createKnotsBoundaries.Rd: -------------------------------------------------------------------------------- 1 | \name{createKnotsBoundaries} 2 | \alias{createKnotsBoundaries} 3 | \title{Function to create Knots and Boundaries from supplied data in LONG format.} 4 | \description{ 5 | The function createKnotsBoundaries creates Knots, Boundaries and Loss/Hoss scores for subsequent use and embedding in SGPstateData. Function can be called separately but is usually called as part of 6 | \code{\link{prepareSGP}}. See examples below. 7 | } 8 | 9 | \usage{ 10 | createKnotsBoundaries(tmp.data, 11 | knot.cut.percentiles=c(0.2,0.4,0.6,0.8)) 12 | } 13 | 14 | \arguments{ 15 | \item{tmp.data}{Data supplied to function in LONG format. See sgpData_LONG for an exemplar. tmp.data must contain, at least, variables 'VALID_CASE', 'CONTENT_AREA', 'SCALE_SCORE', 'GRADE'. 16 | } 17 | \item{knot.cut.percentiles}{A numeric vector of quantiles of 'SCALE_SCORE' to be used as the cut points. Default is to use the 20th, 40th, 60th, and 80th percentiles (i.e., c(0.2,0.4,0.6,0.8)). 18 | } 19 | } 20 | 21 | \value{Returns a list containing Knots, Boundaries and Loss/Hoss scores. 22 | } 23 | 24 | \author{Damian W. Betebenner \email{dbetebenner@nciea.org}} 25 | 26 | \examples{ 27 | \dontrun{ 28 | ### Run on supplied long data 29 | 30 | DEMO_Knots_Boundaries <- createKnotsBoundaries(sgpData_LONG) 31 | 32 | ### Run as part of prepareSGP 33 | 34 | ### First NULL out knots and boundaries embedded in SGPstateData 35 | 36 | SGPstateData[["DEMO"]][["Achievement"]][["Knots_Boundaries"]] <- NULL 37 | Demonstration_SGP <- prepareSGP(sgpData_LONG) 38 | } 39 | } 40 | 41 | \keyword{documentation} 42 | -------------------------------------------------------------------------------- /man/getStateAbbreviation.Rd: -------------------------------------------------------------------------------- 1 | \name{getStateAbbreviation} 2 | \alias{getStateAbbreviation} 3 | \title{Function for converting state/organization abbreviations to long form and back.} 4 | \description{ 5 | The function getStateAbbreviation converts state/organization abbreviations to their long form and back. For example ID gets converted to Idaho. 6 | } 7 | 8 | \usage{ 9 | getStateAbbreviation( 10 | supplied.name, 11 | SGPfunction=NULL, 12 | type="ABBREVIATION") 13 | } 14 | 15 | \arguments{ 16 | \item{supplied.name}{A character string state/organization abbreviation or long form name. 17 | } 18 | \item{SGPfunction}{SGP package function from which \code{getStateAbbreviation} is being called. Defaults to NULL. 19 | } 20 | \item{type}{Either \code{Abbreviation} or \code{Long} indicating whether the desired output is an Abbreviation (long form name is supplied) or the long form name (abbreviation is supplied). 21 | The default is \code{Abbreviation}. 22 | } 23 | } 24 | 25 | \value{Returns a character string. 26 | } 27 | 28 | \author{Damian W. Betebenner \email{dbetebenner@nciea.org}} 29 | 30 | \examples{ 31 | getStateAbbreviation("IDAHO") ## ID 32 | getStateAbbreviation("ID", type="Long") ## Idaho 33 | } 34 | 35 | \keyword{documentation} 36 | -------------------------------------------------------------------------------- /man/gofPrint.Rd: -------------------------------------------------------------------------------- 1 | \name{gofPrint} 2 | \alias{gofPrint} 3 | \title{Function to produce Goodness of Fit plots from a SGP object.} 4 | \description{ 5 | The function gofPrint is used to output Goodness of Fit plots from R grobs stored in a SGP object. 6 | } 7 | 8 | \usage{ 9 | gofPrint( 10 | sgp_object, 11 | years = NULL, 12 | content_areas = NULL, 13 | grades = NULL, 14 | sgp_types = NULL, 15 | norm_group = NULL, 16 | output_format = c("PDF", "SVG", "DECILE_TABLES"), 17 | output_path = "Goodness_of_Fit", 18 | ...) 19 | } 20 | 21 | \arguments{ 22 | \item{sgp_object}{SGP object resulting from SGP analyses 23 | } 24 | \item{years}{The academic year(s) for which fit plots should be produced 25 | } 26 | \item{content_areas}{The content area(s) for which fit plots should be produced 27 | } 28 | \item{grades}{The grade(s) for which fit plots should be produced 29 | } 30 | \item{sgp_types}{The SGP type for which fit plots should be produdced (e.g., 31 | cohort or baseline referenced, SIMEX adjusted, etc.). 32 | } 33 | \item{norm_group}{The specific norm group (cohort or course progression) for 34 | which fit plots should be produced 35 | } 36 | \item{output_format}{The graphical file type of plots that should be produced 37 | and/or the decile tables as a .Rdata file. Defaults are PDF, SVG and decile tables. 38 | PNG file type is also available. 39 | } 40 | \item{output_path}{Directory path for plot/table output 41 | } 42 | \item{...}{Additional arguments to pass to \code{svglite} 43 | } 44 | } 45 | 46 | \value{Returns a graphical output of the fit plot(s) requested based on the arguments provided. Can also save the decile table data in Rdata format. 47 | } 48 | 49 | \author{Adam Van Iwaarden \email{avaniwaarden@nciea.org} and Damian W. Betebenner \email{dbetebenner@nciea.org}} 50 | 51 | \examples{ 52 | \dontrun{ 53 | gofPrint(Demonstration_SGP) 54 | } 55 | } 56 | 57 | \keyword{documentation} 58 | -------------------------------------------------------------------------------- /man/gofSGP.Rd: -------------------------------------------------------------------------------- 1 | \name{gofSGP} 2 | \alias{gofSGP} 3 | \title{Function for producing goodness of fit plots using existing SGP object} 4 | \description{ 5 | gofSGP creates goodness-of-fit plots in either PDF or PNG for showing SGP distribution by prior achievement level and prior scale score decile. These plots expand upon the plots currently produced 6 | with the \code{\link{studentGrowthPercentiles}} function. 7 | } 8 | 9 | \usage{ 10 | gofSGP( 11 | sgp_object, 12 | state=NULL, 13 | years=NULL, 14 | content_areas=NULL, 15 | content_areas_prior=NULL, 16 | grades=NULL, 17 | ceiling.floor=TRUE, 18 | use.sgp="SGP", 19 | output.format="PDF", 20 | color.scale="reds.and.blues") 21 | } 22 | 23 | \arguments{ 24 | \item{sgp_object}{The SGP object from which the goodness-of-fit data will be used. 25 | } 26 | \item{state}{The 'state' for the sgp_object. Derive from sgp_object name if not explicitly supplied. 27 | } 28 | \item{years}{The years that goodness-of-fit plots are requested. Default is to use all years available. 29 | } 30 | \item{content_areas}{The content area(s) that goodness-of-fit plots are requested. Default is to use all content areas available. 31 | } 32 | \item{content_areas_prior}{The content area(s) of the prior year which growth by achievement level is being produced that goodness-of-fit plots are requested. 33 | Default is to use all content areas available. 34 | } 35 | \item{grades}{The grade(s) that goodness-of-fit plots are requested. Default is to use all grade available. 36 | } 37 | \item{ceiling.floor}{Boolean variable to explictly control display of ceiling/floor portion of goodness of fit plot. 38 | } 39 | \item{use.sgp}{Character vectors (defaults to 'SGP') indicating what student growth percentile variable to calculate goodness-of-fit plots for. 40 | } 41 | \item{output.format}{Character vectors (defaults to 'PDF') indicating what driver to use to output results. Options currently include 'PDF', 'PNG' and 'SVG'. 'SVG' is currently experimental. 42 | } 43 | \item{color.scale}{Character vectors (defaults to 'red') indicating what color palette to use for creating percentile distribution table. 44 | } 45 | } 46 | 47 | \value{Returns output ('PDF' , 'PNG' or 'SVG') associated with goodness-of-fit analyses. 48 | } 49 | 50 | \author{Damian W. Betebenner \email{dbetebenner@nciea.org}} 51 | 52 | \seealso{\code{\link{studentGrowthPercentiles}}} 53 | 54 | \examples{ 55 | \dontrun{ 56 | Demonstration_SGP <- abcSGP(sgpData_LONG) 57 | gofSGP(Demonstration_SGP) 58 | } 59 | } 60 | 61 | \keyword{documentation} 62 | -------------------------------------------------------------------------------- /man/prepareSGP.Rd: -------------------------------------------------------------------------------- 1 | \name{prepareSGP} 2 | \alias{prepareSGP} 3 | \title{Prepare data for SGP analyses} 4 | \description{ 5 | Utility function/exemplar used to embed supplied long data into a list object as a keyed data.table. NOTE: This function also serves the purposes of running many checks on the SGP object you 6 | construct to make sure it is up to date and in the best shape possible. If you have an older object that you wish to make sure is up to date with the latest version of the SGP package, running 7 | \code{\link{prepareSGP}} on an object is never bad thing to do. See examples for more information. 8 | } 9 | 10 | \usage{ 11 | prepareSGP(data, 12 | data_supplementary=NULL, 13 | state=NULL, 14 | var.names=NULL, 15 | create.additional.variables=TRUE, 16 | fix.duplicates=NULL, 17 | create.achievement.level=TRUE) 18 | } 19 | 20 | \arguments{ 21 | \item{data}{A panel data set in long form or an object of class SGP. See embedded \code{\link[SGPdata]{sgpData_LONG}} data set for an exemplar. 22 | } 23 | \item{data_supplementary}{Supplementary data (e.g., student teacher lookup tables) to be embedded in SGP object in slot @Data_Supplementary. Data must be embedded in a list. Default is no data supplied. 24 | } 25 | \item{state}{A two letter acronym indicating the state associated with the data. If not supplied, the function will try to infer what the state is from the data object name supplied. 26 | } 27 | \item{var.names}{A list or a data.frame that includes all required columns that do not match the SGP conventions, as well as all secondary columns needed 28 | for summarizing and reporting. 29 | } 30 | \item{create.additional.variables}{Boolean argument indicating whether prepareSGP should create additional variables often used in analyses. For example, the function can create a variable 31 | \code{HIGH_NEED_STATUS} identifying the top and bottom quartile of students in each school by year by content area by grade grouping. 32 | } 33 | \item{fix.duplicates}{Argument to control how \code{prepareSGP} deals with duplicate records based upon the key of VALID_CASE, CONTENT_AREA, YEAR, and ID. 34 | The function currently warns of duplicate records and doesn't modify data. If set to TRUE, \code{prepareSGP} tries to 35 | fix the duplicate individual records by adding a '_DUP_***' suffix to the duplicate ID in order to create unique records based upon the key. 36 | } 37 | \item{create.achievement.level}{Boolean argument indicating whether prepareSGP should create the ACHIEVEMENT_LEVEL variable if it is missing. Defaults to TRUE.} 38 | } 39 | 40 | \value{Function returns an object of class \code{SGP}. The long data is 41 | in the \code{data} slot. 42 | } 43 | 44 | \author{Adam Van Iwaarden \email{avaniwaarden@nciea.org}, Damian W. Betebenner \email{dbetebenner@nciea.org}, and Ben Domingue \email{ben.domingue@gmail.com}} 45 | 46 | \seealso{\code{\link[SGPdata]{sgpData_LONG}}} 47 | 48 | \examples{ 49 | \dontrun{ 50 | ## prepareSGP is Step 1 of 5 of abcSGP 51 | Demonstration_SGP <- prepareSGP(sgpData_LONG) 52 | 53 | ## Running prepareSGP on an already create SGP object as part of a annual update 54 | 55 | Demonstration_SGP <- prepareSGP(Demonstration_SGP) 56 | 57 | 58 | ## Running prepareSGP on a long data set without creating addition variables 59 | 60 | Demonstration_SGP <- prepareSGP(sgpData_LONG, create.additional.variables=FALSE) 61 | } 62 | } 63 | 64 | \keyword{documentation} 65 | -------------------------------------------------------------------------------- /man/setNamesSGP.Rd: -------------------------------------------------------------------------------- 1 | \name{setNamesSGP} 2 | \alias{setNamesSGP} 3 | \title{Function for renaming data (typically from \code{\link{outputSGP}}) from 4 | a state/organization naming conventions to those used in the SGP package} 5 | \description{ 6 | setNamesSGP renames a dataset (without copying or returning the data). 7 | } 8 | 9 | \usage{ 10 | setNamesSGP( 11 | data, 12 | state=NULL) 13 | } 14 | 15 | \arguments{ 16 | \item{data}{The dataset to be renamed. For example longitudinal data exported 17 | from \code{\link{outputSGP}} that uses a state's naming conventions. 18 | } 19 | \item{state}{The 'state' for the \code{data} Derive from \code{data} name if not explicitly supplied. 20 | } 21 | } 22 | 23 | \value{NULL. Simply renames the data. Note that the \code{state} must be included 24 | in the \code{SGPstateData} and have a \code{Variable_Name_Lookup} entry to work. 25 | } 26 | 27 | \author{Adam R. Van Iwaarden \email{avaniwaarden@nciea.org} } 28 | 29 | \seealso{\code{\link{outputSGP}}} 30 | 31 | \examples{ 32 | \dontrun{ 33 | load("Data/Demonstration_SGP_LONG_Data.Rdata") 34 | setNamesSGP(Demonstration_SGP_LONG_Data) 35 | } 36 | } 37 | 38 | \keyword{documentation} 39 | -------------------------------------------------------------------------------- /man/splineMatrix-class.Rd: -------------------------------------------------------------------------------- 1 | \name{splineMatrix-class} 2 | \docType{class} 3 | \alias{splineMatrix-class} 4 | \alias{is.splineMatrix} 5 | \alias{as.splineMatrix} 6 | \title{Class "splineMatrix"} 7 | \description{The formal S4 class for coefficient matrices produced from the \code{\link{studentGrowthPercentiles}} function. This class stores the B-spline knots and boundaries used by the coefficient matrix object for the production of student growth percentiles and projections.} 8 | 9 | \section{Objects from the Class}{ 10 | Objects can be created by calls of the form \code{new("splineMatrix", ...)}, but this is not encouraged. Previously produced coefficient matrices MUST be bound to the IDENTICAL knots and boundaries used to create them. Use the function \code{\link{studentGrowthPercentiles}} instead. 11 | } 12 | 13 | \section{Slots}{ 14 | \describe{ 15 | \item{\code{.Data}:}{A coefficient matrix derived from \code{\link{studentGrowthPercentiles}}.} 16 | \item{\code{Knots}:}{A list(s) of numeric values used as the \code{knots} to generate the B-spline basis matrix in \code{\link{studentGrowthPercentiles}}.} 17 | \item{\code{Boundaries}:}{A list(s) of numeric values used as the \code{Boundary.knots}to generate the B-spline basis matrix in \code{\link{studentGrowthPercentiles}}.} 18 | \item{\code{Content_Areas}:}{A list of time dependent content area names included in the data used to produce the coefficient matrix.} 19 | \item{\code{Grade_Progression}:}{A list of the time dependent grades included in the data used to produce matrices.} 20 | \item{\code{Time}:}{A list of the Times (e.g., years) measurements occurred included in the data used to produce matrices.} 21 | \item{\code{Time_Lags}:}{A list of the time lags/differences between Time (e.g., years) included in the data used to produce matrices.} 22 | \item{\code{Version}:}{A list including the version of the SGP package used to construct the splineMatrix object and the date the object was created.} 23 | } 24 | } 25 | 26 | \details{ 27 | \describe{ 28 | \item{splineMatrix:}{This class contains the S3 \code{matrix} class, inheriting its methods. The slot \code{Knots} should be one or more lists of numeric vector(s) used in the internal call 29 | to \code{bs}, which generates a B-spline basis matrix from student scores. There are typically with 4 values for the knots. Similarly, \code{Boundaries} are used in \code{bs} for the 30 | \code{Boundary.knots} argument. This is always two values which are at or slightly beyond the lowest and highest observed student scores. \code{Content_Areas} and 31 | \code{Grade_Progression} provide information about the data (sub)set used to produce the matrix. 32 | } 33 | } 34 | } 35 | 36 | 37 | \author{Adam Van Iwaarden \email{avaniwaarden@nciea.org}, Ben Domingue \email{ben.domingue@gmail.com} and Damian W. Betebenner \email{dbetebenner@nciea.org}} 38 | 39 | \seealso{ 40 | \code{\link{studentGrowthPercentiles}} 41 | } 42 | \keyword{classes} 43 | -------------------------------------------------------------------------------- /man/studentGrowthPlot.Rd: -------------------------------------------------------------------------------- 1 | \name{studentGrowthPlot} 2 | \alias{studentGrowthPlot} 3 | \title{Create a student growth and achievement chart} 4 | \description{Function used to produce individual student growth and achievement chart (an achievement time lines indicating student growth) based upon output from student growth percentile 5 | and student growth projection analyses. Function is integrated with \code{SGPstateData} to accommodate state specific scales and nomenclature including performance 6 | level names. See Betebenner (2012) for discussion} 7 | \usage{ 8 | studentGrowthPlot(Scale_Scores, 9 | Plotting_Scale_Scores, 10 | Achievement_Levels, 11 | SGP, 12 | SGP_Levels, 13 | Grades, 14 | Content_Areas, 15 | Cuts, 16 | Plotting_Cuts, 17 | SGP_Targets, 18 | SGP_Scale_Score_Targets, 19 | Plotting_SGP_Scale_Score_Targets, 20 | Cutscores, 21 | Years, 22 | Report_Parameters) 23 | } 24 | \arguments{ 25 | \item{Scale_Scores}{ 26 | A vector of historical scale scores. 27 | } 28 | \item{Plotting_Scale_Scores}{ 29 | A vector of scale scores used as the vertical coordinates for plotting. If supplied, \code{Scale_Scores} are used for text and Plotting_Scale_Scores 30 | are used for the actual coordinates. 31 | } 32 | \item{Achievement_Levels}{ 33 | A vector of historical performance levels. 34 | } 35 | \item{SGP}{ 36 | A vector of historical student growth percentiles. 37 | } 38 | \item{SGP_Levels}{ 39 | A vector of historical growth (SGP) levels (e.g., low, typical, high). 40 | } 41 | \item{Grades}{ 42 | A vector of historical grades student was tested in. 43 | } 44 | \item{Content_Areas}{ 45 | A vector of historical content areas student was tested in. 46 | } 47 | \item{Cuts}{ 48 | A list of cuts scores for NY1, NY2, and NY3. 49 | } 50 | \item{Plotting_Cuts}{ 51 | A list of plotting cuts scores for NY1, NY2, and NY3. Plotting cuts are identical to Cuts for states with a vertical scale and are transformed for non-vertical scale states. 52 | } 53 | \item{SGP_Targets}{ 54 | A list of CUKU, CUKU_Current, MUSU, MUSU_Current targets. 55 | } 56 | \item{SGP_Scale_Score_Targets}{ 57 | A list of CUKU, CUKU_Current, MUSU, MUSU_Current scale score targets. 58 | } 59 | \item{Plotting_SGP_Scale_Score_Targets}{ 60 | A list of CUKU, CUKU_Current, MUSU, MUSU_Current scale score targets for plotting that are transformed when no vertical scale exists. 61 | } 62 | \item{Cutscores}{ 63 | A data.frame of long formatted achievement level cutscores. 64 | } 65 | \item{Years}{ 66 | A vector of years corresponding to supplied scale scores. 67 | } 68 | \item{Report_Parameters}{ 69 | A list containing arguments: \code{Current_Year}, \code{Content_Area}, \code{State}, \code{Denote_Content_Area}, \code{SGP_Targets}, and \code{Configuration}. 70 | } 71 | } 72 | \details{Function currently used as part of SGP package to produce student growth charts for states. Function is usually called from the higher level function \code{\link{visualizeSGP}} which 73 | allows for the creation of a student growth plot catalog for each school with student reports organized by grade and student name.} 74 | \value{Returns a student growth plot graphical object that is usually exported in either PDF or PNG format.} 75 | \author{Damian W. Betebenner \email{dbetebenner@nciea.org}} 76 | \references{ 77 | Betebenner, D. W. (2012). Growth, standards, and accountability. In G. J. Cizek, 78 | \emph{Setting Performance Standards: Foundations, Methods & Innovations. 2nd Edition} (pp. 439-450). 79 | New York: Routledge. 80 | } 81 | -------------------------------------------------------------------------------- /man/testSGP.Rd: -------------------------------------------------------------------------------- 1 | \name{testSGP} 2 | \alias{testSGP} 3 | \title{Test SGP Package functions} 4 | \description{ 5 | testSGP runs large scale tests of the SGP package to test for consistent performance across releases. 6 | } 7 | 8 | \usage{ 9 | testSGP(TEST_NUMBER, 10 | save.results=TRUE, 11 | test.option=list(), 12 | memory.profile=FALSE, 13 | stop.fail=TRUE) 14 | } 15 | 16 | \arguments{ 17 | \item{TEST_NUMBER}{An integer indicating the test to be run. Type 'testSGP()' to see list and description of available tests. 18 | } 19 | \item{save.results}{A Boolean variable, defaulting to FALSE, indicating whether the results of the analysis is saved to the working directory. 20 | } 21 | \item{test.option}{A character string (defaults to NULL) supplying a test option to the given test specified by TEST_NUMBER. Argument is test specific. See source code for testSGP for possible 22 | arguments.} 23 | \item{memory.profile}{A Boolean variable indicating whether to use memory profiling via \code{Rprof}. Experimental. Defaults to FALSE. 24 | } 25 | \item{stop.fail}{A Boolean variable indicating whether to stop the function if a test fails Defaults to TRUE. 26 | } 27 | } 28 | 29 | \value{Returns output associated with functions being run. 30 | } 31 | 32 | \author{Damian W. Betebenner \email{dbetebenner@nciea.org} and Adam Van Iwaarden \email{avaniwaarden@nciea.org}} 33 | 34 | \seealso{\code{\link{abcSGP}}} 35 | 36 | \examples{ 37 | \dontrun{ 38 | ## testSGP(0): Test of studentGrowthPercentiles, studentGrowthProjections, and sgpData 39 | testSGP(0) 40 | 41 | ## testSGP(1) & testSGP('1b') runs abcSGP for all years in sgpData_LONG with/without sqliteSGP 42 | testSGP(1) 43 | testSGP('1b') 44 | 45 | ## testSGP(2): Various tests of updateSGP functionality. 46 | ## testSGP('2a'): Test of updateSGP performing SGP analyses in two steps: 47 | ## Create what_sgp_object: 2010-2011 to 2013-2014 then add with_sgp_data_LONG 2014-2015 using 48 | ## overwrite.existing.data=FALSE and sgp.use.my.coefficient.matrices=FALSE. 49 | ## testSGP('2b'): Test of updateSGP performing SGP analyses in two steps: 50 | ## Create what_sgp_object: 2010-2011 to 2013-2014 then add with_sgp_data_LONG 2014-2015 using 51 | ## overwrite.existing.data=TRUE and sgp.use.my.coefficient.matrices=FALSE. 52 | ## testSGP('2c'): Test of updateSGP performing SGP analyses in two steps: 53 | ## Create what_sgp_object: 2010-2011 to 2013-2014 then add with_sgp_data_LONG 2014-2015 using 54 | ## overwrite.existing.data=TRUE and sgp.use.my.coefficient.matrices=TRUE. 55 | ## testSGP('2d'): Test of updateSGP performing SGP analyses in two steps: 56 | ## Create what_sgp_object: 2010-2011 to 2013-2014 then add with_sgp_data_LONG 2014-2015 using 57 | ## overwrite.existing.data=FALSE and sgp.use.my.coefficient.matrices=TRUE. 58 | testSGP('2a') 59 | testSGP('2b') 60 | testSGP('2c') 61 | testSGP('2d') 62 | 63 | ## testSGP(3) runs abcSGP on grade progressions including End of Course Tests in Mathematics 64 | ## (Algebra I and Algebra II) and Reading (Grade 9 Literature and American Literature) 65 | testSGP(3) 66 | 67 | ## testSGP(4) runs prepareSGP and analyzeSGP with simex adjustment for measurement error 68 | testSGP(4) 69 | 70 | ## testSGP(5) runs abcSGP assuming at test transition in the most recent year. NOTE YET COMPLETED 71 | testSGP(5) 72 | 73 | ## testSGP(6) runs a basic baseline SGP analysis including the construction of baseline matrices. 74 | testSGP(6) 75 | } 76 | } 77 | 78 | \keyword{documentation} 79 | -------------------------------------------------------------------------------- /vignettes/releases/SGP-1.4-0.0.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "SGP 1.4-0.0" 3 | date: "January 10th, 2016" 4 | --- 5 | 6 | ```{r include = FALSE} 7 | library(SGP) 8 | 9 | is_html_output = function() { 10 | knitr::opts_knit$get("rmarkdown.pandoc.to")=="html" 11 | } 12 | 13 | knitr::opts_chunk$set( 14 | collapse=TRUE, 15 | comment="", 16 | prompt=TRUE, 17 | fig.dpi=96) 18 | 19 | if (is_html_output()) { 20 | options(width=1000) 21 | } 22 | ``` 23 | 24 | 25 | This is the 1.4 release of the SGP package posted to CRAN. This is the first release to be officially [tagged on GitHub](https://github.com/CenterForAssessment/SGP/releases/tag/636943f). Download from GitHub via: 26 | 27 | ```{r eval=FALSE} 28 | devtools::install_github("CenterForAssessment/SGP", ref="636943f") 29 | ``` 30 | 31 | To see all the changes in this release check out the [change log](https://sgp.io/news/index.html#sgp-1-4-0-0). 32 | 33 | 34 | Feel free to drop me a line with any comments, feature requests, or ideas. And give us a shout-out Tweet using the Twitter button in the upper right! 35 | -------------------------------------------------------------------------------- /vignettes/releases/SGP-1.5-0.0.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "SGP 1.5-0.0" 3 | date: "March 5th, 2016" 4 | --- 5 | 6 | ```{r include = FALSE} 7 | library(SGP) 8 | 9 | is_html_output = function() { 10 | knitr::opts_knit$get("rmarkdown.pandoc.to")=="html" 11 | } 12 | 13 | knitr::opts_chunk$set( 14 | collapse=TRUE, 15 | comment="", 16 | prompt=TRUE, 17 | fig.dpi=96) 18 | 19 | if (is_html_output()) { 20 | options(width=1000) 21 | } 22 | ``` 23 | 24 | 25 | This is the 1.5 release of the SGP package posted to CRAN. This is the second release to be officially [tagged on GitHub](https://github.com/CenterForAssessment/SGP/releases/tag/9df303e). Download from GitHub via: 26 | 27 | ```{r eval=FALSE} 28 | devtools::install_github("CenterForAssessment/SGP", ref="9df303e") 29 | ``` 30 | 31 | To see all the changes in this release check out the [change log](https://sgp.io/news/index.html#sgp-1-5-0-0). 32 | 33 | 34 | Feel free to drop me a line with any comments, feature requests, or ideas. And give us a shout-out Tweet using the Twitter button in the upper right! 35 | -------------------------------------------------------------------------------- /vignettes/releases/SGP-1.6-0.0.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "SGP 1.6-0.0" 3 | date: "January 1st, 2017" 4 | --- 5 | 6 | ```{r include = FALSE} 7 | library(SGP) 8 | 9 | is_html_output = function() { 10 | knitr::opts_knit$get("rmarkdown.pandoc.to")=="html" 11 | } 12 | 13 | knitr::opts_chunk$set( 14 | collapse=TRUE, 15 | comment="", 16 | prompt=TRUE, 17 | fig.dpi=96) 18 | 19 | if (is_html_output()) { 20 | options(width=1000) 21 | } 22 | ``` 23 | 24 | 25 | This is the 1.6 release of the SGP package posted to CRAN. This is the third release to be officially [tagged on GitHub](https://github.com/CenterForAssessment/SGP/releases/tag/87fd67a). Download from GitHub via: 26 | 27 | ```{r eval=FALSE} 28 | devtools::install_github("CenterForAssessment/SGP", ref="87fd67a") 29 | ``` 30 | 31 | To see all the changes in this release check out the [change log](https://sgp.io/news/index.html#sgp-1-6-0-0). 32 | 33 | 34 | Feel free to drop me a line with any comments, feature requests, or ideas. And give us a shout-out Tweet using the Twitter button in the upper right! 35 | -------------------------------------------------------------------------------- /vignettes/releases/SGP-1.7-0.0.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "SGP 1.7-0.0" 3 | date: "April 10th, 2017" 4 | --- 5 | 6 | ```{r include = FALSE} 7 | library(SGP) 8 | 9 | is_html_output = function() { 10 | knitr::opts_knit$get("rmarkdown.pandoc.to")=="html" 11 | } 12 | 13 | knitr::opts_chunk$set( 14 | collapse=TRUE, 15 | comment="", 16 | prompt=TRUE, 17 | fig.dpi=96) 18 | 19 | if (is_html_output()) { 20 | options(width=1000) 21 | } 22 | ``` 23 | 24 | 25 | This is the 1.7 release of the SGP package posted to CRAN. This [GitHub tagged release](https://github.com/CenterForAssessment/SGP/releases/tag/ceec338) 26 | can be downloaded via: 27 | 28 | ```{r eval=FALSE} 29 | devtools::install_github("CenterForAssessment/SGP", ref="ceec338") 30 | ``` 31 | 32 | To see all the changes in this release check out the [change log](https://sgp.io/news/index.html#sgp-1-7-0-0). 33 | 34 | 35 | Feel free to drop me a line with any comments, feature requests, or ideas. And give us a shout-out Tweet using the Twitter button in the upper right! 36 | -------------------------------------------------------------------------------- /vignettes/releases/SGP-1.8-0.0.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "SGP 1.8-0.0" 3 | date: "April 6th, 2018" 4 | --- 5 | 6 | ```{r include = FALSE} 7 | library(SGP) 8 | 9 | is_html_output = function() { 10 | knitr::opts_knit$get("rmarkdown.pandoc.to")=="html" 11 | } 12 | 13 | knitr::opts_chunk$set( 14 | collapse=TRUE, 15 | comment="", 16 | prompt=TRUE, 17 | fig.dpi=96) 18 | 19 | if (is_html_output()) { 20 | options(width=1000) 21 | } 22 | ``` 23 | 24 | 25 | This is the 1.8 release of the SGP package posted to CRAN. This [GitHub tagged release](https://github.com/CenterForAssessment/SGP/releases/tag/ea0d75e) 26 | can be downloaded via: 27 | 28 | ```{r eval=FALSE} 29 | devtools::install_github("CenterForAssessment/SGP", ref="ea0d75e") 30 | ``` 31 | 32 | To see all the changes in this release check out the [change log](https://sgp.io/news/index.html#sgp-1-8-0-0). 33 | 34 | 35 | Feel free to drop me a line with any comments, feature requests, or ideas. And give us a shout-out Tweet using the Twitter button in the upper right! 36 | -------------------------------------------------------------------------------- /vignettes/releases/SGP-1.9-0.0.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "SGP 1.9-0.0" 3 | date: "February 20th, 2019" 4 | --- 5 | 6 | ```{r include = FALSE} 7 | library(SGP) 8 | 9 | is_html_output = function() { 10 | knitr::opts_knit$get("rmarkdown.pandoc.to")=="html" 11 | } 12 | 13 | knitr::opts_chunk$set( 14 | collapse=TRUE, 15 | comment="", 16 | prompt=TRUE, 17 | fig.dpi=96) 18 | 19 | if (is_html_output()) { 20 | options(width=1000) 21 | } 22 | ``` 23 | 24 | 25 | This is the 1.9 release of the SGP package posted to CRAN. This [GitHub tagged release](https://github.com/CenterForAssessment/SGP/releases/tag/8906c2a) 26 | can be downloaded via: 27 | 28 | ```{r eval=FALSE} 29 | devtools::install_github("CenterForAssessment/SGP", ref="8906c2a") 30 | ``` 31 | 32 | To see all the changes in this release check out the [change log](https://sgp.io/news/index.html#sgp-1-9-0-0). 33 | 34 | 35 | Feel free to drop me a line with any comments, feature requests, or ideas. And give us a shout-out Tweet using the Twitter button in the upper right! 36 | -------------------------------------------------------------------------------- /vignettes/releases/SGP-1.9-5.0.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "SGP 1.9-5.0" 3 | date: "February 2nd, 2020" 4 | --- 5 | 6 | ```{r include = FALSE} 7 | library(SGP) 8 | 9 | is_html_output = function() { 10 | knitr::opts_knit$get("rmarkdown.pandoc.to")=="html" 11 | } 12 | 13 | knitr::opts_chunk$set( 14 | collapse=TRUE, 15 | comment="", 16 | prompt=TRUE, 17 | fig.dpi=96) 18 | 19 | if (is_html_output()) { 20 | options(width=1000) 21 | } 22 | ``` 23 | 24 | 25 | This is the 1.9-5.0 release of the SGP package posted to CRAN. This [GitHub tagged release](https://github.com/CenterForAssessment/SGP/releases/tag/619c5e4) 26 | can be downloaded via: 27 | 28 | ```{r eval=FALSE} 29 | devtools::install_github("CenterForAssessment/SGP", ref="619c5e4") 30 | ``` 31 | 32 | To see all the changes in this release check out the [change log](https://sgp.io/news/index.html#sgp-1-9-5-0). 33 | 34 | 35 | Feel free to drop me a line with any comments, feature requests, or ideas. And give us a shout-out Tweet using the Twitter button in the upper right! 36 | -------------------------------------------------------------------------------- /vignettes/releases/SGP-2.0-0.0.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "SGP 2.0-0.0" 3 | date: "May 27th, 2022" 4 | --- 5 | 6 | ```{r include = FALSE} 7 | library(SGP) 8 | 9 | is_html_output = function() { 10 | knitr::opts_knit$get("rmarkdown.pandoc.to")=="html" 11 | } 12 | 13 | knitr::opts_chunk$set( 14 | collapse=TRUE, 15 | comment="", 16 | prompt=TRUE, 17 | fig.dpi=96) 18 | 19 | if (is_html_output()) { 20 | options(width=1000) 21 | } 22 | ``` 23 | 24 | 25 | This is the 2.0-0.0 release of the SGP package posted to CRAN. This [GitHub tagged release](https://github.com/CenterForAssessment/SGP/releases/tag/7f10af5) 26 | can be downloaded via: 27 | 28 | ```{r eval=FALSE} 29 | devtools::install_github("CenterForAssessment/SGP", ref="7f10af5") 30 | ``` 31 | 32 | To see all the changes in this release check out the [change log](https://sgp.io/news/index.html#sgp-2-0-0-0). 33 | 34 | 35 | Feel free to drop me a line with any comments, feature requests, or ideas. And give us a shout-out Tweet using the Twitter button in the upper right! 36 | -------------------------------------------------------------------------------- /vignettes/releases/SGP-2.1-0.0.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "SGP 2.1-0.0" 3 | date: "October 24th, 2023" 4 | --- 5 | 6 | ```{r include = FALSE} 7 | library(SGP) 8 | 9 | is_html_output = function() { 10 | knitr::opts_knit$get("rmarkdown.pandoc.to")=="html" 11 | } 12 | 13 | knitr::opts_chunk$set( 14 | collapse=TRUE, 15 | comment="", 16 | prompt=TRUE, 17 | fig.dpi=96) 18 | 19 | if (is_html_output()) { 20 | options(width=1000) 21 | } 22 | ``` 23 | 24 | 25 | This is the 2.1-0.0 release of the SGP package posted to CRAN. This [GitHub tagged release](https://github.com/CenterForAssessment/SGP/releases/tag/ea8d8a3) 26 | can be downloaded via: 27 | 28 | ```{r eval=FALSE} 29 | devtools::install_github("CenterForAssessment/SGP", ref="ea8d8a3") 30 | ``` 31 | 32 | To see all the changes in this release check out the [change log](https://sgp.io/news/index.html#sgp-2-1-0-0). 33 | 34 | 35 | Feel free to drop me a line with any comments, feature requests, or ideas. And give us a shout-out Tweet using the Twitter button in the upper right! 36 | --------------------------------------------------------------------------------