Coder Social home page Coder Social logo

gruffi's People

Contributors

heylf avatar jn-goe avatar vertesy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

gruffi's Issues

Still unclear how to install

Hi,
I'm very excited about trying gruffi as I think it could resolve some issues I've been observing with the pseudotime analysis. Unfortunately I've been following your installation and it is still unclear for me how to make the package work. I get a similar warning as in the resolved issue #2 but I don't understand what the solution actually is. I'm not a trained computational biologist, more an advanced amateur so an implied answer didn't really help me.
This is the warning I get:

devtools::load_all("/Library/Frameworks/R.framework/Versions/4.2/Resources/library/gruffi/")

ℹ Loading gruffi
Warning messages:
1: S3 method ‘plot.clust.size.distr’ was declared in NAMESPACE but not found
2: Objects listed as exports, but not present in namespace:
• AddCustomScore
• AddGOGeneList.manual
• AddGOScore
• CalcTranscriptomePercentage
• CalcTranscriptomePercentageGO
• CleanDuplicateScorenames
• CustomScoreEvaluation
• FeaturePlotSaveCustomScore
• FeaturePlotSaveGO
• FilterStressedCells
• GO_score_evaluation
• GetAllGOTerms
• GetGOTerms
• GetNamedClusteringRuns
• IntersectWithExpressed
• PasteUniqueGeneList
• PlotGoTermScores
• PlotNormAndSkew
• Shiny.GO.thresh
• UMAP.3d.cubes
• aut.res.clustering
• calc.cluster.averages.gruffi
• clUMAP.thresholding
• fix.metad.Colname.rm.trailing.1
• reassign.small.clusters
• saveData
• saveRDS.compress.in.BG
• sparse.cor
• stand_dev_skewed
• ww.convert.GO_term.2.score
• ww.convert.score.2.GO_term

The install_github functions like devtools::install_github(repo = "vertesy/Stringendo", upgrade = F) install them in the same folder "/Library/Frameworks/R.framework/Versions/4.2/Resources/library/", so I really don't know what I'm supposed to "load_all".
I'd appreciate any help. Thank you!
Michal

Error message related with Idents

Hi,
I would please appreciate help installing Gruffi. I get an error message during the installation that I try to describe below. (note: I have limited R knowledge). After all packages have been installed and loaded, including also the Seurat object, I run the following code extracted from GitHub edited to include the the name of my Seurat object ('all samples.combined')

combined.obj <- Seurat.utils::SetupReductionsNtoKdimensions(obj = allsamples.combined, nPCs = 30, dimensions=1:20, reduction="umap")
ensembl <- biomaRt::useEnsembl("ensembl", dataset = "hsapiens_gene_ensembl")
go1 <- "GO:0006096" # Glycolysis
go2 <- "GO:0034976" # ER-stress
go3 <- "GO:0042063" # Gliogenesis, negative filtering
combined.obj <- aut.res.clustering(obj = combined.obj)
granule.res.4.gruffi <- combined.obj@misc$gruffi$'optimal.granule.res'
combined.obj <- reassign.small.clusters(combined.obj, ident = granule.res.4.gruffi)
granule.res.4.gruffi <- paste0(granule.res.4.gruffi, '.reassigned')
combined.obj <- GO_score_evaluation(obj = combined.obj, GO_term = go1, save.UMAP = TRUE, new_GO_term_computation = T, clustering = granule.res.4.gruffi, plot.each.gene = F)

At this point, I get an error message:
Error in Idents<-:
! 'value' must be a factor or vector
Run rlang::last_trace() to see where the error occurred.

As suggested, I run the code to see the error:

rlang::last_trace()
<error/rlang_error>
Error in Idents<-:
! 'value' must be a factor or vector


Backtrace:

  1. └─gruffi::GO_score_evaluation(...)
  2. ├─Seurat::Idents<-(*tmp*, value = [email protected][clustering])
  3. └─SeuratObject:::Idents<-.Seurat(*tmp*, value = [email protected][clustering])
    Run rlang::last_trace(drop = FALSE) to see 1 hidden frame.

