diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json deleted file mode 100644 index 8ac18d2..0000000 --- a/.config/dotnet-tools.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "version": 1, - "isRoot": true, - "tools": { - "fsdocs-tool": { - "version": "20.0.1", - "commands": [ - "fsdocs" - ] - } - } -} \ No newline at end of file diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml deleted file mode 100644 index c0e2872..0000000 --- a/.github/workflows/build-and-test.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Build and test - -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - - -jobs: - build-and-test-linux: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - name: Setup .NET - uses: actions/setup-dotnet@v4 - with: - dotnet-version: 8.x.x - - name: make script executable - run: chmod u+x build.sh - - name: Build and test - working-directory: ./ - run: ./build.sh runTests - - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@v5 - with: - token: ${{ secrets.CODECOV_TOKEN }} - slug: BioFSharp/BioFSharp.Visualization - - build-and-test-windows: - - runs-on: windows-latest - - steps: - - uses: actions/checkout@v4 - - name: Setup .NET - uses: actions/setup-dotnet@v4 - with: - dotnet-version: 8.x.x - - name: Build and test - working-directory: ./ - run: ./build.cmd runTests diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml deleted file mode 100644 index 0e1100e..0000000 --- a/.github/workflows/deploy-docs.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Deploy Docs - -on: - push: - branches: [ main ] - paths: - - 'docs/**' - -jobs: - deploy: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: make script executable - run: chmod u+x build.sh - - name: Setup .NET - uses: actions/setup-dotnet@v4 - with: - dotnet-version: 8.x.x - - name: make script executable - run: chmod u+x build.sh - - name: restore tools - run: dotnet tool restore - - name: Build Docs - working-directory: ./ - run: ./build.sh builddocs - - name: Deploy - uses: JamesIves/github-pages-deploy-action@v4 - with: - folder: output # The folder the action should deploy. \ No newline at end of file diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 2777ea1..0000000 --- a/.gitignore +++ /dev/null @@ -1,403 +0,0 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. -## -## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore - -# User-specific files -*.rsuser -*.suo -*.user -*.userosscache -*.sln.docstates - -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Mono auto generated files -mono_crash.* - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -[Ww][Ii][Nn]32/ -[Aa][Rr][Mm]/ -[Aa][Rr][Mm]64/ -bld/ -[Bb]in/ -[Oo]bj/ -[Ll]og/ -[Ll]ogs/ - -# Visual Studio 2015/2017 cache/options directory -.vs/ -# Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ - -# Visual Studio 2017 auto generated files -Generated\ Files/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUnit -*.VisualState.xml -TestResult.xml -nunit-*.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -# Benchmark Results -BenchmarkDotNet.Artifacts/ - -# .NET Core -project.lock.json -project.fragment.lock.json -artifacts/ - -# ASP.NET Scaffolding -ScaffoldingReadMe.txt - -# StyleCop -StyleCopReport.xml - -# Files built by Visual Studio -*_i.c -*_p.c -*_h.h -*.ilk -*.meta -*.obj -*.iobj -*.pch -*.pdb -*.ipdb -*.pgc -*.pgd -*.rsp -# but not Directory.Build.rsp, as it configures directory-level build defaults -!Directory.Build.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*_wpftmp.csproj -*.log -*.tlog -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile -*.VC.db -*.VC.VC.opendb - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap - -# Visual Studio Trace Files -*.e2e - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# AxoCover is a Code Coverage Tool -.axoCover/* -!.axoCover/settings.json - -# Coverlet is a free, cross platform Code Coverage Tool -coverage*.json -coverage*.xml -coverage*.info - -# Visual Studio code coverage results -*.coverage -*.coveragexml - -# NCrunch -_NCrunch_* -.*crunch*.local.xml -nCrunchTemp_* - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# Note: Comment the next line if you want to checkin your web deploy settings, -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# Microsoft Azure Web App publish settings. Comment the next line if you want to -# checkin your Azure Web App publish settings, but sensitive information contained -# in these scripts will be unencrypted -PublishScripts/ - -# NuGet Packages -*.nupkg -# NuGet Symbol Packages -*.snupkg -# The packages folder can be ignored because of Package Restore -**/[Pp]ackages/* -# except build/, which is used as an MSBuild target. -!**/[Pp]ackages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/[Pp]ackages/repositories.config -# NuGet v3's project.json files produces more ignorable files -*.nuget.props -*.nuget.targets - -# Microsoft Azure Build Output -csx/ -*.build.csdef - -# Microsoft Azure Emulator -ecf/ -rcf/ - -# Windows Store app package directories and files -AppPackages/ -BundleArtifacts/ -Package.StoreAssociation.xml -_pkginfo.txt -*.appx -*.appxbundle -*.appxupload - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!?*.[Cc]ache/ - -# Others -ClientBin/ -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.jfm -*.pfx -*.publishsettings -orleans.codegen.cs - -# Including strong name files can present a security risk -# (https://github.com/github/gitignore/pull/2483#issue-259490424) -#*.snk - -# Since there are multiple workflows, uncomment next line to ignore bower_components -# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) -#bower_components/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm -ServiceFabricBackup/ -*.rptproj.bak - -# SQL Server files -*.mdf -*.ldf -*.ndf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings -*.rptproj.rsuser -*- [Bb]ackup.rdl -*- [Bb]ackup ([0-9]).rdl -*- [Bb]ackup ([0-9][0-9]).rdl - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat -node_modules/ - -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) -*.vbw - -# Visual Studio 6 auto-generated project file (contains which files were open etc.) -*.vbp - -# Visual Studio 6 workspace and project file (working project files containing files to include in project) -*.dsw -*.dsp - -# Visual Studio 6 technical files -*.ncb -*.aps - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Paket dependency manager -.paket/paket.exe -paket-files/ - -# FAKE - F# Make -.fake/ - -# CodeRush personal settings -.cr/personal - -# Python Tools for Visual Studio (PTVS) -__pycache__/ -*.pyc - -# Cake - Uncomment if you are using it -# tools/** -# !tools/packages.config - -# Tabs Studio -*.tss - -# Telerik's JustMock configuration file -*.jmconfig - -# BizTalk build output -*.btp.cs -*.btm.cs -*.odx.cs -*.xsd.cs - -# OpenCover UI analysis results -OpenCover/ - -# Azure Stream Analytics local run output -ASALocalRun/ - -# MSBuild Binary and Structured Log -*.binlog - -# NVidia Nsight GPU debugger configuration file -*.nvuser - -# MFractors (Xamarin productivity tool) working folder -.mfractor/ - -# Local History for Visual Studio -.localhistory/ - -# Visual Studio History (VSHistory) files -.vshistory/ - -# BeatPulse healthcheck temp database -healthchecksdb - -# Backup folder for Package Reference Convert tool in Visual Studio 2017 -MigrationBackup/ - -# Ionide (cross platform F# VS Code tools) working folder -.ionide/ - -# Fody - auto-generated XML schema -FodyWeavers.xsd - -# VS Code files for those working on multiple tools -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json -*.code-workspace - -# Local History for Visual Studio Code -.history/ - -# Windows Installer files from build outputs -*.cab -*.msi -*.msix -*.msm -*.msp - -# JetBrains Rider -*.sln.iml -/tmp/watch -/.fsdocs -/output diff --git a/BioFSharp.Visualization.sln b/BioFSharp.Visualization.sln deleted file mode 100644 index 3a9dcf0..0000000 --- a/BioFSharp.Visualization.sln +++ /dev/null @@ -1,73 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.31903.59 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{7501C4DF-A844-40A0-8742-3343E48E55F1}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{D152DA0B-8F60-4611-B613-642379E2B17C}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "project", "project", "{77A50576-9359-44E5-B2F9-95318AB3DAEA}" - ProjectSection(SolutionItems) = preProject - .gitignore = .gitignore - LICENSE = LICENSE - README.md = README.md - RELEASE_NOTES.md = RELEASE_NOTES.md - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{78399A41-F06A-4B35-AA24-E2E20209D8DE}" - ProjectSection(SolutionItems) = preProject - build.cmd = build.cmd - build.sh = build.sh - .config\dotnet-tools.json = .config\dotnet-tools.json - global.json = global.json - EndProjectSection -EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "build", "build\build.fsproj", "{8DCCA688-871C-49DD-BC06-4877F714497C}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{88932F99-4093-455A-901B-E0203694A436}" - ProjectSection(SolutionItems) = preProject - docs\index.fsx = docs\index.fsx - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".ci", ".ci", "{812698C9-F1C7-4708-8B28-B22FAAC0ADA4}" - ProjectSection(SolutionItems) = preProject - .github\workflows\build-and-test.yml = .github\workflows\build-and-test.yml - .github\workflows\deploy-docs.yml = .github\workflows\deploy-docs.yml - EndProjectSection -EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "BioFSharp.Visualization", "src\BioFSharp.Visualization\BioFSharp.Visualization.fsproj", "{5206207C-4C0E-B0AF-1AF5-9E150F257530}" -EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "BioFSharp.Visualization.Tests", "tests\BioFSharp.Visualization.Tests\BioFSharp.Visualization.Tests.fsproj", "{CEE58A95-C0FA-D276-5B4F-30025F4B96C9}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8DCCA688-871C-49DD-BC06-4877F714497C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8DCCA688-871C-49DD-BC06-4877F714497C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8DCCA688-871C-49DD-BC06-4877F714497C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8DCCA688-871C-49DD-BC06-4877F714497C}.Release|Any CPU.Build.0 = Release|Any CPU - {5206207C-4C0E-B0AF-1AF5-9E150F257530}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5206207C-4C0E-B0AF-1AF5-9E150F257530}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5206207C-4C0E-B0AF-1AF5-9E150F257530}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5206207C-4C0E-B0AF-1AF5-9E150F257530}.Release|Any CPU.Build.0 = Release|Any CPU - {CEE58A95-C0FA-D276-5B4F-30025F4B96C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CEE58A95-C0FA-D276-5B4F-30025F4B96C9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CEE58A95-C0FA-D276-5B4F-30025F4B96C9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CEE58A95-C0FA-D276-5B4F-30025F4B96C9}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {8DCCA688-871C-49DD-BC06-4877F714497C} = {78399A41-F06A-4B35-AA24-E2E20209D8DE} - {5206207C-4C0E-B0AF-1AF5-9E150F257530} = {7501C4DF-A844-40A0-8742-3343E48E55F1} - {CEE58A95-C0FA-D276-5B4F-30025F4B96C9} = {D152DA0B-8F60-4611-B613-642379E2B17C} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {E7E21A6C-2D45-4429-9F90-1A20E30D18ED} - EndGlobalSection -EndGlobal diff --git a/Dockerfile b/Dockerfile new file mode 100755 index 0000000..989c9ab --- /dev/null +++ b/Dockerfile @@ -0,0 +1,29 @@ +FROM mcr.microsoft.com/dotnet/sdk:7.0 + +RUN apt-get update \ + && apt-get -y upgrade \ + && apt-get -y install python3 python3-pip python3-dev ipython3 + +RUN python3 -m pip install --no-cache-dir notebook jupyterlab + +ARG NB_USER=fsdocs-user +ARG NB_UID=1000 +ENV USER ${NB_USER} +ENV NB_UID ${NB_UID} +ENV HOME /home/${NB_USER} + +RUN adduser --disabled-password \ + --gecos "Default user" \ + --uid ${NB_UID} \ + ${NB_USER} + +COPY . ${HOME} +USER root +RUN chown -R ${NB_UID} ${HOME} +USER ${NB_USER} + +ENV PATH="${PATH}:$HOME/.dotnet/tools/" + +RUN dotnet tool install --global Microsoft.dotnet-interactive --version 1.0.410202 + +RUN dotnet-interactive jupyter install diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 1c0ec04..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2025 BioFSharp - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/NuGet.config b/NuGet.config new file mode 100755 index 0000000..cf1ace5 --- /dev/null +++ b/NuGet.config @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index 0d4f6f6..0000000 --- a/README.md +++ /dev/null @@ -1,106 +0,0 @@ -# BioFSharp.Visualization - -![Logo](docs/img/Logo_large.png) - -A template repository for creating an extension package for BioFSharp. - -## Content - -- `src/BioFSharp.Visualization`: The main project folder. Contains a library with BioFSharp core dependency. -- `tests/BioFSharp.Visualization.Tests`: The test project folder. Contains a XUnit test project -- `build/build.fsproj`: A FAKE build project that handles building, testing, packaging, publishing, etc. -- `docs`: the docs folder contains an example index.fsx file with simple documentation boilerplate. - -## Setup - -Here is a list of things you should/might want to do after setting up a repo with this template: - -> [!IMPORTANT] -> Whenever you change a project file name or folder, make sure to fix the solution registration afterwards. - -- Rename some things: Replace `XYZ` with the name of your package - - `PackageTemplate.sln` - - `src/BioFSharp.Visualization` - - `src/BioFSharp.Visualization/BioFSharp.Visualization.fsproj` - - Rename and add nuget package metadata - - `tests/BioFSharp.Visualization` - - `tests/BioFSharp.Visualization.Tests/BioFSharp.Visualization.Tests.fsproj` - - Also make sure to fix the project reference to BioFSharp.Visualization when renamed - - in `build/ProjectInfo.fs`: - - Set project name: - ```fsharp - let project = "BioFSharp.Visualization" // replace with the name of your project - ``` - - Set git owner: - ```fsharp - let gitOwner = "BioFSharp" // replace with github account name or organization where repo is hosted if necessary - ``` - - fix test project path: - ```fsharp - let testProjects = - [ - "tests/BioFSharp.Visualization.Tests/BioFSharp.Visualization.Tests.fsproj" // replace with the name of your test project - ] - ``` - - in `.github/workflows/build-and-test.yml`: change codecov slug -- If needed, change the target framework of the project. it currently targets `.netstandard2.0` for maximum backwards compatibility, might want to target a newer `.net` version if you need a specific API. - -## Development - -### General - -BioFSharp repositories usually folllow this structure: - -``` -root -│ 📄.sln -│ 📄build.cmd -│ 📄build.sh -├───📁build -├───📁docs -├───📁src -| └───📁 -└───tests - └───📁 -``` - -- .sln is the root solution file. -- `build` contains a [FAKE](https://fake.build/) build project with targets for building, testing and packaging the project. -- `build/sh` and `build.cmd` in the root are shorthand scripts to execute the buildproject. -- `docs` contains the documentation in form of literate scripts and notebooks. -- `src` contains folders with the source code of the project(s). -- `tests` contains folders with test projects. - -### Build - -just call `build.sh` or `build.cmd` depending on your OS. - -### Test - -```bash -build.sh runtests -``` - -```bash -build.cmd runtests -``` - -### Create Nuget package - -```bash -build.sh pack -``` -```bash -build.cmd pack -``` - -### Docs - -You can watch locally with hot reload via - -```bash -build.sh watchdocs -``` -```bash -build.cmd watchdocs -``` \ No newline at end of file diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md deleted file mode 100644 index dcd339b..0000000 --- a/RELEASE_NOTES.md +++ /dev/null @@ -1,6 +0,0 @@ -### 1.0.0 - TBD - -Re-release of the deprecated BioFSharp.Vis package. This package will target netstandard and not use any netfx dependencies anymore - -Plots included in this version: -- SequenceLogo (Plotly.NET extension) \ No newline at end of file diff --git a/build.cmd b/build.cmd deleted file mode 100644 index 8d82883..0000000 --- a/build.cmd +++ /dev/null @@ -1,3 +0,0 @@ -@echo off - -dotnet run --project ./build/build.fsproj %* \ No newline at end of file diff --git a/build.sh b/build.sh deleted file mode 100644 index f33a768..0000000 --- a/build.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -set -eu -set -o pipefail - -dotnet run --project ./build/build.fsproj "$@" \ No newline at end of file diff --git a/build/BasicTasks.fs b/build/BasicTasks.fs deleted file mode 100644 index c5be532..0000000 --- a/build/BasicTasks.fs +++ /dev/null @@ -1,37 +0,0 @@ -module BasicTasks - -open BlackFox.Fake -open Fake.IO -open Fake.DotNet -open Fake.IO.Globbing.Operators - -open ProjectInfo - -let clean = BuildTask.create "Clean" [] { - !! "src/**/bin" - ++ "src/**/obj" - ++ "tests/**/bin" - ++ "tests/**/obj" - ++ "pkg" - |> Shell.cleanDirs -} - - -let setPrereleaseTag = BuildTask.create "SetPrereleaseTag" [] { - printfn "Please enter pre-release package suffix" - let suffix = System.Console.ReadLine() - prereleaseSuffix <- suffix - prereleaseTag <- (sprintf "%s-%s" release.NugetVersion suffix) - isPrerelease <- true -} - -/// builds the solution file (dotnet build solution.sln) -let buildSolution = - BuildTask.create "BuildSolution" [ clean ] { - solutionFile - |> DotNet.build (fun p -> - { p with MSBuildParams = { p.MSBuildParams with DisableInternalBinLog = true }} - |> DotNet.Options.withCustomParams (Some "-tl") - ) - } - diff --git a/build/Build.fs b/build/Build.fs deleted file mode 100644 index bd6b4bb..0000000 --- a/build/Build.fs +++ /dev/null @@ -1,46 +0,0 @@ -open BlackFox.Fake -open System.IO -open Fake.Core -open Fake.DotNet -open Fake.IO -open Fake.IO.FileSystemOperators -open Fake.IO.Globbing.Operators -open Fake.Tools - -open Helpers - -initializeContext() - -open BasicTasks -open TestTasks -open PackageTasks -open DocumentationTasks -open ReleaseTasks - -/// Full release of nuget package, git tag, and documentation for the stable version. -let _release = - BuildTask.createEmpty - "Release" - [clean; buildSolution; runTests; pack; buildDocs; createTag; publishNuget; releaseDocs] - -/// Full release of nuget package, git tag, and documentation for the prerelease version. -let _preRelease = - BuildTask.createEmpty - "PreRelease" - [setPrereleaseTag; clean; buildSolution; runTests; packPrerelease; buildDocsPrerelease; createPrereleaseTag; publishNugetPrerelease; prereleaseDocs] - -/// Full release of nuget package for the prerelease version. -let _releaseNoDocs = - BuildTask.createEmpty - "ReleaseNoDocs" - [clean; buildSolution; runTests; pack; createTag; publishNuget;] - -/// Full release of nuget package for the prerelease version. -let _preReleaseNoDocs = - BuildTask.createEmpty - "PreReleaseNoDocs" - [setPrereleaseTag; clean; buildSolution; runTests; packPrerelease; createPrereleaseTag; publishNugetPrerelease] - -[] -let main args = - runOrDefault buildSolution args diff --git a/build/DocumentationTasks.fs b/build/DocumentationTasks.fs deleted file mode 100644 index 8073637..0000000 --- a/build/DocumentationTasks.fs +++ /dev/null @@ -1,36 +0,0 @@ -module DocumentationTasks - -open Helpers -open ProjectInfo -open BasicTasks - -open BlackFox.Fake - - -let buildDocs = BuildTask.create "BuildDocs" [buildSolution] { - printfn "building docs with stable version %s" stableVersionTag - runDotNet - (sprintf "fsdocs build --eval --clean --properties Configuration=%s --parameters fsdocs-package-version %s" configuration stableVersionTag) - "./" -} - -let buildDocsPrerelease = BuildTask.create "BuildDocsPrerelease" [setPrereleaseTag; buildSolution] { - printfn "building docs with prerelease version %s" prereleaseTag - runDotNet - (sprintf "fsdocs build --eval --clean --properties Configuration=%s --parameters fsdocs-package-version %s" configuration prereleaseTag) - "./" -} - -let watchDocs = BuildTask.create "WatchDocs" [buildSolution] { - printfn "watching docs with stable version %s" stableVersionTag - runDotNet - (sprintf "fsdocs watch --eval --clean --properties Configuration=%s --parameters fsdocs-package-version %s" configuration stableVersionTag) - "./" -} - -let watchDocsPrerelease = BuildTask.create "WatchDocsPrerelease" [setPrereleaseTag; buildSolution] { - printfn "watching docs with prerelease version %s" prereleaseTag - runDotNet - (sprintf "fsdocs watch --eval --clean --properties Configuration=%s --parameters fsdocs-package-version %s" configuration prereleaseTag) - "./" -} diff --git a/build/Helpers.fs b/build/Helpers.fs deleted file mode 100644 index 5dd1ed8..0000000 --- a/build/Helpers.fs +++ /dev/null @@ -1,28 +0,0 @@ -module Helpers - -open BlackFox.Fake -open Fake.Core -open Fake.DotNet - -let initializeContext () = - let execContext = Context.FakeExecutionContext.Create false "build.fsx" [ ] - Context.setExecutionContext (Context.RuntimeContext.Fake execContext) - -/// Executes a dotnet command in the given working directory -let runDotNet cmd workingDir = - let result = - DotNet.exec (DotNet.Options.withWorkingDirectory workingDir) cmd "" - if result.ExitCode <> 0 then failwithf "'dotnet %s' failed in %s" cmd workingDir - -let runOrDefault defaultTarget args = - Trace.trace (sprintf "%A" args) - try - match args with - | [| target |] -> Target.runOrDefault target - | arr when args.Length > 1 -> - Target.run 0 (Array.head arr) ( Array.tail arr |> List.ofArray ) - | _ -> BuildTask.runOrDefault defaultTarget - 0 - with e -> - printfn "%A" e - 1 \ No newline at end of file diff --git a/build/MessagePrompts.fs b/build/MessagePrompts.fs deleted file mode 100644 index afa3708..0000000 --- a/build/MessagePrompts.fs +++ /dev/null @@ -1,18 +0,0 @@ -module MessagePrompts - -let prompt (msg:string) = - System.Console.Write(msg) - System.Console.ReadLine().Trim() - |> function | "" -> None | s -> Some s - |> Option.map (fun s -> s.Replace ("\"","\\\"")) - -let rec promptYesNo msg = - match prompt (sprintf "%s [Yn]: " msg) with - | Some "Y" | Some "y" -> true - | Some "N" | Some "n" -> false - | _ -> System.Console.WriteLine("Sorry, invalid answer"); promptYesNo msg - -let releaseMsg = """This will stage all uncommitted changes, push them to the origin and bump the release version to the latest number in the RELEASE_NOTES.md file. - Do you want to continue?""" - -let releaseDocsMsg = """This will push the docs to gh-pages. Remember building the docs prior to this. Do you want to continue?""" \ No newline at end of file diff --git a/build/PackageTasks.fs b/build/PackageTasks.fs deleted file mode 100644 index c97853e..0000000 --- a/build/PackageTasks.fs +++ /dev/null @@ -1,69 +0,0 @@ -module PackageTasks - -open ProjectInfo - -open MessagePrompts -open BasicTasks -open TestTasks - -open BlackFox.Fake -open Fake.Core -open Fake.DotNet -open Fake.IO.Globbing.Operators - -open System.Text.RegularExpressions - -/// https://github.com/Freymaurer/Fake.Extensions.Release#release-notes-in-nuget -let private replaceCommitLink input = - let commitLinkPattern = @"\[\[#[a-z0-9]*\]\(.*\)\] " - Regex.Replace(input,commitLinkPattern,"") - -let pack = BuildTask.create "Pack" [clean; buildSolution; runTests] { - if promptYesNo (sprintf "creating stable package with version %s OK?" stableVersionTag ) - then - !! "src/**/*.*proj" - -- "src/bin/*" - |> Seq.iter (Fake.DotNet.DotNet.pack (fun p -> - let msBuildParams = - {p.MSBuildParams with - Properties = ([ - "Version",stableVersionTag - "PackageReleaseNotes", (release.Notes |> List.map replaceCommitLink |> String.concat "\r\n" ) - ] @ p.MSBuildParams.Properties) - DisableInternalBinLog = true - } - { - p with - MSBuildParams = msBuildParams - OutputPath = Some pkgDir - } - |> DotNet.Options.withCustomParams (Some "-tl") - )) - else failwith "aborted" -} - -let packPrerelease = BuildTask.create "PackPrerelease" [setPrereleaseTag; clean; buildSolution; runTests] { - if promptYesNo (sprintf "package tag will be %s OK?" prereleaseTag ) - then - !! "src/**/*.*proj" - -- "src/bin/*" - |> Seq.iter (Fake.DotNet.DotNet.pack (fun p -> - let msBuildParams = - {p.MSBuildParams with - Properties = ([ - "Version", prereleaseTag - "PackageReleaseNotes", (release.Notes |> List.map replaceCommitLink |> String.toLines ) - ] @ p.MSBuildParams.Properties) - DisableInternalBinLog = true - } - { - p with - VersionSuffix = Some prereleaseSuffix - OutputPath = Some pkgDir - MSBuildParams = msBuildParams - } - |> DotNet.Options.withCustomParams (Some "-tl") - )) - else - failwith "aborted" -} diff --git a/build/ProjectInfo.fs b/build/ProjectInfo.fs deleted file mode 100644 index 835d7f5..0000000 --- a/build/ProjectInfo.fs +++ /dev/null @@ -1,40 +0,0 @@ -module ProjectInfo - -open Fake.Core - - -let project = "BioFSharp.Visualization" - -let testProjects = - [ - "tests/BioFSharp.Visualization.Tests/BioFSharp.Visualization.Tests.fsproj" - ] - -let solutionFile = $"{project}.sln" - -let configuration = "Release" - -let gitOwner = "BioFSharp" - -let gitHome = $"https://github.com/{gitOwner}" - -let projectRepo = $"https://github.com/{gitOwner}/{project}" - -let pkgDir = "pkg" - - -// Create RELEASE_NOTES.md if not existing. Or "release" would throw an error. -Fake.Extensions.Release.ReleaseNotes.ensure() - -let release = ReleaseNotes.load "RELEASE_NOTES.md" - -let stableVersion = SemVer.parse release.NugetVersion - -let stableVersionTag = (sprintf "%i.%i.%i" stableVersion.Major stableVersion.Minor stableVersion.Patch ) - -let mutable prereleaseSuffix = "" - -let mutable prereleaseTag = "" - -let mutable isPrerelease = false - diff --git a/build/ReleaseNotesTasks.fs b/build/ReleaseNotesTasks.fs deleted file mode 100644 index 8b67175..0000000 --- a/build/ReleaseNotesTasks.fs +++ /dev/null @@ -1,31 +0,0 @@ -module ReleaseNotesTasks - - -open Fake.Extensions.Release -open BlackFox.Fake - -/// This might not be necessary, mostly useful for apps which want to display current version as it creates an accessible F# version script from RELEASE_NOTES.md -let createAssemblyVersion = BuildTask.create "createvfs" [] { - AssemblyVersion.create ProjectInfo.project -} - -// https://github.com/Freymaurer/Fake.Extensions.Release#releaseupdate -let updateReleaseNotes = BuildTask.createFn "ReleaseNotes" [] (fun config -> - ReleaseNotes.update(ProjectInfo.gitOwner, ProjectInfo.project, config) -) - - -// https://github.com/Freymaurer/Fake.Extensions.Release#githubdraft -let githubDraft = BuildTask.createFn "GithubDraft" [] (fun config -> - - let body = "We are ready to go for the first release!" - - Github.draft( - ProjectInfo.gitOwner, - ProjectInfo.project, - (Some body), - None, - config - ) -) - diff --git a/build/ReleaseTasks.fs b/build/ReleaseTasks.fs deleted file mode 100644 index d7f7005..0000000 --- a/build/ReleaseTasks.fs +++ /dev/null @@ -1,86 +0,0 @@ -module ReleaseTasks - -open MessagePrompts -open ProjectInfo -open BasicTasks -open TestTasks -open PackageTasks -open DocumentationTasks - -open BlackFox.Fake -open Fake.Core -open Fake.DotNet -open Fake.Api -open Fake.Tools -open Fake.IO -open Fake.IO.Globbing.Operators - -let createTag = BuildTask.create "CreateTag" [clean; buildSolution; runTests; pack] { - if promptYesNo (sprintf "tagging branch with %s OK?" stableVersionTag ) then - Git.Branches.tag "" stableVersionTag - Git.Branches.pushTag "" projectRepo stableVersionTag - else - failwith "aborted" -} - -let createPrereleaseTag = BuildTask.create "CreatePrereleaseTag" [setPrereleaseTag; clean; buildSolution; runTests; packPrerelease] { - if promptYesNo (sprintf "tagging branch with %s OK?" prereleaseTag ) then - Git.Branches.tag "" prereleaseTag - Git.Branches.pushTag "" projectRepo prereleaseTag - else - failwith "aborted" -} - -let publishNuget = BuildTask.create "PublishNuget" [clean; buildSolution; runTests; pack] { - let targets = (!! (sprintf "%s/*.*pkg" pkgDir )) - for target in targets do printfn "%A" target - let msg = sprintf "release package with version %s?" stableVersionTag - if promptYesNo msg then - let source = "https://api.nuget.org/v3/index.json" - let apikey = Environment.environVar "YOUR_KEY_HERE" - for artifact in targets do - let result = DotNet.exec id "nuget" (sprintf "push -s %s -k %s %s --skip-duplicate" source apikey artifact) - if not result.OK then failwith "failed to push packages" - else failwith "aborted" -} - -let publishNugetPrerelease = BuildTask.create "PublishNugetPrerelease" [clean; buildSolution; runTests; packPrerelease] { - let targets = (!! (sprintf "%s/*.*pkg" pkgDir )) - for target in targets do printfn "%A" target - let msg = sprintf "release package with version %s?" prereleaseTag - if promptYesNo msg then - let source = "https://api.nuget.org/v3/index.json" - let apikey = Environment.environVar "YOUR_KEY_HERE" - for artifact in targets do - let result = DotNet.exec id "nuget" (sprintf "push -s %s -k %s %s --skip-duplicate" source apikey artifact) - if not result.OK then failwith "failed to push packages" - else failwith "aborted" -} - -let releaseDocs = BuildTask.create "ReleaseDocs" [buildDocs] { - let msg = - sprintf "release docs for version %s?" - stableVersionTag - if promptYesNo msg then - Shell.cleanDir "temp" - Git.CommandHelper.runSimpleGitCommand "." (sprintf "clone %s temp/gh-pages --depth 1 -b gh-pages" projectRepo) |> ignore - Shell.copyRecursive "output" "temp/gh-pages" true |> printfn "%A" - Git.CommandHelper.runSimpleGitCommand "temp/gh-pages" "add ." |> printfn "%s" - let cmd = sprintf """commit -a -m "Update generated documentation for version %s""" stableVersionTag - Git.CommandHelper.runSimpleGitCommand "temp/gh-pages" cmd |> printfn "%s" - Git.Branches.push "temp/gh-pages" - else failwith "aborted" -} - -let prereleaseDocs = BuildTask.create "PrereleaseDocs" [buildDocsPrerelease] { - let msg = sprintf "release docs for version %s?" prereleaseTag - if promptYesNo msg then - Shell.cleanDir "temp" - Git.CommandHelper.runSimpleGitCommand "." (sprintf "clone %s temp/gh-pages --depth 1 -b gh-pages" projectRepo) |> ignore - Shell.copyRecursive "output" "temp/gh-pages" true |> printfn "%A" - Git.CommandHelper.runSimpleGitCommand "temp/gh-pages" "add ." |> printfn "%s" - let cmd = sprintf """commit -a -m "Update generated documentation for version %s""" prereleaseTag - Git.CommandHelper.runSimpleGitCommand "temp/gh-pages" cmd |> printfn "%s" - Git.Branches.push "temp/gh-pages" - else failwith "aborted" -} diff --git a/build/TestTasks.fs b/build/TestTasks.fs deleted file mode 100644 index 4ae0afc..0000000 --- a/build/TestTasks.fs +++ /dev/null @@ -1,26 +0,0 @@ -module TestTasks - -open BlackFox.Fake -open Fake.DotNet - -open ProjectInfo -open BasicTasks - - -let runTests = BuildTask.create "RunTests" [clean; buildSolution] { - testProjects - |> Seq.iter (fun testProject -> - testProject - |> Fake.DotNet.DotNet.test (fun testParams -> - { testParams with - Collect = Some "XPlat Code Coverage" - Logger = Some "console;verbosity=detailed" - Configuration = DotNet.BuildConfiguration.fromString configuration - NoBuild = true - MSBuildParams = { testParams.MSBuildParams with DisableInternalBinLog = true } - } - |> DotNet.Options.withCustomParams (Some "-tl") - ) - ) -} - diff --git a/build/build.fsproj b/build/build.fsproj deleted file mode 100644 index cce1a5a..0000000 --- a/build/build.fsproj +++ /dev/null @@ -1,34 +0,0 @@ - - - - net8.0 - Exe - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/content/fsdocs-default.css b/content/fsdocs-default.css new file mode 100755 index 0000000..e2063f5 --- /dev/null +++ b/content/fsdocs-default.css @@ -0,0 +1,1220 @@ +:root { + --monospace-font: "Fira Code", monospace; + --system-font: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; + --heading-font-family: var(--system-font); + + --spacing-50: 4px; + --spacing-100: 8px; + --spacing-200: 12px; + --spacing-300: 16px; + --spacing-400: 24px; + --spacing-500: 32px; + --spacing-600: 48px; + --spacing-700: 64px; + --spacing-800: 96px; + --spacing-900: 128px; + --spacing-950: 192px; + + --font-50: 12px; + --font-100: 14px; + --font-200: 16px; + --font-300: 18px; + --font-400: 20px; + --font-500: 24px; + --font-600: 30px; + --font-700: 36px; + --font-800: 48px; + --font-900: 60px; + --font-950: 72px; + + --line-height: 1.5; + --heading-line-height: 1.25; + --radius: 6px; + + --container-sm: 768px; + --container-md: 960px; + --container-lg: 1024px; + --container-xl: 1200px; + --container-xxl: 1400px; + --container-xxxl: 1800px; + --main-menu-width: 260px; + --page-menu-width: var(--main-menu-width); + --header-height: 60px; + --body-grid-template-columns: var(--main-menu-width) minmax(0, 1fr); + --body-grid-template-columns-xl: var(--main-menu-width) minmax(0, 1fr) var(--page-menu-width); + --main-menu-grid-row: 2; + --main-menu-grid-column: 1; + --main-grid-row: 2; + --main-grid-column: 2; + --dialog-width: 500px; + --api-docs-first-column-min-width: 320px; + --api-docs-second-column-min-width: 240px; + + /* light theme */ + --primary: #1e8bc3; + --background: #f5f5f6; + --text-color: #020202; + --text-hover: #282828; + --heading-color: #2e293a; + --code-background: #ffffff; + --code-color: #1a4b0b; + --header-background: #f9fbfc; + --header-border: #e8ecf1; + --header-link-color: var(--text-color); + --mobile-menu-background: var(--header-background); + --menu-color: var(--text-color); + --menu-item-hover-background: #eff0f1; + --menu-item-hover-color: var(--menu-color); + --doc-tip-background: #F7F7F7; + --link-color: #4871f7; + --link-hover: #91aafa; + --search-background: rgb(229, 231, 235); + --nav-category: rgb(156, 163, 175); + --scrollbar-track-background: #424242; + --scrollbar-track-border: #4A4A4A; + --scrollbar-thumb-background: #686868; + --shadow-color: hsla(0, 0%, 0%, .1); + --main-shadow-color: hsla(0, 0%, 0%, .025); + --aside-background: var(--header-background); + --blockquote-bacground-color: var(--header-background); + --blockquote-color: var(--text-color); + --on-this-page-color: var(--menu-color); + --page-menu-background-color: var(--header-background); + --page-menu-background-border-color: var(--header-border); + --page-menu-background-hover-border-color: var(--text-color); + --nav-item-border-color: var(--header-border); + --nav-item-active-border-color: var(--text-color); + --dialog-background-color: var(--header-background); + --dialog-empty-color: var(--nav-category); + --dialog-icon-color: var(--text-color); + --dialog-link-color: var(--link-color); + --dialog-link-hover-color: var(--header-background); + --dialog-link-hover-background-color: var(--link-hover); + --code-fence-border-color: transparent; + + --header-brand-text-transform: none; + + --code-strings-color: #0093A1; + --code-printf-color: #6B2FBA; + --code-escaped-color: #EA8675; + --code-identifiers-color: #6B2FBA; + --code-module-color: #009999; + --code-reference-color: #4974D1; + --code-value-color: #1B6600; + --code-interface-color: #43AEC6; + --code-typearg-color: #43AEC6; + --code-disposable-color: #43AEC6; + --code-property-color: #43AEC6; + --code-punctuation-color: #43AEC6; + --code-punctuation2-color: var(--text-color); + --code-function-color: #6B2FBA; + --code-function2-color: #6B2FBA; + --code-activepattern-color: #4ec9b0; + --code-unioncase-color: #4ec9b0; + --code-enumeration-color: #8C6C41; + --code-keywords-color: #0F54D6; + --code-comment-color: #707070; + --code-operators-color: #0F54D6; + --code-numbers-color: #009999; + --code-linenumbers-color: #80b0b0; + --code-mutable-color: #1b6600; + --code-inactive-color: #808080; + --code-preprocessor-color: #af75c1; + --code-fsioutput-color: #808080; + --code-tooltip-color: #d1d1d1; +} + +/* dark theme */ + +[data-theme=dark] { + --primary: #81cfe0; + --background: rgb(20, 21, 26); + --text-color: #F7F7F7; + --text-hover: #FFF; + --heading-color: rgb(229, 231, 235); + --code-background: #28282D; + --code-color: #f5f5f6; + --header-background: #0c1318; + --header-border: #9b9b9b; + --menu-item-hover-background: #2c2624; + --doc-tip-background: #2e293a; + --link-color: #c5eff7; + --search-background: #020202; + --nav-category: rgb(207, 211, 215); + --code-strings-color: #86b4b9; + --code-printf-color: #6B2FBA; + --code-escaped-color: #EA8675; + --code-identifiers-color: #d1b3f5; + --code-module-color: #15e1e1; + --code-reference-color: #40fddd; + --code-value-color: #ffb4e9; + --code-interface-color: #43AEC6; + --code-typearg-color: #43AEC6; + --code-disposable-color: #6dd6f1; + --code-property-color: #6acfe7; + --code-punctuation-color: #43AEC6; + --code-punctuation2-color: var(--text-color); + --code-function-color: #6B2FBA; + --code-function2-color: #cbda9d; + --code-activepattern-color: #4ec9b0; + --code-unioncase-color: #4ec9b0; + --code-enumeration-color: #8C6C41; + --code-keywords-color: #a7c2f8; + --code-comment-color: #84d16e; + --code-operators-color: #b4c6ee; + --code-numbers-color: #009999; + --code-linenumbers-color: #80b0b0; + --code-mutable-color: #1b6600; + --code-inactive-color: #808080; + --code-preprocessor-color: #af75c1; + --code-fsioutput-color: #808080; + --code-tooltip-color: #d1d1d1; +} + +/* CSS Reset, source: https://www.joshwcomeau.com/css/custom-css-reset/ */ +*, *::before, *::after { + box-sizing: border-box; +} + +* { + margin: 0; +} + +html { + overflow-y: hidden; +} + +body { + line-height: 1.5; + -webkit-font-smoothing: antialiased; +} + +picture, video, canvas, svg { + display: block; + max-width: 100%; +} + +input, button, textarea, select { + font: inherit; +} + +p, h1, h2, h3, h4, h5, h6 { + overflow-wrap: break-word; +} + +/* Main layout */ +body { + font-family: var(--system-font); + background-color: var(--background); + color: var(--text-color); + line-height: var(--line-height); + scroll-padding-top: var(--header-height); + scroll-behavior: smooth; +} + +header { + background-color: var(--header-background); + padding: var(--spacing-300); + height: var(--header-height); + display: flex; + align-items: center; + justify-content: space-between; + position: sticky; + top: 0; + z-index: 100; + box-shadow: 0 1px 1px var(--shadow-color); + + & .start { + display: flex; + align-items: center; + + & #menu-toggle { + position: relative; + height: var(--spacing-500); + width: var(--spacing-500); + border: 1px solid var(--header-border); + border-radius: var(--radius); + box-shadow: 0 1px 1px var(--shadow-color); + + & .icon { + top: 4px; + left: 4px; + width: calc(var(--spacing-500) - 4px); + height: calc(var(--spacing-500) - 4px); + position: absolute; + color: var(--header-link-color); + + &.open { + display: none; + } + } + + & input[type=checkbox] { + position: absolute; + width: 100%; + height: 100%; + left: 0; + top: 0; + appearance: none; + cursor: pointer; + } + + & .menu { + visibility: hidden; + height: 0; + opacity: 0; + width: 100%; + transition: all 0.2s ease-in-out; + position: fixed; + top: var(--header-height); + left: 0; + background-color: var(--mobile-menu-background); + list-style: none; + padding: var(--spacing-300); + overflow-y: auto; + } + + & input:checked + .menu { + visibility: visible; + opacity: 1; + height: calc(100vh - var(--header-height)); + } + + &:has(input:checked) { + .icon.open { + display: block; + } + + .icon.closed { + display: none; + } + } + } + + > a { + display: flex; + justify-content: center; + align-items: center; + text-decoration: none; + color: var(--header-link-color); + } + + & img { + margin: 0 var(--spacing-200); + border-radius: var(--radius); + height: calc(var(--spacing-500) - 2px); + } + + & strong { + line-height: var(--spacing-500); + font-size: var(--font-200); + display: block; + text-transform: var(--header-brand-text-transform); + font-weight: 500; + } + } + + & .end { + display: flex; + align-items: center; + + & a { + display: none; + color: var(--header-link-color); + } + + & > .themeToggle, & > .search { + cursor: pointer; + height: var(--spacing-500); + align-items: center; + margin: 0 var(--spacing-100); + } + + & > .search { + display: flex; + color: var(--header-link-color); + } + } +} + +aside { + display: none; +} + +main { + height: calc(100dvh - var(--header-height)); +} + +#content { + padding: var(--spacing-300); + + > *:first-child { + margin-top: 0; + } +} + +#fsdocs-page-menu { + display: none; + padding: var(--spacing-300); + background-color: var(--page-menu-background-color); + border-left: 1px solid var(--page-menu-background-border-color); + + &:has(.empty) { + display: none; + } + + > #on-this-page { + font-size: var(--font-100); + line-height: 1.5; + color: var(--on-this-page-color); + font-weight: 500; + margin: 0 0 var(--spacing-50); + } + + & ul { + list-style: none; + padding: 0; + margin: 0; + + & li { + border-left: 1px solid var(--header-border); + margin: 0; + + &:hover, &:focus { + border-color: var(--page-menu-background-hover-border-color); + } + + & a { + color: var(--menu-color); + text-decoration: none; + padding: var(--spacing-50) var(--spacing-100); + display: block; + overflow-x: hidden; + text-overflow: ellipsis; + } + + &.level-3 { + padding-left: var(--spacing-100); + } + + &.level-4 { + padding-left: var(--spacing-300); + } + } + } +} + +/* menu items */ +.menu { + padding: 0; + + & li { + list-style: none; + margin: 0; + } + + .nav-header { + margin-top: var(--spacing-300); + text-transform: uppercase; + font-size: var(--font-200); + font-weight: 500; + color: var(--menu-color); + } +} + +.nav-header:first-child { + margin-top: 0; +} + +.nav-item { + border-left: 1px solid var(--nav-item-border-color); + + & a { + color: var(--menu-color); + text-decoration: none; + font-size: var(--font-200); + padding: var(--spacing-100); + display: block; + overflow-x: hidden; + text-overflow: ellipsis; + + &:hover { + background-color: var(--menu-item-hover-background); + color: var(--menu-item-hover-color); + } + } + + &:hover, &.active { + border-color: var(--nav-item-active-border-color); + } + + &.active { + font-weight: 600; + } +} + +@media screen and (min-width: 768px) { + #menu-toggle { + display: none; + } + + body { + display: grid; + grid-template-rows: var(--header-height) minmax(0, 1fr); + grid-template-columns:var(--body-grid-template-columns); + gap: 0; + } + + header { + border-bottom: 1px solid var(--header-border); + grid-row: 1; + grid-column: span 2; + box-shadow: none; + + & .end { + > a { + display: flex; + align-items: center; + text-decoration: none; + + &:hover { + color: var(--link-hover); + } + } + } + } + + aside, main { + height: calc(100vh - var(--header-height)); + } + + aside { + position: sticky; + top: var(--header-height); + } + + #fsdocs-main-menu { + display: block; + padding: var(--spacing-300) var(--spacing-500); + background-color: var(--aside-background); + width: var(--main-menu-width); + border-right: 1px solid var(--header-border); + grid-row: var(--main-menu-grid-row); + grid-column: var(--main-menu-grid-column); + overflow-y: auto; + } + + main { + grid-row: var(--main-grid-row); + grid-column: var(--main-grid-column); + box-shadow: inset 1px 1px var(--main-shadow-color); + border-radius: 0; + } + + #content { + padding-left: var(--spacing-300); + padding-right: var(--spacing-300); + } +} + +@media screen and (min-width: 768px) { + #content { + max-width: calc(100vw - var(--main-menu-width) - var(--spacing-300) - var(--spacing-300)); + margin: 0 auto; + } +} + +@media screen and (min-width: 960px) { + #content { + max-width: calc(var(--container-md) - var(--main-menu-width) - var(--spacing-300) - var(--spacing-300)); + } +} + +@media screen and (min-width: 1024px) { + #content { + max-width: calc(var(--container-lg) - var(--main-menu-width) - var(--spacing-300) - var(--spacing-300)); + } +} + +@media screen and (min-width: 1200px) { + body { + grid-template-columns: var(--body-grid-template-columns-xl); + + &.api-docs { + grid-template-columns: var(--body-grid-template-columns); + + #content { + max-width: calc(var(--container-xl) - var(--main-menu-width) - var(--spacing-300) - var(--spacing-300)); + } + + #fsdocs-page-menu { + display: none; + } + } + } + + header { + grid-column: span 3; + } + + #fsdocs-page-menu { + grid-column: 3; + display: block; + } + + #content { + max-width: calc(var(--container-xl) - var(--main-menu-width) - var(--page-menu-width) - var(--spacing-300) - var(--spacing-300)); + } +} + +@media screen and (min-width: 1400px) { + body { + &.api-docs, &:has(#fsdocs-page-menu .empty) { + #content { + max-width: calc(var(--container-xxl) - var(--main-menu-width) - var(--spacing-300) - var(--spacing-300)); + } + } + } + + #content { + max-width: calc(var(--container-xxl) - var(--main-menu-width) - var(--page-menu-width) - var(--spacing-300) - var(--spacing-300)); + } +} + +@media screen and (min-width: 1800px) { + body { + &.api-docs, &:has(#fsdocs-page-menu .empty) { + #content { + max-width: calc(var(--container-xxxl) - var(--main-menu-width) - var(--spacing-300) - var(--spacing-300)); + } + } + } + + #content { + max-width: calc(var(--container-xxxl) - var(--main-menu-width) - var(--page-menu-width) - var(--spacing-300) - var(--spacing-300)); + } +} + +/* Headings */ +h1, h2, h3, h4, h5, h6 { + font-family: var(--heading-font-family); +} + +h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { + color: var(--heading-color); + text-decoration: none; +} + +h1 { + font-size: var(--font-600); + line-height: var(--heading-line-height); + margin-bottom: var(--spacing-400); + margin-top: var(--spacing-50); +} + +h2 { + font-size: var(--font-500); + line-height: var(--heading-line-height); + margin-top: var(--spacing-400); + margin-bottom: var(--spacing-300); +} + +h3 { + font-size: var(--font-400); + line-height: var(--heading-line-height); + margin-top: var(--spacing-300); + margin-bottom: var(--spacing-200); +} + +h4 { + font-weight: bold; +} + +h4, h5, h6 { + font-size: var(--font-300); + margin-top: var(--spacing-200); + margin-bottom: var(--spacing-200); +} + +@media screen and (min-width: 768px) { + h1 { + font-size: var(--font-800); + margin-bottom: var(--spacing-400); + line-height: var(--heading-line-height); + } + + h2 { + font-size: var(--font-700); + margin-top: var(--spacing-500); + margin-bottom: var(--spacing-400); + } + + h3 { + font-size: var(--font-600); + margin-top: var(--spacing-500); + margin-bottom: var(--spacing-200); + } + + h4 { + font-size: var(--font-500); + } + + h4, h5, h6 { + margin-top: var(--spacing-300); + } +} + +/* Common items */ +a { + color: var(--link-color); +} + +p { + line-height: 1.8; + margin-top: var(--spacing-300); +} + +ol, ul { + padding-left: var(--spacing-400); +} + +ol li, ul li { + margin: var(--spacing-100) 0; +} + +img { + max-width: 100%; +} + +#content > table { + margin: var(--spacing-300) 0; +} + +blockquote { + border-left: var(--spacing-50) solid var(--primary); + margin: var(--spacing-200) 0; + margin-left: var(--spacing-200); + padding: var(--spacing-100) var(--spacing-300); + background-color: var(--blockquote-bacground-color); + color: var(--blockquote-color); + + > p { + margin: 0; + padding: 0; + } +} + +@media screen and (min-width: 768px) { + blockquote { + margin-left: var(--spacing-400); + } +} + +/* Code snippets */ + +/* reset browser style */ +pre { + margin: 0; + padding: 0; +} + +code, table.pre, pre { + background-color: var(--code-background); + color: var(--code-color); + font-family: var(--monospace-font); + font-variant-ligatures: none; + font-size: var(--font-200); + -webkit-text-size-adjust: 100%; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + font-size: inherit; +} + +table.pre, #content > pre.fssnip { + border: 1px solid var(--code-fence-border-color); +} + +table.pre, pre.fssnip.highlighted { + margin: var(--spacing-300) 0; + padding: var(--spacing-200); +} + +table.pre .snippet pre.fssnip { + padding: 0; + margin: 0; +} + +p > code, li > code { + padding: 2px var(--spacing-50); +} + +table.pre, pre > code { + display: block; +} + +pre.fssnip > code { + max-width: initial; + margin-bottom: initial; +} + +/* avoid problems with transparent background colors */ +pre.fssnip.highlighted > code, table.pre .fssnip, table.pre .fssnip code { + background-color: transparent; +} + +/* Custom scrollbar styling */ +body, aside, #menu-toggle .menu, table.pre, code, +.fsdocs-entity-xmldoc > div > pre, div.fsdocs-summary > pre, +dialog ul, div.fsdocs-tip, .fsdocs-xmldoc > pre { + overflow-x: auto; + max-width: 100%; + + &::-webkit-scrollbar { + height: var(--spacing-100); + width: var(--spacing-100); + } + + &::-webkit-scrollbar-track { + background-color: var(--scrollbar-track-background); + border: 1px solid var(--scrollbar-track-border); + } + + &::-webkit-scrollbar-thumb { + background-color: var(--scrollbar-thumb-background); + } +} + +body, aside, #menu-toggle .menu, table.pre, code, +.fsdocs-entity-xmldoc > div > pre, div.fsdocs-summary > pre, +dialog ul, div.fsdocs-tip, .fsdocs-xmldoc > pre { + @media screen and (min-width: 768px) { + &::-webkit-scrollbar { + height: var(--spacing-200); + width: var(--spacing-300); + } + } +} + +table.pre, code, pre.fssnip { + border-radius: var(--radius); +} + +/* Code coloring */ +.param-name, +.return-name, +.param { + font-weight: 900; + font-size: var(--font-100); + font-family: var(--monospace-font); + font-variant-ligatures: none; +} + +.fssnip { + /* strings --- and stlyes for other string related formats */ + + & span.s { + color: var(--code-strings-color); + } + + /* printf formatters */ + + & span.pf { + color: var(--code-printf-color); + } + + /* escaped chars */ + + & span.e { + color: var(--code-escaped-color); + } + + /* identifiers --- and styles for more specific identifier types */ + + & span.id { + color: var(--code-identifiers-color);; + } + + /* module */ + + & span.m { + color: var(--code-module-color); + } + + /* reference type */ + + & span.rt { + color: var(--code-reference-color); + } + + /* value type */ + + & span.vt { + color: var(--code-value-color); + } + + /* interface */ + + & span.if { + color: var(--code-interface-color); + } + + /* type argument */ + + & span.ta { + color: var(--code-typearg-color); + } + + /* disposable */ + + & span.d { + color: var(--code-disposable-color); + } + + /* property */ + + & span.prop { + color: var(--code-property-color); + } + + /* punctuation */ + + & span.p { + color: var(--code-punctuation-color); + } + + & span.pn { + color: var(--code-punctuation2-color); + } + + /* function */ + + & span.f { + color: var(--code-function-color); + } + + & span.fn { + color: var(--code-function2-color); + } + + /* active pattern */ + + & span.pat { + color: var(--code-activepattern-color); + } + + /* union case */ + + & span.u { + color: var(--code-unioncase-color); + } + + /* enumeration */ + + & span.e { + color: var(--code-enumeration-color); + } + + /* keywords */ + + & span.k { + color: var(--code-keywords-color); + } + + /* comment */ + + & span.c { + color: var(--code-comment-color); + font-weight: 400; + font-style: italic; + } + + /* operators */ + + & span.o { + color: var(--code-operators-color); + } + + /* numbers */ + + & span.n { + color: var(--code-numbers-color); + } + + /* line number */ + + & span.l { + color: var(--code-linenumbers-color); + } + + /* mutable var or ref cell */ + + & span.v { + color: var(--code-mutable-color); + font-weight: bold; + } + + /* inactive code */ + + & span.inactive { + color: var(--code-inactive-color); + } + + /* preprocessor */ + + & span.prep { + color: var(--code-preprocessor-color); + } + + /* fsi output */ + + & span.fsi { + color: var(--code-fsioutput-color); + } +} + +/* tooltips */ +div.fsdocs-tip { + z-index: 1000; + display: none; + background-color: var(--doc-tip-background); + border-radius: var(--radius); + border: 1px solid var(--header-border); + padding: var(--spacing-200); + font-family: var(--monospace-font); + font-variant-ligatures: none; + color: var(--code-color); + box-shadow: 0 1px 1px var(--shadow-color); + + & code { + color: var(--code-color); + } +} + +span[onmouseout] { + cursor: pointer; +} + +/* API docs */ +#content > div > h2:first-child { + margin-top: 0; +} + +.fsdocs-xmldoc { + & pre { + overflow-x: auto; + } +} + +.table { + width: 100%; + table-layout: fixed; + + & thead tr td { + font-weight: bold; + padding: var(--spacing-400) 0; + } + + & tr { + display: flex; + flex-flow: row wrap; + column-gap: var(--spacing-300); + + & td:first-of-type { + flex: 25 0 0; + min-width: var(--api-docs-first-column-min-width); + overflow-x: hidden; + text-overflow: ellipsis; + overflow-wrap: break-word; + + & p { + margin: unset; + } + } + + & td:nth-of-type(2) { + flex: 75 0 0; + min-width: var(--api-docs-second-column-min-width); + } + } + + & tbody td { + border-top: 1px solid var(--header-border); + padding: var(--spacing-300) 0; + } + + .fsdocs-entity-xmldoc { + > div { + display: flex; + flex-direction: row-reverse; + justify-content: flex-start; + align-items: flex-start; + + & p.fsdocs-summary { + margin: 0; + flex-grow: 1; + } + + & pre { + margin-bottom: var(--spacing-200); + padding: var(--spacing-50); + flex-grow: 1; + overflow-x: auto; + } + } + } + + .fsdocs-member-xmldoc { + & summary { + display: list-item; + counter-increment: list-item 0; + list-style: disclosure-closed outside; + cursor: pointer; + margin-left: var(--spacing-300); + + > .fsdocs-summary { + display: flex; + flex-direction: row-reverse; + justify-content: flex-start; + align-items: flex-start; + + & p.fsdocs-summary { + margin: 0; + flex-grow: 1; + } + + & pre { + margin-bottom: var(--spacing-200); + padding: var(--spacing-50); + flex-grow: 1; + overflow-x: auto; + } + } + } + + & details[open] summary { + list-style-type: disclosure-open; + margin-bottom: var(--spacing-200); + } + + .fsdocs-returns, .fsdocs-params { + margin: var(--spacing-200); + + &:first-child { + margin-top: 0; + } + + &:last-child { + margin-bottom: 0; + } + } + + .fsdocs-return-name, .fsdocs-param-name { + font-weight: 500; + } + } +} + +.fsdocs-source-link { + display: none; + padding: 0 var(--spacing-100); + color: var(--text-color); + cursor: pointer; + height: var(--font-500); + width: var(--font-500); + margin: 0 var(--spacing-50); + + &:hover { + color: var(--primary); + } +} + +@media screen and (min-width: 768px) { + .fsdocs-source-link { + display: block; + } +} + +/* Search */ +::backdrop { + background-color: #020202; + opacity: 0.5; +} + +dialog { + background-color: var(--dialog-background-color); + margin: var(--spacing-700) auto; + padding: var(--spacing-100); + border: none; + opacity: 0; + visibility: hidden; + transition: all 0.2s ease-in-out; + border-radius: var(--radius); + width: var(--dialog-width); + + &[open] { + opacity: 1; + visibility: visible; + } + + & input[type=search] { + margin: 0; + display: block; + width: 100%; + padding: var(--spacing-200); + outline: 1px solid var(--primary); + border-radius: var(--radius); + border: none; + + &::placeholder { + font-size: var(--font-400); + } + } + + .empty { + color: var(--dialog-empty-color); + text-align: center; + font-size: var(--font-100); + margin: var(--spacing-100); + margin-bottom: 0; + } + + & ul { + overflow-y: auto; + max-height: calc(50vh - var(--spacing-700) - var(--spacing-700)); + list-style: none; + padding: 0; + + & li { + margin: 0; + border-bottom: 1px solid var(--header-border); + + &:hover { + & a, & a iconify-icon { + background-color: var(--dialog-link-hover-background-color); + color: var(--dialog-link-hover-color); + } + } + + & a { + display: flex; + padding: var(--spacing-300); + overflow-x: hidden; + color: var(--dialog-link-color); + + & iconify-icon { + color: var(--dialog-icon-color); + width: 24px; + margin-right: var(--spacing-200); + } + } + } + } +} + +/* Variables don't seem to work on ::backdrop */ +[data-theme=dark] { + ::backdrop { + opacity: 0.75; + } +} diff --git a/content/fsdocs-search.js b/content/fsdocs-search.js new file mode 100755 index 0000000..9e4c21d --- /dev/null +++ b/content/fsdocs-search.js @@ -0,0 +1,126 @@ +import Fuse from "https://esm.sh/fuse.js@7.0.0"; + +const searchBtn = document.querySelector("#search-btn"); + +function hideSearchBtn() { + // Hide search icon if we can't search in the first place. + searchBtn.style.display = 'none'; +} + +function debounce(mainFunction, delay) { + // Declare a variable called 'timer' to store the timer ID + let timer; + + // Return an anonymous function that takes in any number of arguments + return function (...args) { + // Clear the previous timer to prevent the execution of 'mainFunction' + clearTimeout(timer); + + // Set a new timer that will execute 'mainFunction' after the specified delay + timer = setTimeout(() => { + mainFunction(...args); + }, delay); + }; +} + +const root = document.documentElement.getAttribute("data-root"); +if (root && searchBtn) { + let fuse = null; + const searchIndexUrl = `${root}/index.json`; + fetch(searchIndexUrl, {}) + .then(response => response.json()) + .then(index => { + fuse = new Fuse(index, { + includeScore: true, + keys: ['uri', 'title', 'content', 'headings'], + includeMatches: true, + limit: 20, + ignoreLocation: true, + threshold: 0.6, + minMatchCharLength: 2, + ignoreFieldNorm: true, + shouldSort: true + }); + }) + .catch(() => { + hideSearchBtn(); + }) + + const searchDialog = document.querySelector("dialog"); + const empty = document.querySelector("dialog .empty"); + const resultsElement = document.querySelector("dialog ul"); + const searchBox = document.querySelector("dialog input[type=search]"); + + searchBtn.addEventListener("click", () => { + searchDialog.showModal(); + }) + + searchDialog.addEventListener("click", ev => { + if (ev.target.tagName === "DIALOG") { + searchBox.value = ''; + searchDialog.close() + } + }) + + function searchAux(searchTerm) { + if (!fuse) return; + + const results = fuse.search(searchTerm); + if (results.length === 0) { + clearResults(); + empty.textContent = "No results were found"; + } else { + if (location.hostname === 'localhost'){ + console.table(results); + } + + empty.style.display = 'none'; + const newResultNodes = + results + .map(result => { + const item = result.item; + const li = document.createElement("li"); + const a = document.createElement("a"); + a.setAttribute("href", item.uri); + const icon = document.createElement("iconify-icon"); + icon.setAttribute("width", "24"); + icon.setAttribute("height", "24"); + icon.setAttribute("icon", item.type === "content" ? "iconoir:page" : "bxs:file-doc") + a.append(icon, item.title); + li.appendChild(a); + return li; + }); + resultsElement.replaceChildren(...newResultNodes); + } + } + + const search = debounce(searchAux, 250); + + function clearResults() { + empty.style.display = 'block'; + resultsElement.replaceChildren(); + } + + searchBox.addEventListener('keyup', ev => { + ev.stopPropagation(); + const searchTerm = ev.target.value; + if (!searchTerm) { + empty.textContent = "Type something to start searching."; + clearResults(); + } else { + search(searchTerm); + } + }); + + window.addEventListener('keyup', ev => { + if (ev.key === 'Escape' && searchDialog.open) { + searchDialog.close(); + } + + if (ev.key === '/' && !searchDialog.open) { + searchDialog.showModal(); + } + }) +} else { + hideSearchBtn(); +} diff --git a/content/fsdocs-theme-set-dark.js b/content/fsdocs-theme-set-dark.js new file mode 100755 index 0000000..b6eeaba --- /dev/null +++ b/content/fsdocs-theme-set-dark.js @@ -0,0 +1,5 @@ +const prefersDark = window.matchMedia("@media (prefers-color-scheme: dark)").matches; +let currentTheme = localStorage.getItem('theme') ?? (prefersDark ? 'dark' : 'light'); +if (currentTheme === 'dark') { + window.document.documentElement.setAttribute("data-theme", 'dark'); +} diff --git a/content/fsdocs-theme-toggle.js b/content/fsdocs-theme-toggle.js new file mode 100755 index 0000000..5e32f9e --- /dev/null +++ b/content/fsdocs-theme-toggle.js @@ -0,0 +1,38 @@ +import {LitElement, html, css} from 'https://cdn.jsdelivr.net/gh/lit/dist@3/core/lit-core.min.js'; + +const prefersDark = window.matchMedia("@media (prefers-color-scheme: dark)").matches; +let currentTheme = localStorage.getItem('theme') ?? (prefersDark ? 'dark' : 'light'); + +export class ThemeToggle extends LitElement { + static properties = { + _theme: {state: true, type: String}, + }; + + constructor() { + super(); + this._theme = currentTheme; + } + + static styles = css` + :host { + cursor: pointer; + box-sizing: border-box; + transform: translateY(3px); + } + `; + + changeTheme() { + this._theme = this._theme === 'light' ? 'dark' : 'light'; + localStorage.setItem('theme', this._theme); + window.document.documentElement.setAttribute("data-theme", this._theme); + } + + render() { + const icon = this._theme === 'light' ? 'basil:moon-solid' : 'basil:sun-solid'; + return html` + + `; + } +} + +customElements.define('fsdocs-theme-toggle', ThemeToggle); diff --git a/content/fsdocs-theme.css b/content/fsdocs-theme.css new file mode 100755 index 0000000..cd0e6a9 --- /dev/null +++ b/content/fsdocs-theme.css @@ -0,0 +1 @@ +/* Override any variables here */ \ No newline at end of file diff --git a/content/fsdocs-theme.js b/content/fsdocs-theme.js new file mode 100755 index 0000000..eea7d52 --- /dev/null +++ b/content/fsdocs-theme.js @@ -0,0 +1,35 @@ +// Automatically scroll to the active aside menu item. +const mainMenu = document.getElementById('fsdocs-main-menu'); +function scrollToActiveItem(activeItem) { + const halfMainMenuHeight = mainMenu.offsetHeight / 2 + if(activeItem.offsetTop > halfMainMenuHeight){ + mainMenu.scrollTop = (activeItem.offsetTop - halfMainMenuHeight) - (activeItem.offsetHeight / 2); + } +} + +const activeItem = document.querySelector("aside .nav-item.active"); +if (activeItem && mainMenu) { + scrollToActiveItem(activeItem); +} + +function scrollToAndExpandSelectedMember() { + if (location.hash) { + const details = document.querySelector(`tr > td.fsdocs-member-usage:has(a[href='${location.hash}']) ~ td.fsdocs-member-xmldoc > details`); + details?.setAttribute('open', 'true'); + const header = document.querySelector(`a[href='${location.hash}']`); + header?.scrollIntoView({ behavior: 'instant'}); + } +} + +scrollToAndExpandSelectedMember(); +addEventListener('hashchange', scrollToAndExpandSelectedMember); + +if(location.pathname.startsWith('/reference/')) { + // Scroll to API Reference header + const navHeaders = document.querySelectorAll(".nav-header"); + for (const navHeader of navHeaders) { + if (navHeader.textContent && navHeader.textContent.trim() === 'API Reference') { + scrollToActiveItem(navHeader); + } + } +} \ No newline at end of file diff --git a/content/fsdocs-tips.js b/content/fsdocs-tips.js new file mode 100755 index 0000000..787e183 --- /dev/null +++ b/content/fsdocs-tips.js @@ -0,0 +1,59 @@ +let currentTip = null; +let currentTipElement = null; + +function hideTip(evt, name, unique) { + const el = document.getElementById(name); + el.style.display = "none"; + currentTip = null; +} + +function hideUsingEsc(e) { + hideTip(e, currentTipElement, currentTip); +} + +function showTip(evt, name, unique, owner) { + document.onkeydown = hideUsingEsc; + if (currentTip === unique) return; + currentTip = unique; + currentTipElement = name; + + const offset = 20; + let x = evt.clientX; + let y = evt.clientY + offset; + + const el = document.getElementById(name); + el.style.position = "absolute"; + el.style.display = "block"; + el.style.left = `${x}px`; + el.style.top = `${y}px`; + const maxWidth = document.documentElement.clientWidth - x - 16; + el.style.maxWidth = `${maxWidth}px`; + + const rect = el.getBoundingClientRect(); + // Move tooltip if it is out of sight + if(rect.bottom > window.innerHeight) { + y = y - el.clientHeight - offset; + el.style.top = `${y}px`; + } + + if (rect.right > window.innerWidth) { + x = y - el.clientWidth - offset; + el.style.left = `${x}px`; + const maxWidth = document.documentElement.clientWidth - x - 16; + el.style.maxWidth = `${maxWidth}px`; + } +} + +function Clipboard_CopyTo(value) { + const tempInput = document.createElement("input"); + tempInput.value = value; + document.body.appendChild(tempInput); + tempInput.select(); + document.execCommand("copy"); + document.body.removeChild(tempInput); +} + +window.showTip = showTip; +window.hideTip = hideTip; +// Used by API documentation +window.Clipboard_CopyTo = Clipboard_CopyTo; \ No newline at end of file diff --git a/content/img/github-pages-settings.png b/content/img/github-pages-settings.png new file mode 100755 index 0000000..a765770 Binary files /dev/null and b/content/img/github-pages-settings.png differ diff --git a/docs/index.fsx b/docs/index.fsx deleted file mode 100644 index 1546ae0..0000000 --- a/docs/index.fsx +++ /dev/null @@ -1,34 +0,0 @@ -(** -# BioFSharp.Visualization - -![Logo](./img/Logo_large.png) - -you can write markdown in these comment brackets `(** ... *)` -*) - -// and actual F# content in a literate script file -let a = 42 - -(** -include evaluations like this: -*) - -(***include-value: a***) - -(** -Include the compiled binaries of your project to use in the docs like this. -Make sure to load any external references via nuget. -*) -#r "nuget: BioFSharp, 2.0.0-preview.3" -#I @"..\src\BioFSharp.Visualization\bin\Release\netstandard2.0" -#r "BioFSharp.Visualization.dll" - -open BioFSharp.Visualization - -let o = BioTalk.helloBio "Kev" - -(***include-value: o***) - -(** -Read more about documentation with fsdocs here: https://fsprojects.github.io/FSharp.Formatting/ -*) \ No newline at end of file diff --git a/global.json b/global.json deleted file mode 100644 index 989a69c..0000000 --- a/global.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "sdk": { - "version": "8.0.100", - "rollForward": "latestMinor" - } -} \ No newline at end of file diff --git a/docs/img/Logo_large.png b/img/Logo_large.png similarity index 100% rename from docs/img/Logo_large.png rename to img/Logo_large.png diff --git a/docs/img/icon.png b/img/icon.png similarity index 100% rename from docs/img/icon.png rename to img/icon.png diff --git a/index.html b/index.html new file mode 100644 index 0000000..793e353 --- /dev/null +++ b/index.html @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + BioFSharp.XYZ + | BioFSharp.XYZ + + + + + + + + + + + + +
+
+ + + Header menu logo + BioFSharp.XYZ + +
+
+ + + + + +
+
+ +
+
+

