{"id":18722526,"url":"https://github.com/mdsumner/seaice.map","last_synced_at":"2025-04-12T14:52:57.720Z","repository":{"id":193259607,"uuid":"667385442","full_name":"mdsumner/seaice.map","owner":"mdsumner","description":"plots a map of latest sea ice image, on a global map","archived":false,"fork":false,"pushed_at":"2025-04-09T14:07:55.000Z","size":4841043,"stargazers_count":5,"open_issues_count":3,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-09T15:24:09.636Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mdsumner.png","metadata":{"files":{"readme":"README.Rmd","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-07-17T11:40:26.000Z","updated_at":"2025-04-09T14:07:59.000Z","dependencies_parsed_at":"2024-11-05T15:30:01.648Z","dependency_job_id":null,"html_url":"https://github.com/mdsumner/seaice.map","commit_stats":{"total_commits":1360,"total_committers":1,"mean_commits":1360.0,"dds":0.0,"last_synced_commit":"beff518a55061a72eed4e7468d6b0e5172ce0385"},"previous_names":["mdsumner/seaice.map"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdsumner%2Fseaice.map","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdsumner%2Fseaice.map/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdsumner%2Fseaice.map/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdsumner%2Fseaice.map/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mdsumner","download_url":"https://codeload.github.com/mdsumner/seaice.map/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248586229,"owners_count":21128995,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-07T13:41:49.109Z","updated_at":"2025-04-12T14:52:57.700Z","avatar_url":"https://github.com/mdsumner.png","language":"R","funding_links":[],"categories":[],"sub_categories":[],"readme":"---\noutput: github_document\neditor_options: \n  chunk_output_type: console\n---\n\n\n\u003c!-- README.md is generated from README.Rmd. Please edit that file --\u003e\n\n```{r, include = FALSE}\nknitr::opts_chunk$set(\n  collapse = TRUE,\n  comment = \"#\u003e\",\n  fig.path = \"man/figures/README-\"\n)\nop \u003c- options(warn = -1)\npl \u003c- as.data.frame(rbind(\nc(158.93835,-54.49871), \nc(77 + 58/60 + 3/3600,-(68 + 34/60 + 36/3600)),\nc(62 + 52/60 + 27/3600, -(67 + 36/60 + 12/3600)),\nc(110 + 31/60 + 36/3600,-(66 + 16/60 + 57/3600)),\nc(73 + 30/60 + 30/3600,-(53 + 0 + 0/3600))))\nnames(pl) \u003c- c(\"x\", \"y\")\npl$name \u003c- c(\"Macquarie Island\", \"Davis Station\", \"Casey Station\", \"Mawson Station\", \"Heard Island\")\n## copied from nuyina.map\nnuyina_underway \u003c- function(mintime) {\n\n  uwy0 \u003c- cached_underway()\n  latest \u003c- format(max(uwy0$datetime), \"%Y-%m-%dT%H:%M:%SZ\")\n  uwy \u003c- vapour::vapour_read_fields(\"WFS:https://data.aad.gov.au/geoserver/ows?service=wfs\u0026version=2.0.0\u0026request=GetCapabilities\",\n                                    sql = glue::glue(query1 \u003c- \"SELECT * FROM \\\"underway:nuyina_underway\\\" WHERE datetime \u003e '{latest}'\"))\n  #browser()\n  uwy1 \u003c- tibble::as_tibble(uwy)\n  if (!missing(mintime)) {\n    uwy0 \u003c- dplyr::filter(uwy0, datetime \u003e= mintime)\n    uwy1 \u003c-  dplyr::filter(uwy1, datetime \u003e= mintime)\n  }\n  dplyr::bind_rows(uwy0, uwy1)\n}\n\n\ncached_underway \u003c- function() {\n  arrow::read_parquet(\"https://github.com/mdsumner/nuyina.underway/raw/main/data-raw/nuyina_underway.parquet\")\n}\n```\n# seaice.map\n\n\u003c!-- badges: start --\u003e\n\u003c!-- [![R-CMD-check](https://github.com/mdsumner/seaice.map/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/mdsumner/seaice.map/actions/workflows/R-CMD-check.yaml)--\u003e\n\u003c!-- badges: end --\u003e\n\nThe goal of seaice.map is to \n\n- download very latest available sea ice concentration data\n- generate a global map of the data with a customizable focus (i.e. global but centred on Tasmania/East Antarctica)\n- also show some contextual spatio-temporal data (i.e. recent movements of a research vessel)\n- explicate how to do this all with free tools. \n\nFirst, a modified map of the subsequent one to put the ship in the centre.  (we'll fix this up)\n\n```{r pivot-map, fig.dim = c(6, 14.4), results = \"show\", echo=FALSE}\nn \u003c- 30 * 24 * 60\n\ndat \u003c- nuyina_underway()\nprint(range( dat$datetime))\ndat \u003c- tail(dat, n)\n\ntrack \u003c- cbind(dat$longitude, dat$latitude)\n\nlibrary(terra)\nr0 \u003c- vapour::gdal_raster_data(\"data-raw/seaice.png\", bands = 1:3, target_crs = sprintf(\"+proj=tmerc +lon_0=%f\", track[nrow(track), 1]), \n                              target_dim = c(1024, 0))\n\npcrs0 \u003c- attr(r0, \"projection\")\n\nptrack \u003c- terra::project(as.matrix(track), to = pcrs0, from = \"OGC:CRS84\")\n\n\nximage::ximage(r0, asp = 1, axes = FALSE)\n\npoints(terra::project(do.call(cbind, maps::map(plot = F)[1:2]), to = pcrs0, from = \"OGC:CRS84\"), pch = \".\", col = \"#777777\")\ntitle(readLines(\"data-raw/latestdate.txt\"), line = -2, col.main = \"white\")\n\n\n\nlines(ptrack, col = \"hotpink\")\npt \u003c- tail(ptrack[!is.na(ptrack[,1]) \u0026 !is.na(ptrack[,2]), ], 1L)\npoints(pt, pch = \"+\", col = \"hotpink\")\n## key locations just defined in the source of this document\n\npl[c(\"X\", \"Y\")] \u003c- terra::project(cbind(pl$x, pl$y), to = pcrs0, from = \"OGC:CRS84\")\npoints(pl$X, pl$Y, pch = 19, col = \"hotpink\", cex = 0.5)\nbx \u003c- c(range(track[,1], na.rm = TRUE), range(track[,2], na.rm = TRUE))\nrect(bx[1], bx[3], bx[2], bx[4])\n\nclaims \u003c- terra::project(terra::vect(\"data-raw/claims/claim_boundaries_ps.shp\"), pcrs0)\nplot(claims, add = TRUE)\n\n```\n\n\nNow the map we carefully designed (but keep changing to figure out how we'd like to think about East Antarctica). \n\n```{r example, fig.dim = c(6, 14.4), results=\"show\"}\nlibrary(terra)\nr \u003c- vapour::gdal_raster_data(\"data-raw/seaice.png\", bands = 1:3)\npcrs \u003c- attr(r, \"projection\")\nximage::ximage(r, asp = 1, axes = FALSE)\npoints(terra::project(do.call(cbind, maps::map(plot = F)[1:2]), to = pcrs, from = \"OGC:CRS84\"), pch = \".\", col = \"#777777\")\ntitle(readLines(\"data-raw/latestdate.txt\"), line = -2, col.main = \"white\")\n\nptrack \u003c- terra::project(as.matrix(track), to = pcrs, from = \"OGC:CRS84\")\n\nlines(ptrack, col = \"hotpink\")\npt \u003c- tail(ptrack[!is.na(track[,1]) \u0026 !is.na(ptrack[,2]), ], 1L)\n\nn \u003c- 30 * 24 * 60\n\ndat \u003c- nuyina_underway()\n\n\ndat$longitude[dat$longitude \u003c 0] \u003c- -dat$longitude[dat$longitude \u003c 0] \nprint(range( dat$datetime))\ndat \u003c- tibble::as_tibble(dat)\ndat \u003c- tail(dat, n)\ndat$datetime \u003c- as.POSIXct(dat$datetime, \"%Y/%m/%d %H:%M:%S\", tz = \"UTC\")\n\ntrack \u003c- cbind(dat$longitude, dat$latitude)\n\ntrack \u003c- terra::project(as.matrix(track), to = pcrs, from = \"OGC:CRS84\")\nlines(track, col = \"hotpink\")\npt \u003c- tail(track[!is.na(track[,1]) \u0026 !is.na(track[,2]), ], 1L)\npoints(pt, pch = \"+\", col = \"hotpink\")\n## key locations just defined in the source of this document\npl[c(\"X\", \"Y\")] \u003c- terra::project(cbind(pl$x, pl$y), to = pcrs, from = \"OGC:CRS84\")\npoints(pl$X, pl$Y, pch = 19, col = \"hotpink\", cex = 0.5)\nbx \u003c- c(range(ptrack[,1], na.rm = TRUE), range(ptrack[,2], na.rm = TRUE))\nrect(bx[1], bx[3], bx[2], bx[4])\nclaims \u003c- terra::project(terra::vect(\"data-raw/claims/claim_boundaries_ps.shp\"), pcrs)\n\nplot(claims, add = TRUE)\n\nmap \u003c- terra::vect(\"data-raw/CGAZ.fgb\")\n\n\n\nptrack0 \u003c- terra::project(as.matrix(track), to = pcrs0, from = pcrs)\nplot(tail(ptrack0, 10000), type = \"n\", asp = 1, axes = F, xlab = \"\", ylab = \"\")\ntitle(paste0(as.Date(range(dat$datetime)),collapse = \",\"), col.main = \"white\")\n#plotRGB(r, add = TRUE)\nximage::ximage(r0, add = TRUE)\nlines(tail(ptrack0, 4000), col = \"hotpink\")\nplot(terra::project(map, pcrs0), add = TRUE, border = \"#777777\")\n\nplot(terra::project(claims, pcrs0), add = TRUE)\npl[c(\"X\", \"Y\")] \u003c- terra::project(cbind(pl$x, pl$y), to = pcrs0, from = \"OGC:CRS84\")\npoints(pl$X, pl$Y, pch = 19, col = \"hotpink\", cex = 1)\n\npt_recent \u003c- tail(ptrack0, 1000)\nlines(pt_recent, lwd = 3, col = \"green\")\npoints(tail(pt_recent, 1), pch = \"X\", cex = 2, col = \"white\")\nrr \u003c- diff(par(\"usr\"))[c(1, 3)]\nif (rr[1] \u003e rr[2]) {\n  dm \u003c- as.integer(c(1, rr[2]/rr[1]) * 1024)\n} else {\n  dm \u003c- as.integer(c(1, rr[1]/rr[2]) * 1024)\n}\ncont \u003c- terra::project(terra::rast(\"/vsicurl/https://gebco2023.s3.valeria.science/gebco_2023_land_cog.tif\"), \n               terra::rast(terra::ext(par(\"usr\")), ncols = dm[1], nrows = dm[2], crs = pcrs0))\ncont[cont \u003e -10] \u003c- NA\ntry(contour(cont, add = TRUE, col = \"lightgrey\", breaks = quantile(na.omit(values(cont)[,1]), seq(0.1, 1, by = 10))), silent = TRUE)\n\n\n```\n\n\n```{r traceplots}\n\nvars \u003c- c(\"port_solar_irradiance\", \"shipnav_ground_course\", \"air_pressure_trend3h\", \"fore_2_wind_from_direction_true\", \"port_air_temperature\", \"longitude\", \"latitude\")\nwhich(vars %in% names(dat))\n for (i in seq_along(vars)) {\n   bad \u003c- is.na(dat[[vars[i]]])\n   if (any(!bad)) {\n     dat2 \u003c- dat[!bad, ]\n      plot(dat2$datetime, dat2[[vars[i]]], pch = 19, cex = .2, xlab = \"\", main = vars[i])\n   }\n }\n\n```\n\n\nThis is 25km sea ice concentration from NSIDC, reprojected from images published by NOAA at https://noaadata.apps.nsidc.org/NOAA/G02135/ (the projection is Transverse Mercator with central longitude 147). \n\nThe point (and track if available) is the recent position of the [Nuyina research vessel](https://www.antarctica.gov.au/nuyina/) taken from the underway data that measures atmospheric and water properties. \n\nFiles in 'data-raw/' contain the actual metadata and scripts. This runs as a daily task on github actions. \n\n\nNow zoom in on the ship some more.  This should just show coarse google imagery, with better Maxar imagery when near coastline.  \n\n```{r zoom, fig.dim = c(9, 9)}\nloc \u003c- ptrack[nrow(ptrack),,  drop = FALSE]\n#loc \u003c- pl[2, c(\"X\", \"Y\")]\n#loc \u003c- terra::project(cbind(-70.933004,-10.7192677)[,2:1, drop = F], to = pcrs, from = \"OGC:CRS84\")\nxr \u003c- loc[1,1] + c(-1000, 1000) * 34\nyr \u003c- loc[1,2] + c(-1000, 1000)  * 34\n\n\ngoog \u003c- sds::wms_googlehybrid_tms()\nesri \u003c- sds::wms_arcgis_mapserver_ESRI.WorldImagery_tms()\ngmap \u003c- vapour::gdal_raster_image(goog, target_ext = c(xr, yr), target_crs = pcrs, target_dim = c(1024, 0))\nif (length(unique(gmap[[1]])) \u003c 800) {\n\nxr \u003c- loc[1,1] + c(-1000, 1000) * 800\nyr \u003c- loc[1,2] + c(-1000, 1000) * 800\ngmap \u003c- vapour::gdal_raster_image(esri, target_ext = c(xr, yr), target_crs = pcrs, target_dim = c(1024, 0))\n#length(unique(gmap[[1]]))\n}\n\n\nplot(loc[,1:2, drop = F], xlim = xr, ylim =yr, asp = 1, axes = FALSE, xlab = \"\", ylab = \"\")\nximage::ximage(gmap, add = T)\nplot(claims, add = TRUE)\n\nlines(ptrack, col = \"hotpink\")\npoints(pl$X, pl$Y, pch = 19, col = \"hotpink\", cex = 0.5)\n\n\n```\n\n\nA sentinel-2-l2a image around the ship, or at least the last one that worked where the ship was at the time. \n\n```{r sentinel-zoom, fig.dim = c(14, 14)}\ndat \u003c- nuyina_underway()\nprint(range( dat$datetime))\n\ntrack \u003c- cbind(dat$longitude, dat$latitude)\n## there's an artefact uploaded for each run, but we should probably put these elswhere ...WIP\nr \u003c- try(vapour::gdal_raster_data(\"data-raw/sentinel-image.tif\", target_dim = c(1024, 0), bands = 1:3))\n\nfor (i in seq_along(r)) {\n  r[[i]][is.na(r[[i]])] \u003c- 0\n}\n\n\nif (!inherits(r, \"try-error\")) {\n  ptrack \u003c- terra::project(as.matrix(track), to = attr(r, \"projection\"), from = \"OGC:CRS84\")\nfor (i in 1:3) r[[i]][is.na(r[[i]])] \u003c- 0\nximage::ximage(r, asp = 1)\nlines(tail(ptrack, 5000), col = \"hotpink\")\n#points(pl$X, pl$Y, pch = 19, col = \"hotpink\", cex = 0.5)\n}\n```\n\n\n\n## Code of Conduct\n  \nPlease note that the seaice.map project is released with a [Contributor Code of Conduct](https://contributor-covenant.org/version/2/1/CODE_OF_CONDUCT.html). By contributing to this project, you agree to abide by its terms.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmdsumner%2Fseaice.map","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmdsumner%2Fseaice.map","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmdsumner%2Fseaice.map/lists"}