As suggested, I run the code to see the error:

rlang::last_trace(drop = FALSE)
<error/rlang_error>
Error in Idents<-:
! 'value' must be a factor or vector


Backtrace:

  1. └─gruffi::GO_score_evaluation(...)
  2. ├─Seurat::Idents<-(*tmp*, value = [email protected][clustering])
  3. └─SeuratObject:::Idents<-.Seurat(*tmp*, value = [email protected][clustering])
  4. └─rlang::abort(message = "'value' must be a factor or vector")
    

I do not know how to fix the issue.
Thank you in advance.
Ivan

Additional information: The following are the open packages and I am using a saved session in which I created the Seurat object
library(pdist)
library(raster)
library(DOSE)
library(org.Hs.eg.db)
library(sparseMatrixStats)
library(biomaRt)
library(Stringendo)
library(CodeAndRoll2)
library(ReadWriter)
library(MarkdownHelpers)
library(MarkdownReports)
library(ggExpress)
library(Seurat.utils)
library(gruffi)

Unable to call Shiny app for GO thresh

Hi,

I've been trying to use this on my samples. It works fine until thresholding for GO term where I got this error:

In file(filename, "r", encoding = encoding) :
cannot open file '/ui.R': No such file or directory

I had a look and I couldn't find the ui.R and server.R from the package. Can you please advise?

Automatic execution of Shiny app

@vertesy

The Gruffi tool is very useful, but I need it in a completely automatic fashion, leading to the following question. Would it be possible to set the thresholds for the three GO terms without the Shiny app (e.g., just push the button save thresholds immediately after start of the shiny app)?

How important is it to have negative filters

Hi,
I had a question, im using the gruffi package to identify stressed vs non-stressed cells in my human iPSC DaNs 10x data.
I have read the pre-print for gruffi and i see why negative filtering was gliogenesis was implemented.
Since in my case neurogenesis or cell differentiation would be a better negative filter I included those.

However, i was wondering do i definitely need to have a negative filter?
If i decided to not use a negative filter for neurogenesis, true i might be identifying real neurons which have difference in the stressed pathways because of my treatment, but in your experience how much difference does not including a negative filter make.
Or rather how should I then interpret the results?

Best,
Devika

GOScoreEvaluation fails because the faulty implementation of the mirror option.

Describe the bug
GOScoreEvaluation fails with unused argument (mirror = NULL). seems like this argument is passed on to FeaturePlot

To Reproduce