BioFSharp.XYZ

+

Logo

+

you can write markdown in these comment brackets (** ... *)

+
// and actual F# content in a literate script file
+let a = 42
+
+

include evaluations like this:

+
42
+

Include the compiled binaries of your project to use in the docs like this. +Make sure to load any external references via nuget.

+
#r "nuget: BioFSharp, 2.0.0-preview.3"
+#I @"..\src\BioFSharp.XYZ\bin\Release\netstandard2.0"
+#r "BioFSharp.XYZ.dll"
+
+open BioFSharp.XYZ
+
+let o = BioTalk.helloBio "Kev"
+
+
No value returned by any evaluator
+

Read more about documentation with fsdocs here: https://fsprojects.github.io/FSharp.Formatting/

+ +
val a: int
+
namespace BioFSharp
+
val o: obj
+ +
+
+ + + +
+
    +

    Type something to start searching.

    +
    +
    + + + + + + + \ No newline at end of file diff --git a/index.json b/index.json new file mode 100644 index 0000000..91eadcc --- /dev/null +++ b/index.json @@ -0,0 +1 @@ +[{"uri":"https://BioFSharp.github.io/BioFSharp.XYZ/reference/biofsharp-xyz.html","title":"BioFSharp.XYZ","content":"BioTalk","headings":[],"type":"apiDocs"},{"uri":"https://BioFSharp.github.io/BioFSharp.XYZ/reference/biofsharp-xyz-biotalk.html","title":"BioTalk","content":"BioTalk \n \nBioTalk.helloBio \nhelloBio","headings":[],"type":"apiDocs"},{"uri":"https://BioFSharp.github.io/BioFSharp.XYZ/reference/biofsharp-xyz-biotalk.html#helloBio","title":"BioTalk.helloBio","content":"BioTalk.helloBio \nhelloBio \n","headings":[],"type":"apiDocs"},{"uri":"https://BioFSharp.github.io/BioFSharp.XYZ/index.html","title":"BioFSharp.XYZ\n","content":"BioFSharp.XYZ\n\nyou can write markdown in these comment brackets (** ... *)\n// and actual F# content in a literate script file\nlet a = 42\n\ninclude evaluations like this:\n42\nInclude the compiled binaries of your project to use in the docs like this.\nMake sure to load any external references via nuget.\n#r \u0026quot;nuget: BioFSharp, 2.0.0-preview.3\u0026quot;\n#I @\u0026quot;..\\src\\BioFSharp.XYZ\\bin\\Release\\netstandard2.0\u0026quot;\n#r \u0026quot;BioFSharp.XYZ.dll\u0026quot;\n\nopen BioFSharp.XYZ\n\nlet o = BioTalk.helloBio \u0026quot;Kev\u0026quot;\n\nNo value returned by any evaluator\nRead more about documentation with fsdocs here: https://fsprojects.github.io/FSharp.Formatting/\n","headings":["BioFSharp.XYZ"],"type":"content"}] \ No newline at end of file diff --git a/reference/biofsharp-xyz-biotalk.html b/reference/biofsharp-xyz-biotalk.html new file mode 100644 index 0000000..7b8087e --- /dev/null +++ b/reference/biofsharp-xyz-biotalk.html @@ -0,0 +1,224 @@ + + + + + + + + + + + + + + + + + + BioTalk (BioFSharp.XYZ) | BioFSharp.XYZ + + + + + + + + + + + + +
    +
    + + + Header menu logo + BioFSharp.XYZ + +
    +
    + + + + + +
    +
    + +
    +
    +
    +

    + BioTalk Module +

    + +
    +
    +

    + +

    +
    +
    +
    +

    + Functions and values +

    + + + + + + + + + + + + + +
    + Function or value + + Description +
    +
    + +

    + + + helloBio name + + +

    +
    +
    +
    + Full Usage: + helloBio name +
    +
    + Parameters: +
      + + + name + + : + char seq + +
      +
    +
    + + Returns: + string + +
    +
    +
    +
    +
    +
    +
    + + name + + : + char seq +
    +
    +
    +
    +
    + + Returns: + + string +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    + + + +
    +
      +

      Type something to start searching.

      +
      +
      + + + + + + + \ No newline at end of file diff --git a/reference/biofsharp-xyz.html b/reference/biofsharp-xyz.html new file mode 100644 index 0000000..6d0e90d --- /dev/null +++ b/reference/biofsharp-xyz.html @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + BioFSharp.XYZ | BioFSharp.XYZ + + + + + + + + + + + + +
      +
      + + + Header menu logo + BioFSharp.XYZ + +
      +
      + + + + + +
      +
      + +
      +
      +
      +

      + BioFSharp.XYZ Namespace +

      +
      + + + + + + + + + + + + + +
      + Modules + + Description +
      +

      + + + BioTalk + + +

      +
      +
      + + + + + +

      + +

      +
      +
      +
      + +
      +
      + + + +
      +
        +

        Type something to start searching.

        +
        +
        + + + + + + + \ No newline at end of file diff --git a/reference/index.html b/reference/index.html new file mode 100644 index 0000000..b8e0a25 --- /dev/null +++ b/reference/index.html @@ -0,0 +1,143 @@ + + + + + + + + + + + + + + + + + + BioFSharp.XYZ (API Reference) | BioFSharp.XYZ + + + + + + + + + + + + +
        +
        + + + Header menu logo + BioFSharp.XYZ + +
        +
        + + + + + +
        +
        + +
        +
        +
        +

        + API Reference +

        +

        + Available Namespaces: +

        + + + + + + + + + + + + + +
        + Namespace + + Description +
        + + BioFSharp.XYZ + +
        +
        + +
        +
        + + + +
        +
          +

          Type something to start searching.

          +
          +
          + + + + + + + \ No newline at end of file diff --git a/src/BioFSharp.Visualization/BioFSharp.Visualization.fsproj b/src/BioFSharp.Visualization/BioFSharp.Visualization.fsproj deleted file mode 100644 index cf14b31..0000000 --- a/src/BioFSharp.Visualization/BioFSharp.Visualization.fsproj +++ /dev/null @@ -1,42 +0,0 @@ - - - - netstandard2.0 - true - true - snupkg - - - - - - - - - - - - - - - - - - - MIT - https://BioFSharp.github.io/BioFSharp.Visualization/ - icon.png - bioinformatics F# fsharp statistic biostatistics datascience - https://github.com/BioFSharp/BioFSharp.Visualization - git - https://github.com/BioFSharp/BioFSharp.Visualization/blob/main/LICENSE - https://github.com/BioFSharp/BioFSharp.Visualization/blob/main/RELEASE_NOTES.md - - - - - - - - - diff --git a/src/BioFSharp.Visualization/Logo.fs b/src/BioFSharp.Visualization/Logo.fs deleted file mode 100644 index 117dae4..0000000 --- a/src/BioFSharp.Visualization/Logo.fs +++ /dev/null @@ -1,179 +0,0 @@ -namespace BioFSharp.Visualization - -open BioFSharp -open BioFSharp.Nucleotides -open BioFSharp.AminoAcids -open Plotly.NET -open Plotly.NET.LayoutObjects - -module Logo = - - // https://weblogo.threeplusone.com/manual.html - module ColorThemes = - - type LogoTheme<'T> = { - Name: string - ColorKeys: (string*Color) array - ColorMap: ('T*Color) array - } with - static member create name colorKeys colorMap = - { Name = name; ColorKeys = colorKeys; ColorMap = colorMap } - - - module Nucleotides = - - let classic = - LogoTheme.create - "Classic" - [| - "A", Color.fromKeyword Green - "C", Color.fromKeyword Blue - "G", Color.fromKeyword Orange - "T+U", Color.fromKeyword Red - |] - [| - Nucleotides.A, Color.fromKeyword Green - Nucleotides.C, Color.fromKeyword Blue - Nucleotides.G, Color.fromKeyword Orange - Nucleotides.T, Color.fromKeyword Red - Nucleotides.U, Color.fromKeyword Red - |] - - let basePairing = - LogoTheme.create - "Base Pairing" - [| - "2 Watson-Crick hydrogen bonds", Color.fromKeyword DarkOrange - "3 Watson-Crick hydrogen bonds", Color.fromKeyword Blue - |] - [| - (Nucleotides.T, Color.fromKeyword DarkOrange) - (Nucleotides.A, Color.fromKeyword DarkOrange) - (Nucleotides.U, Color.fromKeyword DarkOrange) - (Nucleotides.C, Color.fromKeyword Blue) - (Nucleotides.G, Color.fromKeyword Blue) - |] - - module AminoAcids = - - let hydrophobicity = - LogoTheme.create - "Hydrophobicity" - [| - "Hydrophilic", Color.fromKeyword Blue - "Hydrophobic", Color.fromKeyword Green - "Neutral", Color.fromKeyword Black - |] - [| - // Hydrophilic - Arg, Color.fromKeyword Blue - Lys, Color.fromKeyword Blue - Asp, Color.fromKeyword Blue - Glu, Color.fromKeyword Blue - Asn, Color.fromKeyword Blue - Gln, Color.fromKeyword Blue - // Hydrophobic - Tyr, Color.fromKeyword Green - Val, Color.fromKeyword Green - Met, Color.fromKeyword Green - Cys, Color.fromKeyword Green - Leu, Color.fromKeyword Green - Phe, Color.fromKeyword Green - Ile, Color.fromKeyword Green - Trp, Color.fromKeyword Green - // Neutral - Ser, Color.fromKeyword Black - Gly, Color.fromKeyword Black - His, Color.fromKeyword Black - Thr, Color.fromKeyword Black - Ala, Color.fromKeyword Black - Pro, Color.fromKeyword Black - |] - - let chemistry = - LogoTheme.create - "Chemistry" - [| - "Polar", Color.fromKeyword Green - "Neutral", Color.fromKeyword Purple - "Basic", Color.fromKeyword Blue - "Acidic", Color.fromKeyword Red - "Hydrophobic", Color.fromKeyword Black - |] - [| - // polar - Gly, Color.fromKeyword Green - Ser, Color.fromKeyword Green - Thr, Color.fromKeyword Green - Tyr, Color.fromKeyword Green - Cys, Color.fromKeyword Green - // neutral - Gln, Color.fromKeyword Purple - Asn, Color.fromKeyword Purple - // basic - Lys, Color.fromKeyword Blue - Arg, Color.fromKeyword Blue - His, Color.fromKeyword Blue - // acidic - Asp, Color.fromKeyword Red - Glu, Color.fromKeyword Red - // hydrophobic - Ala, Color.fromKeyword Black - Val, Color.fromKeyword Black - Leu, Color.fromKeyword Black - Ile, Color.fromKeyword Black - Pro, Color.fromKeyword Black - Trp, Color.fromKeyword Black - Phe, Color.fromKeyword Black - Met, Color.fromKeyword Black - |] - - let charge = - LogoTheme.create - "Charge" - [| - "Positive", Color.fromKeyword Blue - "Negative", Color.fromKeyword Red - |] - [| - // positive - Lys, Color.fromKeyword Blue - Arg, Color.fromKeyword Blue - His, Color.fromKeyword Blue - - // negative - Asp, Color.fromKeyword Red - Glu, Color.fromKeyword Red - |] - - open SVG - - let letterPaths = - Map [ - (BioItem.name Nucleotide.A), "M 10.72 14 L 8.92 14 L 7.84 10.56 L 2.9 10.56 L 1.84 14 L 0 14 L 4.62 0 L 6.08 0 L 10.72 14 Z M 4.98 3.9 L 3.38 9.02 L 7.34 9.02 L 5.72 3.9 Q 5.48 3.12 5.34 2.54 Q 5.26 3.02 4.98 3.9 Z" - (BioItem.name Nucleotide.T), "M 5.74 14 L 4.02 14 L 4.02 1.66 L 0 1.66 L 0 0 L 9.76 0 L 9.76 1.66 L 5.74 1.66 L 5.74 14 Z" - (BioItem.name Nucleotide.G), "M 8.925 2.446 L 7.405 3.326 Q 6.965 2.526 6.425 2.066 Q 5.885 1.606 5.045 1.606 Q 3.905 1.606 3.145 2.506 Q 2.385 3.406 2.095 4.616 Q 1.805 5.826 1.805 7.246 Q 1.805 9.626 2.625 11.256 Q 3.445 12.886 5.045 12.886 Q 6.225 12.886 6.905 12.016 Q 7.585 11.146 7.585 9.706 L 7.585 9.046 L 5.065 9.046 L 5.065 7.466 L 9.385 7.466 L 9.385 9.146 Q 9.385 11.666 8.165 13.076 Q 6.945 14.486 5.045 14.486 Q 3.345 14.486 2.175 13.416 Q 1.005 12.346 0.505 10.756 Q 0.005 9.166 0.005 7.246 Q 0.005 4.226 1.305 2.116 Q 2.605 0.006 5.045 0.006 Q 6.565 0.006 7.445 0.666 Q 8.325 1.326 8.925 2.446 Z" - (BioItem.name Nucleotide.C), "M 4.54 1.242 L 3.78 1.652 Q 3.56 1.242 3.3 1.022 Q 3.04 0.802 2.63 0.802 Q 2.17 0.802 1.82 1.057 Q 1.47 1.312 1.275 1.732 Q 1.08 2.152 0.985 2.627 Q 0.89 3.102 0.89 3.622 Q 0.89 4.372 1.065 4.987 Q 1.24 5.602 1.645 6.022 Q 2.05 6.442 2.63 6.442 Q 3.43 6.442 3.85 5.552 L 4.62 5.842 Q 4.36 6.462 3.865 6.852 Q 3.37 7.242 2.63 7.242 Q 2.08 7.242 1.625 7.037 Q 1.17 6.832 0.875 6.487 Q 0.58 6.142 0.38 5.672 Q 0.18 5.202 0.09 4.692 Q 0 4.182 0 3.622 Q 0 2.662 0.26 1.867 Q 0.52 1.072 1.13 0.537 Q 1.74 0.002 2.63 0.002 Q 3.96 0.002 4.54 1.242 Z" - (BioItem.name Nucleotide.U), "M 0 2 L 0 8 C 0 10 4 10 4 8 L 4 2 L 3 2 L 3 8 C 3 9 1 9 1 8 L 1 2 Z" - - (BioItem.name AminoAcid.Ala), "M 10.72 14 L 8.92 14 L 7.84 10.56 L 2.9 10.56 L 1.84 14 L 0 14 L 4.62 0 L 6.08 0 L 10.72 14 Z M 4.98 3.9 L 3.38 9.02 L 7.34 9.02 L 5.72 3.9 Q 5.48 3.12 5.34 2.54 Q 5.26 3.02 4.98 3.9 Z" - (BioItem.name AminoAcid.Ile), "M 0.95 0.0 Q 1.05 0.0565 0.95 0.113 L 0.606 0.113 L 0.606 0.887 L .95 0.887 Q 1.05 0.9435 .95 1.0 L 0.05 1.0 Q -0.05 0.9435 .05 0.887 L 0.394 0.887 L 0.394 0.113 L 0.05 0.113 Q -0.05 0.0565 0.05 0.0 L 0.95 0.0 Z" - (BioItem.name AminoAcid.Leu), "M 8.38 14 L 0 14 L 0 0 L 1.72 0 L 1.72 12.34 L 8.38 12.34 L 8.38 14 Z" - (BioItem.name AminoAcid.Met), "M 1.58 14 L 0 14 L 0 0 L 1.86 0 L 3.96 8.38 Q 4.18 9.26 4.26 9.84 Q 4.32 9.26 4.56 8.38 L 6.68 0 L 8.48 0 L 8.48 14 L 6.9 14 L 6.9 5.22 Q 6.9 4.38 6.94 3.94 Q 6.9 4.16 6.64 5.22 L 4.38 14 L 4.1 14 L 1.84 5.22 Q 1.6 4.16 1.54 3.94 Q 1.58 4.82 1.58 5.22 L 1.58 14 Z" - (BioItem.name AminoAcid.Val), "M 6.06 14 L 4.62 14 L 0 0 L 1.86 0 L 5.08 10.38 Q 5.2 10.76 5.34 11.5 Q 5.48 10.76 5.6 10.38 L 8.84 0 L 10.68 0 L 6.06 14 Z" - (BioItem.name AminoAcid.Phe), "M 1.72 14 L 0 14 L 0 0 L 8.78 0 L 8.78 1.64 L 1.72 1.64 L 1.72 5.94 L 6.66 5.94 L 6.66 7.58 L 1.72 7.58 L 1.72 14 Z" - (BioItem.name AminoAcid.Trp), "M 3.6 14 L 2.2 14 L 0 0 L 1.64 0 L 2.94 9.24 Q 2.96 9.4 2.99 9.71 Q 3.02 10.02 3.04 10.14 Q 3.1 9.68 3.2 9.24 L 4.8 0 L 6 0 L 7.6 9.14 Q 7.66 9.46 7.74 9.96 Q 7.76 9.56 7.84 9.16 L 9.1 0 L 10.76 0 L 8.56 14 L 7.16 14 L 5.52 4.82 Q 5.5 4.68 5.45 4.37 Q 5.4 4.06 5.38 3.88 Q 5.3 4.52 5.24 4.78 L 3.6 14 Z" - (BioItem.name AminoAcid.Tyr), "M 4.9 6.78 L 7.92 0 L 9.76 0 L 5.76 8.48 L 5.76 14 L 4.04 14 L 4.04 8.48 L 0 0 L 1.92 0 L 4.9 6.78 Z" - (BioItem.name AminoAcid.Asn), "M 1.68 14 L 0 14 L 0 0 L 1.7 0 L 6.48 9.82 Q 6.8 10.44 6.84 10.56 Q 6.82 10.18 6.82 9.8 L 6.82 0 L 8.48 0 L 8.48 14 L 6.82 14 L 2.02 4.3 Q 1.88 4.06 1.64 3.54 Q 1.68 3.84 1.68 4.3 L 1.68 14 Z" - (BioItem.name AminoAcid.Cys), "M 4.54 1.242 L 3.78 1.652 Q 3.56 1.242 3.3 1.022 Q 3.04 0.802 2.63 0.802 Q 2.17 0.802 1.82 1.057 Q 1.47 1.312 1.275 1.732 Q 1.08 2.152 0.985 2.627 Q 0.89 3.102 0.89 3.622 Q 0.89 4.372 1.065 4.987 Q 1.24 5.602 1.645 6.022 Q 2.05 6.442 2.63 6.442 Q 3.43 6.442 3.85 5.552 L 4.62 5.842 Q 4.36 6.462 3.865 6.852 Q 3.37 7.242 2.63 7.242 Q 2.08 7.242 1.625 7.037 Q 1.17 6.832 0.875 6.487 Q 0.58 6.142 0.38 5.672 Q 0.18 5.202 0.09 4.692 Q 0 4.182 0 3.622 Q 0 2.662 0.26 1.867 Q 0.52 1.072 1.13 0.537 Q 1.74 0.002 2.63 0.002 Q 3.96 0.002 4.54 1.242 Z" - (BioItem.name AminoAcid.Gln), "M 7.58 13.381 L 8.68 15.041 L 7.46 15.901 L 6.32 14.201 Q 5.6 14.481 4.76 14.481 Q 3.5 14.481 2.55 13.861 Q 1.6 13.241 1.06 12.181 Q 0.52 11.121 0.26 9.881 Q 0 8.641 0 7.241 Q 0 5.841 0.26 4.601 Q 0.52 3.361 1.06 2.301 Q 1.6 1.241 2.55 0.621 Q 3.5 0.001 4.76 0.001 Q 6.02 0.001 6.97 0.621 Q 7.92 1.241 8.47 2.301 Q 9.02 3.361 9.28 4.601 Q 9.54 5.841 9.54 7.241 Q 9.54 11.481 7.58 13.381 Z M 5.38 12.801 L 4.42 11.381 L 5.68 10.521 L 6.58 11.881 Q 7.74 10.361 7.74 7.241 Q 7.74 4.821 7.01 3.211 Q 6.28 1.601 4.76 1.601 Q 3.72 1.601 3.03 2.471 Q 2.34 3.341 2.06 4.561 Q 1.78 5.781 1.78 7.241 Q 1.78 9.661 2.51 11.271 Q 3.24 12.881 4.76 12.881 Q 5.12 12.881 5.38 12.801 Z" - (BioItem.name AminoAcid.Ser), "M 0 5.692 L 0.8 5.402 Q 1 5.882 1.39 6.167 Q 1.78 6.452 2.27 6.452 Q 2.82 6.452 3.14 6.147 Q 3.46 5.842 3.46 5.282 Q 3.46 4.372 2.05 3.762 Q 1.65 3.592 1.38 3.437 Q 1.11 3.282 0.815 3.037 Q 0.52 2.792 0.365 2.457 Q 0.21 2.122 0.21 1.702 Q 0.21 0.982 0.74 0.492 Q 1.27 0.002 2.15 0.002 Q 2.86 0.002 3.365 0.347 Q 3.87 0.692 4.02 1.242 L 3.23 1.502 Q 3.1 1.192 2.81 0.992 Q 2.52 0.792 2.12 0.792 Q 1.65 0.792 1.37 1.037 Q 1.09 1.282 1.09 1.702 Q 1.09 1.942 1.195 2.132 Q 1.3 2.322 1.53 2.482 Q 1.76 2.642 1.945 2.742 Q 2.13 2.842 2.48 2.992 Q 2.86 3.162 3.135 3.332 Q 3.41 3.502 3.715 3.772 Q 4.02 4.042 4.18 4.417 Q 4.34 4.792 4.34 5.252 Q 4.34 6.182 3.75 6.712 Q 3.16 7.242 2.23 7.242 Q 1.43 7.242 0.825 6.802 Q 0.22 6.362 0 5.692 Z" - (BioItem.name AminoAcid.Thr), "M 5.74 14 L 4.02 14 L 4.02 1.66 L 0 1.66 L 0 0 L 9.76 0 L 9.76 1.66 L 5.74 1.66 L 5.74 14 Z" - (BioItem.name AminoAcid.Asp), "M 3.22 14.001 L 0 14.001 L 0 0.001 L 3.3 0.001 Q 4.82 0.001 5.97 0.601 Q 7.12 1.201 7.77 2.221 Q 8.42 3.241 8.73 4.441 Q 9.04 5.641 9.04 7.001 Q 9.04 8.301 8.75 9.471 Q 8.46 10.641 7.83 11.691 Q 7.2 12.741 6.01 13.371 Q 4.82 14.001 3.22 14.001 Z M 1.74 1.581 L 1.74 12.421 L 3.28 12.421 Q 4.38 12.421 5.18 11.951 Q 5.98 11.481 6.41 10.661 Q 6.84 9.841 7.04 8.941 Q 7.24 8.041 7.24 7.001 Q 7.24 4.721 6.31 3.151 Q 5.38 1.581 3.5 1.581 L 1.74 1.581 Z" - (BioItem.name AminoAcid.Glu), "M 8.62 14 L 0 14 L 0 0 L 8.2 0 L 8.2 1.64 L 1.72 1.64 L 1.72 5.94 L 6.14 5.94 L 6.14 7.58 L 1.72 7.58 L 1.72 12.36 L 8.62 12.36 L 8.62 14 Z" - (BioItem.name AminoAcid.Arg), "M 5.64 7.88 L 8.64 14.02 L 6.74 14.02 L 3.82 8.02 L 1.72 8.02 L 1.72 14.02 L 0 14.02 L 0 0.02 L 4.3 0.02 Q 6.64 0.02 7.67 1.15 Q 8.7 2.28 8.7 4 Q 8.7 5.36 7.95 6.45 Q 7.2 7.54 5.64 7.88 Z M 4.34 1.6 L 1.72 1.6 L 1.72 6.44 L 4.34 6.44 Q 5.74 6.44 6.37 5.75 Q 7 5.06 7 4.04 Q 7 3.08 6.38 2.34 Q 5.76 1.6 4.34 1.6 Z" - (BioItem.name AminoAcid.His), "M 1.72 14 L 0 14 L 0 0 L 1.72 0 L 1.72 5.92 L 6.76 5.92 L 6.76 0 L 8.48 0 L 8.48 14 L 6.76 14 L 6.76 7.56 L 1.72 7.56 L 1.72 14 Z" - (BioItem.name AminoAcid.Lys), "M 9.32 14 L 7.34 14 L 3.32 6.38 L 1.72 8.4 L 1.72 14 L 0 14 L 0 0 L 1.72 0 L 1.72 6.02 L 6.4 0 L 8.38 0 L 4.5 4.9 L 9.32 14 Z" - (BioItem.name AminoAcid.Gly), "M 8.925 2.446 L 7.405 3.326 Q 6.965 2.526 6.425 2.066 Q 5.885 1.606 5.045 1.606 Q 3.905 1.606 3.145 2.506 Q 2.385 3.406 2.095 4.616 Q 1.805 5.826 1.805 7.246 Q 1.805 9.626 2.625 11.256 Q 3.445 12.886 5.045 12.886 Q 6.225 12.886 6.905 12.016 Q 7.585 11.146 7.585 9.706 L 7.585 9.046 L 5.065 9.046 L 5.065 7.466 L 9.385 7.466 L 9.385 9.146 Q 9.385 11.666 8.165 13.076 Q 6.945 14.486 5.045 14.486 Q 3.345 14.486 2.175 13.416 Q 1.005 12.346 0.505 10.756 Q 0.005 9.166 0.005 7.246 Q 0.005 4.226 1.305 2.116 Q 2.605 0.006 5.045 0.006 Q 6.565 0.006 7.445 0.666 Q 8.325 1.326 8.925 2.446 Z" - (BioItem.name AminoAcid.Pro), "M 1.72 14.001 L 0 14.001 L 0 0.001 L 4.32 0.001 Q 5.54 0.001 6.45 0.361 Q 7.36 0.721 7.86 1.331 Q 8.36 1.941 8.6 2.661 Q 8.84 3.381 8.84 4.201 Q 8.84 5.861 7.71 7.121 Q 6.58 8.381 4.32 8.381 L 1.72 8.381 L 1.72 14.001 Z M 1.72 1.581 L 1.72 6.781 L 4.44 6.781 Q 5.82 6.781 6.48 6.021 Q 7.14 5.261 7.14 4.201 Q 7.14 3.161 6.51 2.371 Q 5.88 1.581 4.44 1.581 L 1.72 1.581 Z" - ] diff --git a/src/BioFSharp.Visualization/PlotlyExtensions/ChartExtensions.fs b/src/BioFSharp.Visualization/PlotlyExtensions/ChartExtensions.fs deleted file mode 100644 index 12650f7..0000000 --- a/src/BioFSharp.Visualization/PlotlyExtensions/ChartExtensions.fs +++ /dev/null @@ -1,79 +0,0 @@ -namespace BioFSharp.Visualization.Plotly - -open BioFSharp.Visualization -open Plotly.NET -open BioFSharp - -module ChartExtensions = - - open Utils - - type Chart with - - static member SequenceLogo( - sequences: #seq<#seq>, - ?NucleotideColorScheme: StyleParam.SequenceLogoNucleotideColorScheme, - ?OutlineColor: Color, - ?Outline: Line - ) = - - let theme = - defaultArg NucleotideColorScheme StyleParam.SequenceLogoNucleotideColorScheme.Classic - |> getNucleotideColorMap - - let legendShapes = LogoUtils.createLogoLegendShapes(theme = theme, ?OutlineColor = OutlineColor, ?Outline = Outline) - - let sequences = sequences |> Array.ofSeq |> Array.map Array.ofSeq - - let sequenceIndices = getSequenceIndices sequences - - Chart.Point([]) - |> Chart.withShapes ( - sequenceIndices - |> Array.map (fun index -> - LogoUtils.createMotifShapes( - sequenceIndex = index, - colorLookup = (lookupNucleotideColor theme), - motifPosition = (getNucleotideMotifPosition index sequences), - ?OutlineColor = OutlineColor, - ?Outline = Outline - ) - ) - |> Array.concat - ) - |> Chart.withShapes(legendShapes, Append=true) - - static member SequenceLogo( - sequences: #seq<#seq>, - ?AminoAcidColorScheme: StyleParam.SequenceLogoAminoAcidColorScheme, - ?OutlineColor: Color, - ?Outline: Line - ) = - - let theme = - defaultArg AminoAcidColorScheme StyleParam.SequenceLogoAminoAcidColorScheme.Hydrophobicity - |> getAminoAcidColorMap - - let legendShapes = LogoUtils.createLogoLegendShapes(theme = theme, ?OutlineColor = OutlineColor, ?Outline = Outline) - - let sequences = sequences |> Array.ofSeq |> Array.map Array.ofSeq - - let sequenceIndices = getSequenceIndices sequences - - Chart.Point([]) - |> Chart.withShapes ( - sequenceIndices - |> Array.map (fun index -> - LogoUtils.createMotifShapes( - sequenceIndex = index, - colorLookup = (lookupAminoAcidColor theme), - motifPosition = (getAminoAcidMotifPosition index sequences), - ?OutlineColor = OutlineColor, - ?Outline = Outline - ) - ) - |> Array.concat - ) - |> Chart.withShapes(legendShapes, Append=true) - - diff --git a/src/BioFSharp.Visualization/PlotlyExtensions/StyleParam.fs b/src/BioFSharp.Visualization/PlotlyExtensions/StyleParam.fs deleted file mode 100644 index 4e2b1ce..0000000 --- a/src/BioFSharp.Visualization/PlotlyExtensions/StyleParam.fs +++ /dev/null @@ -1,21 +0,0 @@ -namespace BioFSharp.Visualization.Plotly - -open BioFSharp.Visualization - -open System -open Plotly.NET -open BioFSharp -open BioFSharp.Visualization.Logo.ColorThemes - -module StyleParam = - - type SequenceLogoNucleotideColorScheme = - | Custom of LogoTheme - | Classic - | BasePairing - - type SequenceLogoAminoAcidColorScheme = - | Custom of LogoTheme - | Hydrophobicity - | Chemistry - | Charge \ No newline at end of file diff --git a/src/BioFSharp.Visualization/PlotlyExtensions/Utils.fs b/src/BioFSharp.Visualization/PlotlyExtensions/Utils.fs deleted file mode 100644 index c554729..0000000 --- a/src/BioFSharp.Visualization/PlotlyExtensions/Utils.fs +++ /dev/null @@ -1,142 +0,0 @@ -namespace BioFSharp.Visualization.Plotly - -open Plotly.NET -open Plotly.NET.LayoutObjects -open BioFSharp -open BioFSharp.Visualization -open BioFSharp.Visualization.Logo -open BioFSharp.Visualization.SVG - -module Utils = - - let internal getNucleotideColorMap (m: StyleParam.SequenceLogoNucleotideColorScheme) = - match m with - | StyleParam.SequenceLogoNucleotideColorScheme.Custom table -> table - | StyleParam.SequenceLogoNucleotideColorScheme.Classic -> ColorThemes.Nucleotides.classic - | StyleParam.SequenceLogoNucleotideColorScheme.BasePairing -> ColorThemes.Nucleotides.basePairing - - let internal getAminoAcidColorMap (m: StyleParam.SequenceLogoAminoAcidColorScheme) = - match m with - | StyleParam.SequenceLogoAminoAcidColorScheme.Custom table -> table - | StyleParam.SequenceLogoAminoAcidColorScheme.Hydrophobicity -> ColorThemes.AminoAcids.hydrophobicity - | StyleParam.SequenceLogoAminoAcidColorScheme.Chemistry -> ColorThemes.AminoAcids.chemistry - | StyleParam.SequenceLogoAminoAcidColorScheme.Charge -> ColorThemes.AminoAcids.charge - - let internal lookupNucleotideColor (theme: ColorThemes.LogoTheme) (nuc: Nucleotides.Nucleotide) = - theme.ColorMap - |> Array.tryFind (fun (n, _) -> n = nuc) - |> Option.map snd - |> Option.defaultValue (Color.fromKeyword Gray) - - let internal lookupAminoAcidColor (theme: ColorThemes.LogoTheme) (aa: AminoAcids.AminoAcid) = - theme.ColorMap - |> Array.tryFind (fun (a, _) -> a = aa) - |> Option.map snd - |> Option.defaultValue (Color.fromKeyword Gray) - - let internal getSequenceIndices (sequences: #seq<#seq<#IBioItem*float>>) = - let maxLength = - sequences - |> Seq.map Seq.length - |> Seq.max - [|1 .. maxLength|] - - let internal getMotifPosition (index: int) (sequences: #seq<#seq<#IBioItem*float>>) = - sequences - |> Seq.choose (Seq.tryItem (index - 1)) - |> Seq.sortBy snd - |> Seq.map (fun (item, value) -> item, value) - |> Array.ofSeq - - let internal getNucleotideMotifPosition (index: int) (sequences: #seq<#seq>) = - sequences |> getMotifPosition index - - let internal getAminoAcidMotifPosition (index: int) (sequences: #seq<#seq>) = - sequences |> getMotifPosition index - - type LogoUtils = - - static member createLogoLegendShapes ( - theme:ColorThemes.LogoTheme<_>, - ?OutlineColor: Color, - ?Outline: Line - ) = - - let outline = - Outline - |> Option.defaultValue (Plotly.NET.Line.init ()) - |> Plotly.NET.Line.style ( - ?Color = OutlineColor, - Width = 0. - ) - - theme.ColorKeys - |> Array.map (fun key -> - Shape.init( - FillColor = snd key, - Name = fst key, - ShowLegend = true, - LegendGroup = theme.Name, - LegendGroupTitle = Title.init($"Logo Theme: {theme.Name}"), - ShapeType = StyleParam.ShapeType.Circle, - Line = outline, - X0 = 1., - Y0 = 0., - X1 = 1., - Y1 = 0. - ) - ) - - static member createMotifShapes ( - sequenceIndex: int, - colorLookup: #IBioItem -> Color, - motifPosition: #seq<#IBioItem*float>, - ?OutlineColor: Color, - ?Outline: Line - ) = - - let outline = - Outline - |> Option.defaultValue (Plotly.NET.Line.init ()) - |> Plotly.NET.Line.style ( - ?Color = OutlineColor - ) - - let x = float sequenceIndex - let mutable currentPosBottom = 0.0 - let mutable currentNegTop = 0.0 - - motifPosition - |> Seq.map (fun (letter, y) -> - let path = - Map.tryFind (BioItem.name letter) letterPaths - |> fun x -> - if x.IsNone then printfn $"wtf {letter}" - x - |> Option.defaultValue "" - |> SVGPath - |> SVGPath.normalize - if y < 0 then - // letter should stack below x axis - let top = currentNegTop - let bottom = currentNegTop + y - currentNegTop <- currentNegTop + y - let svg = - path - |> SVGPath.reposition (x - 0.5) (x + 0.5) bottom top - Shape.init( - Path = SVGPath.toString svg, - FillColor = colorLookup letter, - Line = outline - ) - else - // letter should stack above x axis - let bottom = currentPosBottom - currentPosBottom <- bottom + y - let top = bottom + y - let svg = - path - |> SVGPath.reposition (x - 0.5) (x + 0.5) bottom top - Shape.init(Path = SVGPath.toString svg, FillColor = colorLookup letter, Line = outline) - ) - |> Seq.toArray \ No newline at end of file diff --git a/src/BioFSharp.Visualization/SVG.fs b/src/BioFSharp.Visualization/SVG.fs deleted file mode 100644 index dd80477..0000000 --- a/src/BioFSharp.Visualization/SVG.fs +++ /dev/null @@ -1,224 +0,0 @@ -namespace BioFSharp.Visualization - -module SVG = - - type InvertDirection = - | X - | Y - | XY - - type Coordinate2D(x: float, y: float) = - member this.X = x - member this.Y = y - - static member normalizeBy (minx: float) (maxx: float) (miny: float) (maxy: float) (c: Coordinate2D) = - Coordinate2D((c.X-minx) / (maxx - minx), (c.Y-miny) / (maxy - miny)) - - static member invert (direction: InvertDirection) (c: Coordinate2D) = - match direction with - | X -> Coordinate2D(-c.X, c.Y) - | Y -> Coordinate2D(c.X, -c.Y) - | XY -> Coordinate2D(-c.X, -c.Y) - - type SVGPathSegment = - | M of XY: Coordinate2D - | L of XY: Coordinate2D - | Q of XY1: Coordinate2D * XY: Coordinate2D - | C of XY1: Coordinate2D * XY2: Coordinate2D * XY: Coordinate2D - | Z - - static member toString (s: SVGPathSegment) = - match s with - | M(c) -> sprintf "M %f %f" c.X c.Y - | L(c) -> sprintf "L %f %f" c.X c.Y - | Q(c1, c) -> sprintf "Q %f %f %f %f" c1.X c1.Y c.X c.Y - | C(c1, c2, c) -> sprintf "C %f %f %f %f %f %f" c1.X c1.Y c2.X c2.Y c.X c.Y - | Z -> "Z" - - static member getMaxCoords (s: SVGPathSegment) = - match s with - | M(c) -> (c.X, c.Y) - | L(c) -> (c.X, c.Y) - | Q(c1, c) -> (max c1.X c.X , max c1.Y c.Y) - | C(c1, c2, c) -> (max c1.X (max c2.X c.X) , max c1.Y (max c2.Y c.Y)) - | Z -> (0., 0.) - - static member getMinCoords (s: SVGPathSegment) = - match s with - | M(c) -> (c.X, c.Y) - | L(c) -> (c.X, c.Y) - | Q(c1, c) -> (min c1.X c.X , min c1.Y c.Y) - | C(c1, c2, c) -> (min c1.X (min c2.X c.X) , min c1.Y (min c2.Y c.Y)) - | Z -> (0., 0.) - - static member normalizeBy (minx: float) (maxx: float) (miny: float) (maxy: float) (s: SVGPathSegment) = - match s with - | M(c) -> M(c |> Coordinate2D.normalizeBy minx maxx miny maxy) - - | L(c) -> L(c |> Coordinate2D.normalizeBy minx maxx miny maxy) - | Q(c1, c) -> - Q( - c1 |> Coordinate2D.normalizeBy minx maxx miny maxy, - c |> Coordinate2D.normalizeBy minx maxx miny maxy - ) - | C(c1, c2, c) -> - C( - c1 |> Coordinate2D.normalizeBy minx maxx miny maxy, - c2 |> Coordinate2D.normalizeBy minx maxx miny maxy, - c |> Coordinate2D.normalizeBy minx maxx miny maxy - ) - | Z -> Z - - static member invert (direction: InvertDirection) (s: SVGPathSegment) = - match s with - | M(c) -> M(c |> Coordinate2D.invert direction) - | L(c) -> L(c |> Coordinate2D.invert direction) - | Q(c1, c) -> - Q( - c1 |> Coordinate2D.invert direction, - c |> Coordinate2D.invert direction - ) - | C(c1, c2, c) -> - C( - c1 |> Coordinate2D.invert direction, - c2 |> Coordinate2D.invert direction, - c |> Coordinate2D.invert direction - ) - | Z -> Z - - - static member reposition (anchorLeft:float) (anchorRight:float) (anchorTop:float) (anchorBottom:float) (left:float) (right:float) (top:float) (bottom:float) (s: SVGPathSegment) = - let x_ratio = (right - left) / (anchorRight - anchorLeft) - let y_ratio = (top - bottom) / (anchorTop - anchorBottom) - match s with - | M(c) -> - let newX = (c.X - anchorLeft) * x_ratio + left - let newY = (c.Y - anchorBottom) * y_ratio + bottom - M(Coordinate2D(newX, newY)) - | L(c) -> - let newX = (c.X - anchorLeft) * x_ratio + left - let newY = (c.Y - anchorBottom) * y_ratio + bottom - L(Coordinate2D(newX, newY)) - | Q(c1, c) -> - let newX1 = (c1.X - anchorLeft) * x_ratio + left - let newY1 = (c1.Y - anchorBottom) * y_ratio + bottom - let newX = (c.X - anchorLeft) * x_ratio + left - let newY = (c.Y - anchorBottom) * y_ratio + bottom - Q(Coordinate2D(newX1, newY1), Coordinate2D(newX, newY)) - | C(c1, c2, c) -> - let newX1 = (c1.X - anchorLeft) * x_ratio + left - let newY1 = (c1.Y - anchorBottom) * y_ratio + bottom - let newX2 = (c2.X - anchorLeft) * x_ratio + left - let newY2 = (c2.Y - anchorBottom) * y_ratio + bottom - let newX = (c.X - anchorLeft) * x_ratio + left - let newY = (c.Y - anchorBottom) * y_ratio + bottom - C(Coordinate2D(newX1, newY1), Coordinate2D(newX2, newY2), Coordinate2D(newX, newY)) - | Z -> Z - - type SVGPath(path: string, ?Left: float, ?Right: float, ?Top: float, ?Bottom: float) = - let left, right, top, bottom = - defaultArg Right 1.0, - defaultArg Left 0.0, - defaultArg Top 1.0, - defaultArg Bottom 0.0 - - let splt = path.Split([| ' '; ',' |], System.StringSplitOptions.RemoveEmptyEntries) - let segments = ResizeArray() - - let rec loop currentIndex = - if currentIndex >= splt.Length then - () - else - let currentSegment = splt.[currentIndex] - match currentSegment with - | "M" -> - let x = float splt.[currentIndex + 1] - let y = float splt.[currentIndex + 2] - segments.Add(M(Coordinate2D(x, y))) - loop (currentIndex + 3) - | "L" -> - let x = float splt.[currentIndex + 1] - let y = float splt.[currentIndex + 2] - segments.Add(L(Coordinate2D(x, y))) - loop (currentIndex + 3) - | "Q" -> - let x1 = float splt.[currentIndex + 1] - let y1 = float splt.[currentIndex + 2] - let x = float splt.[currentIndex + 3] - let y = float splt.[currentIndex + 4] - segments.Add(Q(Coordinate2D(x1, y1), Coordinate2D(x, y))) - loop (currentIndex + 5) - | "C" -> - let x1 = float splt.[currentIndex + 1] - let y1 = float splt.[currentIndex + 2] - let x2 = float splt.[currentIndex + 3] - let y2 = float splt.[currentIndex + 4] - let x = float splt.[currentIndex + 5] - let y = float splt.[currentIndex + 6] - segments.Add(C(Coordinate2D(x1, y1), Coordinate2D(x2, y2), Coordinate2D(x, y))) - loop (currentIndex + 7) - | "Z" -> - segments.Add(Z) - loop (currentIndex + 1) - | _ -> - failwithf "Unknown path command: %s" currentSegment - - do loop 0 - - member this.Segments : SVGPathSegment array = segments |> Array.ofSeq - member this.Left = left - member this.Right = right - member this.Top = top - member this.Bottom = bottom - - static member toString (path: SVGPath) = - path.Segments |> Array.map SVGPathSegment.toString |> String.concat " " - - static member normalize (path: SVGPath) = - let mutable maxx = -System.Double.MaxValue - let mutable maxy = -System.Double.MaxValue - let mutable minx = System.Double.MaxValue - let mutable miny = System.Double.MaxValue - - for segment in path.Segments do - if segment <> Z then - let mx, my = SVGPathSegment.getMaxCoords segment - let mnx, mny = SVGPathSegment.getMinCoords segment - if mx > maxx then maxx <- mx - if my > maxy then maxy <- my - if mnx < minx then minx <- mnx - if mny < miny then miny <- mny - - let normalizedSegments = - path.Segments |> Array.map (SVGPathSegment.normalizeBy minx maxx miny maxy) - - SVGPath( - normalizedSegments |> Array.map SVGPathSegment.toString |> String.concat " ", - Left = path.Left, - Right = path.Right, - Top = path.Top, - Bottom = path.Bottom - ) - - static member invert (direction: InvertDirection) (path: SVGPath) = - let invertedSegments = - path.Segments |> Array.map (SVGPathSegment.invert direction) - SVGPath( - invertedSegments |> Array.map SVGPathSegment.toString |> String.concat " ", - Left = path.Left, - Right = path.Right, - Top = path.Top, - Bottom = path.Bottom - ) - - static member reposition (left:float) (right:float) (top:float) (bottom:float) (path: SVGPath) = - let repositionedSegments = - path.Segments - |> Array.map (SVGPathSegment.reposition path.Left path.Right path.Top path.Bottom left right top bottom) - SVGPath( - repositionedSegments |> Array.map SVGPathSegment.toString |> String.concat " ", - Left = left, - Right = right, - Top = top, - Bottom = bottom - ) diff --git a/src/BioFSharp.Visualization/playground.fsx b/src/BioFSharp.Visualization/playground.fsx deleted file mode 100644 index e020d4b..0000000 --- a/src/BioFSharp.Visualization/playground.fsx +++ /dev/null @@ -1,52 +0,0 @@ -#r "nuget: Plotly.NET, 6.0.0-preview.1" -#r "nuget: BioFSharp, 2.0.0" - -#I "../../src/BioFSharp.Visualization/bin/Debug/netstandard2.0" -#r "BioFSharp.Visualization.dll" - -open Plotly.NET -open Plotly.NET.LayoutObjects -open BioFSharp -open DynamicObj -open BioFSharp.AminoAcids -open BioFSharp.Nucleotides -open BioFSharp.Visualization -open BioFSharp.Visualization.Plotly -open BioFSharp.Visualization.Plotly.ChartExtensions - -let aminos = - [| - [| (Ala, 0.3); (Glu, 0.4); (His, 0.2); (Leu, 0.1); (Pro, 0.2); (Ser, 0.1); (Trp, 0.1) |] - [| (Cys, 0.1); (Phe, 0.2); (Ile, 0.1); (Met, 0.2); (Gln, 0.1); (Thr, 0.2); (Tyr, 0.2) |] - [| (Asp, 0.4); (Gly, 0.3); (Lys, 0.4); (Asn, 0.2); (Arg, 0.4); (Val, 0.2) |] - |] - -let nucleos = - [| - [| (U, 0.3); (G, 0.4); (G, 0.2); (T, 0.1) |] - [| (A, 0.1); (C, 0.2); (G, 0.1); (T, 0.2) |] - [| (T, 0.4); (U, 0.3); (G, 0.4); (T, 0.2) |] - |] - -[ - Chart.SequenceLogo( - aminos, - AminoAcidColorScheme = StyleParam.SequenceLogoAminoAcidColorScheme.Chemistry, - Outline = Line.init(Width = 0) - ) - Chart.SequenceLogo(nucleos) - |> GenericChart.mapLayout (fun l -> - l?shapes - |> unbox> - |> Seq.iter (fun s -> - s?xref <- "x2" - s?yref <- "y2" - ) - l - - ) -] -|> Chart.SingleStack(SubPlotTitles = ["Amino Acids"; "Nucleotides"]) -|> Chart.show - -AminoAcids.standardSet |> Seq.map (fun a -> BioItem.symbol a, BioItem.name a, a) |> Seq.iter (printfn "%A") \ No newline at end of file diff --git a/tests/BioFSharp.Visualization.Tests/BioFSharp.Visualization.Tests.fsproj b/tests/BioFSharp.Visualization.Tests/BioFSharp.Visualization.Tests.fsproj deleted file mode 100644 index 93e925b..0000000 --- a/tests/BioFSharp.Visualization.Tests/BioFSharp.Visualization.Tests.fsproj +++ /dev/null @@ -1,27 +0,0 @@ - - - - net8.0 - - false - false - true - - - - - - - - - - - - - - - - - - - diff --git a/tests/BioFSharp.Visualization.Tests/Program.fs b/tests/BioFSharp.Visualization.Tests/Program.fs deleted file mode 100644 index 0695f84..0000000 --- a/tests/BioFSharp.Visualization.Tests/Program.fs +++ /dev/null @@ -1 +0,0 @@ -module Program = let [] main _ = 0 diff --git a/tests/BioFSharp.Visualization.Tests/Tests.fs b/tests/BioFSharp.Visualization.Tests/Tests.fs deleted file mode 100644 index 6f393b0..0000000 --- a/tests/BioFSharp.Visualization.Tests/Tests.fs +++ /dev/null @@ -1,10 +0,0 @@ -namespace BioFSharp.Visualization.Tests - -open Xunit - -open BioFSharp.Visualization - -type VisualizationTests() = - [] - let ``yes`` () = - Assert.True(true, "nah") \ No newline at end of file