Load R libraries
library(data.table)
## Warning: package 'data.table' was built under R version 3.3.2
library(dplyr)
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 3.3.2
Threshold for open cluster membership
oc.membership.threshold <- 68 # %
Thickness of rings around center of open cluster for radial star density
oc.dr <- 1 # arcmin
Project directories
data.dir <- "../Data/"
output.dir <- "../Output Data/"
Create directories when needed
for (d in c(output.dir)) {
if (!dir.exists(d)) dir.create(d)
}
rm(d)
Load open clusters data DAML02 [1]
daml02.raw <- read.csv(paste0(data.dir, "/B_ocl.csv"),
comment.char="#",
sep=";",
as.is=TRUE,
strip.white=TRUE)
daml02 <- daml02.raw %>%
mutate(name = as.character(Cluster)) %>%
mutate(ra2000 = RAJ2000) %>%
mutate(de2000 = DEJ2000) %>%
mutate(l = as.numeric(X_Glon)) %>%
mutate(b = as.numeric(X_Glat)) %>%
mutate(classification = as.factor(Class)) %>%
mutate(nc = as.numeric(Nc)) %>%
mutate(diameter = as.numeric(Diam)) %>%
mutate(distance = as.numeric(Dist)) %>%
mutate(age = as.numeric(Age)) %>%
mutate(type = as.factor(TrType)) %>%
select(name, l, b, classification, distance, age) %>%
filter(!is.na(l))
print(data.table(daml02))
## name l b classification distance age
## 1: Berkeley 58 116.753 -1.289 2700 8.470
## 2: NGC 7801 114.729 -11.315 r 1275 9.230
## 3: FSR 0459 116.468 -2.994 IR 3800 8.950
## 4: Stock 18 117.625 2.268 1242 8.100
## 5: Berkeley 59 118.221 4.996 1000 6.100
## ---
## 2163: Frolov 1 116.559 -0.568 nf 2000 7.588
## 2164: NGC 7790 116.589 -1.009 2944 7.749
## 2165: NGC 7795 116.376 -2.163 2105 8.650
## 2166: FSR 0460 116.575 -1.533 IR 5875 8.705
## 2167: NGC 7762 118.127 5.644 780 9.300
nrow(daml02)
## [1] 2167
Load open clusters data DMCL14 [2]
dmcl14.raw <- read.csv(paste0(data.dir, "J_A+A_564_A79_table2.csv"),
comment.char="#",
sep=";",
as.is=TRUE,
strip.white=TRUE)
dmcl14 <- dmcl14.raw %>%
mutate(name = as.character(Cluster)) %>%
mutate(ra2000 = as.numeric(RAJ2000)) %>%
mutate(de2000 = as.numeric(DEJ2000)) %>%
mutate(l = as.numeric(X_Glon)) %>%
mutate(b = as.numeric(X_Glat)) %>%
mutate(diameter = 2*as.numeric(Rad)) %>%
mutate(n = as.numeric(N)) %>%
mutate(nc = as.numeric(Nc)) %>%
mutate(nf = as.numeric(Nf)) %>%
select(name, ra2000, de2000, diameter, nc) %>%
filter(!is.na(diameter))
print(data.table(dmcl14))
## name ra2000 de2000 diameter nc
## 1: SAI 113 155.68333 -59.50555 2.0 18
## 2: Dutra Bica 10 267.57501 -28.89500 2.6 29
## 3: FSR 0357 337.72498 53.95639 2.6 23
## 4: FSR 0023 269.39584 -22.87556 2.7 18
## 5: DC 1 100.50417 -12.97417 2.7 11
## ---
## 1801: Alessi 22 357.02914 36.20500 84.0 1819
## 1802: Mamajek 4 276.50000 -51.00000 86.0 8333
## 1803: Blanco 1 1.02917 -29.83333 72.0 527
## 1804: NGC 6475 268.46249 -34.79333 82.0 43550
## 1805: Collinder 173 120.70417 -46.38334 372.0 157743
nrow(dmcl14)
## [1] 1805
Merge open clusters catalog data of DAML02 and DMCL14
clusters <- daml02 %>%
merge(dmcl14, by="name") %>%
select(name, ra2000, de2000, l, b, classification, distance, diameter, nc, age)
print(data.table(clusters))
## name ra2000 de2000 l b classification distance diameter nc age
## 1: AH03 J2011+26.7 302.98749 26.73556 65.737 -3.921 2567 6.5 32 7.35
## 2: Alessi 10 301.19168 -10.47833 31.654 -20.989 513 20.0 182 8.35
## 3: Alessi 12 310.95001 23.79167 67.465 -11.508 537 42.0 2313 8.10
## 4: Alessi 13 50.42500 -36.30000 238.549 -56.981 100 202.0 2752 NA
## 5: Alessi 19 274.61667 12.16667 40.216 12.758 550 90.0 9211 8.00
## ---
## 1796: Waterloo 2 82.00417 40.37167 168.410 3.094 550 6.0 33 8.33
## 1797: Waterloo 3 118.77499 -25.36500 242.562 1.443 5200 4.0 31 NA
## 1798: Waterloo 7 111.53333 -15.09333 230.279 0.622 2800 4.6 45 NA
## 1799: Waterloo 8 112.55000 -15.83333 231.397 1.130 NA 14.0 212 NA
## 1800: Westerlund 2 156.00833 -57.76667 284.276 -0.336 2850 4.0 84 6.30
nrow(clusters)
## [1] 1800
Filter open cluster data by classification
clusters <- clusters %>%
filter(classification != "a") %>% # Possible asterism/dust hole/star cloud (no cluster)
filter(classification != "d") %>% # Objects considered doubtful by the DSS images inspection
filter(classification != "m") %>% # Possible moving group
filter(classification != "nf") %>% # Objects not found in the DSS images inspection
filter(nc >= 5) # Filter clusters w/ less than 5 stars
nrow(clusters)
## [1] 1666
Calculate open clusters galactic cartesian position
clusters$x <- clusters$distance * cos.deg(clusters$l) * cos.deg(clusters$b) / 1000 # kpc
clusters$y <- clusters$distance * sin.deg(clusters$l) / 1000 # kpc
clusters$z <- clusters$distance * cos.deg(clusters$l) * sin.deg(clusters$b) / 1000 # kpc
knitr::include_graphics("DSS/M45.png")
oc <- subset(clusters, name == "Melotte 22")
print(oc %>% select(-x,-y,-z))
## name ra2000 de2000 l b classification distance diameter nc age
## 908 Melotte 22 56.75 24.11667 166.571 -23.521 133 122 252 8.131
Extract data for open clusters distance
distance <- clusters$distance
distance <- distance[!is.na(distance)]
length(distance)
## [1] 1603
Summary statistics of open cluster distance
summary(distance)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 45 1100 1760 2212 2700 14870
Distance to Melotte 22
printf("%.0f pc / %.0f ly", oc$distance, as.ly(oc$distance))
## [1] "133 pc / 434 ly"
p <- histogram.plot(distance, c(0,10000), 100, oc$distance) +
labs(title="Distance of Open Clusters", x="Distance [pc]")
print(p)
Calculate the number of open clusters with distance above or below the value of Melotte 22
abv <- ab(distance, oc$distance)
Number of open clusters nearer …
printf("%d (%.1f%%)", abv$n.lo, abv$p.lo)
## [1] "6 (0.4%)"
… and farther than Melotte 22
printf("%d (%.1f%%)", abv$n.hi, abv$p.hi)
## [1] "1596 (99.6%)"
Extract data for open clusters diameter
diameter <- oc.diameter(clusters)
diameter <- diameter[!is.na(diameter)]
length(diameter)
## [1] 1603
Summary statistics for open clusters diameter
summary(diameter)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.448 3.228 5.044 6.787 8.319 76.910
Diameter of Melotte 22
printf("%.1f arcmin / %.0f pc / %.0f ly", oc$diameter, oc.diameter(oc), as.ly(oc.diameter(oc)))
## [1] "122.0 arcmin / 5 pc / 15 ly"
p <- histogram.plot(diameter, c(0,30), 0.25, oc.diameter(oc)) +
labs(title="Diameter of Open Clusters", x="Diameter [pc]")
print(p)
Calculate the number of open clusters with diameter above or below the value of Melotte 22
abv <- ab(diameter, oc.diameter(oc))
Number of open clusters smaller …
printf("%d (%.1f%%)", abv$n.lo, abv$p.lo)
## [1] "739 (46.1%)"
… and larger than Melotte 22
printf("%d (%.1f%%)", abv$n.hi, abv$p.hi)
## [1] "863 (53.8%)"
Extract data for open clusters number of stars
numberofstars <- clusters$nc
numberofstars <- numberofstars[!is.na(numberofstars)]
length(numberofstars)
## [1] 1666
Summary statistics for open clusters number of stars
summary(numberofstars)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 9.0 63.0 133.5 1237.0 420.0 246200.0
Number of stars of Melotte 22
printf("%.0f", oc$nc)
## [1] "252"
p <- histogram.plot(numberofstars, c(0,1000), 10, oc$nc) +
labs(title="Number of Stars of Open Clusters", x="Number of Stars")
print(p)
Calculate the number of open clusters with number of stars below or above the value of Melotte 22
abv <- ab(numberofstars, oc$nc)
Number of open clusters with less …
printf("%d (%.1f%%)", abv$n.lo, abv$p.lo)
## [1] "1100 (66.0%)"
… and more stars than Melotte 22
printf("%d (%.1f%%)", abv$n.hi, abv$p.hi)
## [1] "563 (33.8%)"
Extract open clusters age
age <- clusters$age
age <- age[!is.na(age)]
length(age)
## [1] 1580
Summary statistics for open clusters age
summary(age)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 6.000 7.757 8.475 8.290 8.900 10.100
Age of Melotte 22
printf("%.1f Myr", 10^(oc$age-6))
## [1] "135.2 Myr"
p <- histogram.plot(age, c(5, 10), 0.1, oc$age) +
labs(title="Age of Open Clusters", x="Age [log yr]")
print(p)
Calculate the number of open clusters with age above or below the value of Melotte 22
abv <- ab(age, oc$age)
Number of open clusters younger …
printf("%d (%.1f%%)", abv$n.lo, abv$p.lo)
## [1] "568 (35.9%)"
… and older than Melotte 22
printf("%d (%.1f%%)", abv$n.hi, abv$p.hi)
## [1] "1011 (64.0%)"
The 10 nearest open clusters to Melotte 22
nearest <- clusters %>%
filter(name != oc$name) %>%
mutate(r=sqrt((x-oc$x)^2 + (y-oc$y)^2 + (z-oc$z)^2) * 1000) %>%
arrange(r) %>%
head(10) %>%
select(name, ra2000, de2000, nc, diameter, distance, r)
print(data.table(nearest))
## name ra2000 de2000 nc diameter distance r
## 1: Mamajek 3 81.79583 6.26667 22970 252 92 73.00665
## 2: Melotte 20 51.07917 49.86166 53143 302 185 86.91747
## 3: Melotte 25 66.72500 15.86667 18603 332 45 89.87130
## 4: Platais 2 18.45833 32.02833 18917 338 190 119.43271
## 5: Platais 3 70.40417 71.23666 20316 218 200 139.36315
## 6: Alessi 13 50.42500 -36.30000 2752 202 100 147.29803
## 7: Platais 4 76.84167 22.27833 21090 206 276 156.31590
## 8: Melotte 111 186.27501 26.10000 827 122 96 190.90327
## 9: Mamajek 1 130.52501 -79.02723 626 42 97 205.49086
## 10: Stock 2 33.67917 59.48500 3280 62 303 214.34022
Compose file name for open cluster member stars
file.name <- paste0("../Data/J_A+A_564_A79_pm_ucac4-",sub(" ","_",oc$name),".csv")
print(file.name)
## [1] "../Data/J_A+A_564_A79_pm_ucac4-Melotte_22.csv"
stopifnot(file.exists(file.name))
Load open cluster member data [2]
stars.raw <- read.csv(file.name, comment.char="#", sep=";", as.is=TRUE, strip.white=TRUE)
stars <- stars.raw %>%
mutate(name = as.character(UCAC4)) %>%
mutate(ra2000 = as.numeric(RAJ2000)) %>%
mutate(de2000 = as.numeric(DEJ2000)) %>%
mutate(p = as.numeric(P)) %>%
mutate(r = as.numeric(R)) %>%
mutate(pmRA = as.numeric(pmRA)) %>%
mutate(pmDE = as.numeric(pmDE)) %>%
mutate(B = as.numeric(Bmag)) %>%
mutate(V = as.numeric(Vmag)) %>%
mutate(J = as.numeric(Jmag)) %>%
select(name, ra2000, de2000, p, r, pmRA, pmDE, B, V, J) %>%
filter(!is.na(ra2000))
print(data.table(stars))
## name ra2000 de2000 p r pmRA pmDE B V J
## 1: 571-008671 56.74844 24.10338 0 0.80 15.4 -7.8 16.888 16.119 14.496
## 2: 571-008667 56.72676 24.11186 0 1.31 35.7 -31.1 15.733 14.507 12.054
## 3: 571-008681 56.77490 24.11167 0 1.40 4.6 -5.9 17.149 16.185 14.198
## 4: 571-008682 56.77718 24.12113 0 1.51 2.0 -4.7 17.635 16.909 15.438
## 5: 571-008677 56.76706 24.13745 0 1.56 4.3 -3.9 NA NA 14.785
## ---
## 4200: 576-009117 57.14420 25.06685 0 60.93 0.6 -8.3 11.538 11.170 10.279
## 4201: 570-008730 57.80947 23.80996 0 60.93 9.7 1.4 17.046 16.153 15.109
## 4202: 574-008350 55.80445 24.65544 96 60.95 23.2 -44.7 NA NA 12.178
## 4203: 566-008101 56.92012 23.11284 0 60.95 -5.2 -3.2 13.132 12.661 11.665
## 4204: 575-008692 55.96730 24.84162 94 60.98 22.4 -43.4 15.785 14.420 11.470
nrow(stars)
## [1] 4204
Membership probability of stars in the UCAC4 catalog near the center of Melotte 22
p <- histogram.plot(stars$p, c(0,100), 1, oc.membership.threshold) +
labs(x="Probability [%]", y="N", title=paste0("Membership (",oc$name,")"))
print(p)
Filter stars with a membership probability > 68%
oc.stars <- stars %>%
filter(p > oc.membership.threshold)
nrow(oc.stars)
## [1] 258
Calculate open cluster member offset from center
oc.stars <- oc.stars %>%
mutate(dRA = (oc$ra2000 - ra2000) * 60) %>% # arcmin
mutate(dDE = (oc$de2000 - de2000) * 60) # arcmin
Extract open cluster stars with B and V values defined
cmd <- oc.stars %>%
mutate(BV = B - V) %>%
filter(!is.na(BV)) %>%
select(B, V, BV)
nrow(cmd)
## [1] 203
p <- ggplot(cmd) +
geom_point(aes(BV,V), alpha=0.3) +
labs(x="B - V [mag]", y="V [mag]", title=paste0("Color Magnitude Diagram (",oc$name,")")) +
coord_cartesian(xlim=c(-0.5, 2.5)) +
scale_y_reverse() +
theme_bw()
print(p)
write.csv(cmd, paste0(output.dir,"Color Magnitude Diagram ",oc$name,".csv"), row.names = FALSE)
dt <- table(cut_width(oc.stars$r, width=oc.dr, center=0))
n <- as.data.frame(dt)[,2]
r <- as.data.frame(dt, stringsAsFactors=FALSE)[,1]
r <- as.numeric(unlist(strsplit(substring(r,2,nchar(r)-1),",")))
index <- seq(length(r))
r1 <- r[index %% 2 == 1]
r2 <- r[index %% 2 == 0]
r <- (r1 + r2) / 2
d <- n / (pi * abs((r+oc.dr)^2 - r^2))
p <- ggplot(data.frame(r=(r1+r2)/2, n=n)) +
geom_bar(aes(r, d), stat="identity") +
geom_hline(yintercept = mean(d)) +
labs(x="r [arcmin]", y="N [1/arcmin^2]", title=paste0("Radial Star Density (",oc$name,")")) +
theme_bw()
print(p)
Calculate the number of elements in a vector above and below a given value.
ab <- function(data, value, na.rm=TRUE) {
if (na.rm) data <- data[!is.na(data)]
n <- length(data)
n.lo <- sum(data < value)
n.hi <- sum(data > value)
p.lo <- 100 * n.lo / n
p.hi <- 100 * n.hi / n
list(n=n, n.lo=n.lo, n.hi=n.hi, p.lo=p.lo, p.hi=p.hi)
}
Convert parsec into lightyears.
as.ly <- function(x) 3.26*x
Convert an angle in degrees into rad.
as.rad <- function(alpha) alpha * pi / 180.0
Calculate the cosine of an angle given in degrees.
cos.deg <- function(alpha) cos(as.rad(alpha))
Create a histogram plot (ggplot2).
histogram.plot <- function(data, xlim=NULL, binwidth=1, xintercept=NULL) {
xlim.min <- ifelse(is.null(xlim), min(data, na.rm=TRUE), xlim[1])
xlim.max <- ifelse(is.null(xlim), max(data, na.rm=TRUE), xlim[2])
df <- data.frame(x=data[!is.na(data) & xlim.min <= data & data <= xlim.max])
p <- ggplot(df, aes(x)) +
geom_histogram(binwidth = binwidth) +
ylab("Count") +
theme_bw() +
coord_cartesian(xlim=c(xlim.min,xlim.max))
if (!is.null(xintercept)) p <- p + geom_vline(xintercept = xintercept)
p
}
Calculate the spatial diameter of an open cluster.
oc.diameter <- function(oc) oc$diameter * oc$distance * 60 / 206265
printf <- function(...) {
sprintf(...)
}
Calculate the sine of an angle given in degrees.
sin.deg <- function(alpha) sin(as.rad(alpha))
[1] Dias, W S; Alessi, B S; Moitinho, A; et al. (2002): „New catalogue of optically visible open clusters and candidates“. Astronomy and Astrophysics. EDP Sciences 389 (3), pp 871–873, DOI: 10.1051/0004-6361:20020668.
[2] Dias, W S; Monteiro, H; Caetano, T C; et al. (2014): „Proper motions of the optically visible open clusters based on the UCAC4 catalog“. Astronomy and Astrophysics. EDP Sciences 564, p A79, DOI: 10.1051/0004-6361/201323226.