> combined.obj <- GOscoreEvaluation(obj = combined.obj, GO_term = 'GO:0006096',
+                                   save.UMAP = TRUE, new_GO_term_computation = T, 
+                                   clustering = granule.res.4.gruffi, plot.each.gene = F)
[1] "Score.GO.0006096"
[1] "Score.GO.0006096 not found. Need to call GetGOTerms(). set only.draw.plot = FALSE."
[1] "GENE SCORE WILL NOW BE SET / OVERWRITTEN"
[1] "90 gene symbols downloaded via biomaRt::getBM(): SLC2A6 LDHA HTR2A PFKL FOXK1 PGK2 INSR EIF6 PGAM1 KAT2B"
[1] "90 Gene symbols downloaded: SLC2A6 LDHA HTR2A PFKL FOXK1 PGK2 INSR EIF6 PGAM1 KAT2B"
[1] "IntersectWithExpressed()"
[1] "3 genes (of 90 ) are MISSING from the Seurat object: PRXL2C TREX1 IFNG"
[1] "Genes in GO:0006096 are saved under obj@misc$GO$ GO.0006096"
[1] "ENO1"   "MTOR"   "PRKAA2" "PGM1"   "ARNT"   "PKLR"  
[1] "AddGOScore()"
[1] "Trailing '1' in metadata column name is removed. Column name: Score.GO.0006096"
Error in Seurat::FeaturePlot(obj, features = GO.score, min.cutoff = "q05",  : 
  unused argument (mirror = NULL)
> traceback()
3: FeaturePlotSaveGO(obj = obj, GO.score = ScoreName, save.plot = save.UMAP, 
       name_desc = desc, ...)
2: PlotGoTermScores(GO = GO_term, save.UMAP = save.UMAP, obj = obj, 
       desc = description, plot.each.gene = plot.each.gene, mirror = mirror, 
       ...)
1: GOscoreEvaluation(obj = combined.obj, GO_term = go_id_glycolysis, 
       save.UMAP = TRUE, new_GO_term_computation = T, clustering = granule.res.4.gruffi, 
       plot.each.gene = F)
sessionInfo()
> sessionInfo()
R version 4.3.2 (2023-10-31)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 22.04.3 LTS

Matrix products: default
BLAS:   /opt/R/4.3.2/lib/R/lib/libRblas.so 
LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.10.0

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C               LC_TIME=en_US.UTF-8       
 [4] LC_COLLATE=en_US.UTF-8     LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                  LC_ADDRESS=C              
[10] LC_TELEPHONE=C             LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

time zone: Europe/Berlin
tzcode source: system (glibc)

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] gruffi_1.2.6          MarkdownReports_4.7.0 MarkdownHelpers_1.0.7 CodeAndRoll2_2.5.6   
 [5] Stringendo_0.6.0      magrittr_2.0.3        tidyr_1.3.1           Matrix_1.6-5         
 [9] igraph_2.0.1.1        cowplot_1.1.3         ggplot2_3.4.4         dplyr_1.1.4          
[13] SeuratObject_4.1.4    Seurat_4.4.0          reticulate_1.35.0    

i cannot seem to load the package

hi!
I manage to install the package fine , but when i do
devtools::load_all(path = "/Library/Frameworks/R.framework/Versions/Current/Resources/library/gruffi/")

i get the same error as #2 . i am sorry but what should I do to solve this?

Devika

AssignGranuleAverageScoresFromGOterm fails at DOSE::geneInCategory() if obj@misc$gruffi$GO$GO.XXX is alredy present

Describe the bug
AssignGranuleAverageScoresFromGOterm fails at DOSE::geneInCategory() if obj@misc$gruffi$GO$GO.XXX is alredy present

> r$gruffi()
ℹ Loading gruffi
> combined.obj <- AssignGranuleAverageScoresFromGOterm(obj = combined.obj, GO_term = go1, save.UMAP = TRUE,
+                                                  new_GO_term_computation = T, clustering = granule.res.4.gruffi, plot.each.gene = F)
[1] "Score.GO.0006096"
Warning in CalculateAndPlotGoTermScores(GO = GO_term, save.UMAP = save.UMAP,  :
  Gene score Score.GO.0006096 will now be overwritten
Running GetGOTerms()
Pre-existing GO_genes results found in obj@misc$gruffi$GO[[make.names(GO)]].
Error in UseMethod("geneInCategory", x) : 
  no applicable method for 'geneInCategory' applied to an object of class "character"
[1] "GO.gene.symbol.slot ENO1 MTOR PRKAA2 PGM1 ARNT PKLR"

Current Workaround
Overwrite that slot by AssignGranuleAverageScoresFromGOterm( ... overwrite.misc.GO_genes = T, ...)

GO_score_evaluation error with Idents

Hello,

Thank you for a great package. I'm trying to run the following code:

AD3 <- aut.res.clustering(obj = AD3)
granule.res.4.gruffi <- AD3@misc$gruffi$'optimal.granule.res'
AD3 <- reassign.small.clusters(AD3, ident = granule.res.4.gruffi)
granule.res.4.gruffi <- paste0(granule.res.4.gruffi, '.reassigned')

AD3 <- GO_score_evaluation(obj = AD3, GO_term = go2, save.UMAP = TRUE, new_GO_term_computation = T, clustering = granule.res.4.gruffi),
but am getting this error:
Error in Idents<-:
! 'value' must be a factor or vector
Run rlang::last_trace() to see where the error occurred.

ER stress GO:0034976

A <- GO_score_evaluation(obj = AD3, GO_term = go2, save.UMAP = TRUE, new_GO_term_computation = T, clustering = granule.res.4.gruffi)
Error in Idents<-:
! 'value' must be a factor or vector
Run rlang::last_trace() to see where the error occurred.
rlang::last_trace()
<error/rlang_error>
Error in Idents<-:
! 'value' must be a factor or vector


Backtrace:

  1. └─gruffi::GO_score_evaluation(...)
  2. ├─Seurat::Idents<-(*tmp*, value = [email protected][clustering])
  3. └─SeuratObject:::Idents<-.Seurat(*tmp*, value = [email protected][clustering])
    Run rlang::last_trace(drop = FALSE) to see 1 hidden frame.

rlang::last_trace(drop = FALSE)
<error/rlang_error>
Error in Idents<-:
! 'value' must be a factor or vector


Backtrace:

  1. └─gruffi::GO_score_evaluation(...)
  2. ├─Seurat::Idents<-(*tmp*, value = [email protected][clustering])
  3. └─SeuratObject:::Idents<-.Seurat(*tmp*, value = [email protected][clustering])
  4. └─rlang::abort(message = "'value' must be a factor or vector")
    

Please advise on how to fix this.

here are my package versions:
sessionInfo()
R version 4.3.1 (2023-06-16)
Platform: x86_64-apple-darwin20 (64-bit)
Running under: macOS Ventura 13.3.1

Matrix products: default
BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.3-x86_64/Resources/lib/libRlapack.dylib; LAPACK version 3.11.0

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

time zone: America/New_York
tzcode source: internal

attached base packages:
[1] stats graphics grDevices utils datasets methods base

other attached packages:
[1] ggExpress_0.7.2 ggpubr_0.6.0 ggplot2_3.4.3 gruffi_0.7.4 Seurat_4.9.9.9059 SeuratObject_4.9.9.9091 sp_2.0-0
[8] MarkdownReports_4.5.9 MarkdownHelpers_0.2.2 CodeAndRoll2_2.3.4 Stringendo_0.3.6 magrittr_2.0.3 rgl_1.1.3 AUCell_1.22.0
[15] biomaRt_2.56.1

loaded via a namespace (and not attached):
[1] fs_1.6.3 matrixStats_1.0.0 spatstat.sparse_3.0-2 bitops_1.0-7 devtools_2.4.5 httr_1.4.7
[7] RColorBrewer_1.1-3 doParallel_1.0.17 backports_1.4.1 profvis_0.3.8 tools_4.3.1 sctransform_0.3.5
[13] utf8_1.2.3 R6_2.5.1 sm_2.2-5.7.1 lazyeval_0.2.2 uwot_0.1.16 GetoptLong_1.0.5
[19] withr_2.5.0 urlchecker_1.0.1 tictoc_1.2 prettyunits_1.1.1 gridExtra_2.3 progressr_0.14.0
[25] cli_3.6.1 Biobase_2.60.0 spatstat.explore_3.2-1 fastDummies_1.7.3 spatstat.data_3.0-1 readr_2.1.4
[31] ggridges_0.5.4 pbapply_1.7-2 slingshot_2.8.0 R.utils_2.12.2 vioplot_0.4.0 parallelly_1.36.0
[37] sessioninfo_1.2.2 rstudioapi_0.15.0 RSQLite_2.3.1 generics_0.1.3 shape_1.4.6 vroom_1.6.3
[43] gtools_3.9.4 ica_1.0-3 spatstat.random_3.1-5 car_3.1-2 zip_2.3.0 dplyr_1.1.3
[49] Matrix_1.6-1 fansi_1.0.4 S4Vectors_0.38.1 SCENIC_1.3.1 clipr_0.8.0 abind_1.4-5
[55] terra_1.7-39 R.methodsS3_1.8.2 lifecycle_1.0.3 SoupX_1.6.2 carData_3.0-5 SummarizedExperiment_1.30.2
[61] BiocFileCache_2.8.0 Rtsne_0.16 grid_4.3.1 blob_1.2.4 gdata_2.19.0 promises_1.2.1
[67] crayon_1.5.2 miniUI_0.1.1.1 lattice_0.21-8 cowplot_1.1.1 annotate_1.78.0 KEGGREST_1.40.0
[73] knitr_1.43 pillar_1.9.0 ComplexHeatmap_2.16.0 GenomicRanges_1.52.0 rjson_0.2.21 future.apply_1.11.0
[79] codetools_0.2-19 leiden_0.4.3 glue_1.6.2 data.table_1.14.8 remotes_2.4.2.1 vctrs_0.6.3
[85] png_0.1-8 spam_2.9-1 gtable_0.3.4 cachem_1.0.8 xfun_0.40 openxlsx_4.2.5.2
[91] princurve_2.1.6 S4Arrays_1.0.6 mime_0.12 ReadWriter_0.3.0 tidyverse_2.0.0 survival_3.5-7
[97] pheatmap_1.0.12 SingleCellExperiment_1.22.0 iterators_1.0.14 ellipsis_0.3.2 fitdistrplus_1.1-11 ROCR_1.0-11
[103] nlme_3.1-163 Seurat.utils_1.9.5 usethis_2.2.2 bit64_4.0.5 progress_1.2.2 filelock_1.0.2
[109] RcppAnnoy_0.0.21 GenomeInfoDb_1.36.2 irlba_2.3.5.1 KernSmooth_2.23-22 colorspace_2.1-0 BiocGenerics_0.46.0
[115] DBI_1.1.3 raster_3.6-23 tidyselect_1.2.0 processx_3.8.2 bit_4.0.5 compiler_4.3.1
[121] curl_5.0.2 graph_1.78.0 hdf5r_1.3.8 xml2_1.3.5 DelayedArray_0.26.7 plotly_4.10.2
[127] scales_1.2.1 lmtest_0.9-40 callr_3.7.3 rappdirs_0.3.3 stringr_1.5.0 digest_0.6.33
[133] goftest_1.2-3 spatstat.utils_3.0-3 XVector_0.40.0 base64enc_0.1-3 htmltools_0.5.6 pkgconfig_2.0.3
[139] sparseMatrixStats_1.12.2 MatrixGenerics_1.12.3 dbplyr_2.3.3 fastmap_1.1.1 rlang_1.1.1 GlobalOptions_0.1.2
[145] htmlwidgets_1.6.2 shiny_1.7.5 DelayedMatrixStats_1.22.6 zoo_1.8-12 jsonlite_1.8.7 BiocParallel_1.34.2
[151] R.oo_1.25.0 RCurl_1.98-1.12 GenomeInfoDbData_1.2.10 dotCall64_1.0-2 patchwork_1.1.3 munsell_0.5.0
[157] Rcpp_1.0.11 viridis_0.6.4 reticulate_1.31 TrajectoryUtils_1.8.0 stringi_1.7.12 zlibbioc_1.46.0
[163] MASS_7.3-60 org.Hs.eg.db_3.17.0 plyr_1.8.8 pkgbuild_1.4.2 parallel_4.3.1 listenv_0.9.0
[169] ggrepel_0.9.3 deldir_1.0-9 Biostrings_2.68.1 splines_4.3.1 tensor_1.5 hms_1.1.3
[175] circlize_0.4.15 ps_1.7.5 igraph_1.5.1 spatstat.geom_3.2-4 ggsignif_0.6.4 RcppHNSW_0.4.1
[181] reshape2_1.4.4 stats4_4.3.1 pkgload_1.3.2.1 XML_3.99-0.14 BiocManager_1.30.22 tzdb_0.4.0
[187] foreach_1.5.2 httpuv_1.6.11 RANN_2.6.1 tidyr_1.3.0 purrr_1.0.2 polyclip_1.10-4
[193] future_1.33.0 clue_0.3-64 scattermore_1.2 broom_1.0.5 xtable_1.8-4 RSpectra_0.16-1
[199] rstatix_0.7.2 ggcorrplot_0.1.4 later_1.3.1 viridisLite_0.4.2 tibble_3.2.1 memoise_2.0.1
[205] AnnotationDbi_1.62.2 IRanges_2.34.1 cluster_2.1.4 HGNChelper_0.8.1 globals_0.16.2 GSEABase_1.62.0

R and packages version?

Hello,

I am trying to install gruffi in my computer and while installing the dependencies, it keeps complaining that some functions are not available. I cannot figure out the proper versions, could someone share the R and the packages/dependencies versions? I believe this could be the issue.

Thank you for your time,
Paula

Unable to load package

Hello,

Firstly thank you for the tool. I've previously managed to run gruffi fine and it was helpful in better defining pseudotime for my dataset. However, recently I tried to run this again on another dataset but I was unable to load the package. Below is the error I'm getting:

Warning messages:
1: S3 method ‘plot.clust.size.distr’ was declared in NAMESPACE but not found
2: In setup_ns_exports(path, export_all, export_imports) :
Objects listed as exports, but not present in namespace: AddCustomScore, AddGOGeneList.manual, AddGOScore, CalcTranscriptomePercentage, CalcTranscriptomePercentageGO, CleanDuplicateScorenames, CustomScoreEvaluation, FeaturePlotSaveCustomScore, FeaturePlotSaveGO, FilterStressedCells, GO_score_evaluation, GetAllGOTerms, GetGOTerms, GetNamedClusteringRuns, IntersectWithExpressed, PasteUniqueGeneList, PlotGoTermScores, PlotNormAndSkew, Shiny.GO.thresh, UMAP.3d.cubes, aut.res.clustering, calc.cluster.averages.gruffi, clUMAP.thresholding, fix.metad.Colname.rm.trailing.1, reassign.small.clusters, saveData, saveRDS.compress.in.BG, sparse.cor, stand_dev_skewed, ww.convert.GO_term.2.score, ww.convert.score.2.GO_term

clusterprofiler / ensembl / AnnotationDbi

Investigate if this is correctly adressed:

i saw that u are using AnnotationDbi anyways- i would strongly be in favor for the clusterprofiler::bitr part be replaced with a simple AnnotationDbi::select(org.Hs.eg.db::org.Hs.eg.db, "GO:0006096", c("SYMBOL"), "GO")$SYMBOL

intersect(biomaRt::getBM(attributes = c('hgnc_symbol'),filters = "go_parent_term", uniqueRows = TRUE,values = "GO:0006096", mart = ensembl)[,1],AnnotationDbi::select(org.Hs.eg.db::org.Hs.eg.db, "GO:0006096", c("SYMBOL"), "GOALL")$SYMBOL %>% unique())

AnnotationDbi::select(org.Hs.eg.db::org.Hs.eg.db, "GO:0006096", c("SYMBOL"), "GOALL")$SYMBOL %>% unique()

# so please instead of

genes <- clusterProfiler::bitr("GO:0006096",fromType="GO",toType="SYMBOL",OrgDb = org.Hs.eg.db::org.Hs.eg.db)$SYMBOL

genes <- AnnotationDbi::select(org.Hs.eg.db::org.Hs.eg.db, GO, c("SYMBOL"), "GOALL")$SYMBOL %>% unique()

# GOALL is for using the equivalent of go_parent_term

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.