This R Markdown file contains code which assists in the visualization
of particular samples in a dendrochronologic set in a restricted time
range. This is meant to assist cross-dating by identifying missing rings
in individual series via the comparison of the target sample with its
sister sample or a strong master chronology of the dendrochronological
series by efficiently moving around the focal sample to see how it
visually matches. Additionally the resulting graphs will indicate the
pearson correlation coefficient of the overlapped sections. Note that
any results gleamed from this type of visualization should be compared
to the actual dendrochronologic sample as to avoid falsifying data and
violating academic integrity. Currently “The Dendro Visual-inator” only
supports the comparison of two samples at a time, but if you need to
compare more than just two samples than just add more code to the fifth
code chunk where the visualizations occur following the naming
conventions/code outlined in throughout the chunk though how this will
work for the correlation coefficients is still unknown. This was code
was written and created by Benjamin A. C. MacNeill on 27/02/2026 and is
the first version of “The Dendro Visual-inator”. The core idea of “The
Dendro Visual-inator” is based on a coded Excel file called “TREE
Viewer_V0.8” which was created by Greg Jonah that performs the same task
except for the display of the correlation coefficient. Anyone can feel
free to use, modify, and experiment with “The Dendro Visual-inator” and
if you have any questions, suggestions, or issues please feel free to
reach out to bamacneill@mta.ca. Warning spelling mistakes
ahead!
##Install the Required Packages
install.packages("tidyverse")
#Note that dplR is only here to read rwl files so if you are importing a txt or csv you don't need it
install.packages("dplR")
##Load the Required Packages
library(tidyverse)
library(dplR)
##Import your Chronology Data
Listed below are some common file types and the code to import them,
though the txt and rwl are more experimental and may need to be fiddled
with.
#Import your Chronology Data (csv)
#Note you can change what type of data files you import but this may require the installation of more packages
Imported_Chronology_Data <- read_csv(file.choose())
#the following line will display the data and can be used to help understand if there was any issues with the import
Imported_Chronology_Data
#Import your Chronology Data (txt)
Imported_Chronology_Data <- read.delim(file.choose(), header = T)
Imported_Chronology_Data
#Import your Chronology Data (rwl)
Imported_Chronology_Data <- read.rwl(file.choose(), header = T)
Imported_Chronology_Data
##Format your Imported Data: Requires an Input
#Input the number of columns that are currently in the data
C <- 85
Full_Dendrochronologic_Set <- pivot_longer(Imported_Chronology_Data, #Select data
col = 2:C, #select columns to merge and convert
names_to = "Sample", #determines the name of the new column where the old column names will go
values_to = "Measure") #determines the name of the column where the old column values will go
#The following code will display the newly transformed data to see if anything when wrong
Full_Dendrochronologic_Set
##Visualizer
#Input the Object which corresponds to the imported long format chronology data
Target_Chronology <- Full_Dendrochronologic_Set
#Input the start and end years of the desired section to be visualized. Note that you should try to minimize the time range >100 or >150 year as it can impact the resolution of the chronology. Additionally, try to insure that the ranges will include sufficient data to capture where the chronologies may match and not match to allow for easier identification of missing rings.
Start <- 1800
End <- 1949
#Input the name of the series/sample or chronology which will be visualized
id1 <- "16TL512A"
id2 <- "16TL512B"
#Input the amount of years you want each series/sample or chronology to move. Note that the mvmt_ID objects en with a number that corresponds to the id# of the previously imputed chronology. Note that that positive values will make the chronology move to the right while negative numbers will move them to the left and 0 means no change.
mvmt_ID1 <- 0
mvmt_ID2 <- 0
#This Marks the end of the imputable sections what follows is the code that generates the graph. Note that the resulting graph will have a number in the left hand corner which is the pearson correlation coefficient of where the two segments overlap. Also not that you can click the "show in new window" button to allow for you to efficiently adjust then view the positions of the segments on the graph.
###############################################################################################
#This code is filtering the Target_Chronology so that it falls within the time range which was previously inputted, attaching the result to a new object called TROC (Time Range Of Chronology).
TROC <- Target_Chronology %>%
filter(Year >= Start,
Year <= End)
#The following code is filtering the newly created TROC to isolate the desired sample/series/Chronology and attaching the result to a new objects which follow the naming convention D#Temp (Data #[corresponds to id#] Temporary).
D1Temp <- TROC %>%
filter(Sample == id1)
D2Temp <- TROC %>%
filter(Sample == id2)
#The following code is creating sets of objects which are modifying the range values of the chronologies according to the previously imputed movements, resulting in two objects per set StD# (Start Data # [corresponds to id#]) and EdD# (End Data # [corresponds to id#]). Note that
StD1 <- Start + mvmt_ID1
EdD1 <- End + mvmt_ID1
StD2 <- Start + mvmt_ID2
EdD2 <- End + mvmt_ID2
#The following code is creating the data frames of each selected series with two variables time (created from the moved time ranges (StD#:EdD#)) and measure (extracted from the temporary data (D#Temp), attaching the the result to an object which follows the naming scheme `Data #` (the number corresponds to the id#).
`Data 1` <- data.frame(Year = StD1:EdD1,
Measure = D1Temp$Measure)
`Data 2` <- data.frame(Year = StD2:EdD2,
Measure = D2Temp$Measure)
#The following code is joining the measures of the `Data #` but only the rows with overlaping years, attaching the resulting data frame to an object called Correlation.df.
Correlation.df <- `Data 1` %>%
inner_join(`Data 2`,
by = "Year")
#The following code is calculating the Pearsons Correlation coefficent between both measures, attatching the result to an object called Correlation_Value. Note that you can change what type of correlation you are doing by writing its name (all lowercase) into the "" in the "method = "pearson"" section of the code. Additionally if you are comparing three segments at once you would want to add another line which calls the new data measure though I have not tested this yet.
Correlation_Value <- cor(Correlation.df$Measure.x,
Correlation.df$Measure.y,
method = "pearson")
#The following code creates the graph and notes will be annotated throughout
ggplot(D1Temp) + #this data was chosen as it matches the number of year present in the `Data #`
labs(y = "Radial Ring Growth (mm)", #generates the axis and legend labels
x = "Year",
colour = "Series",
caption = Correlation_Value) + #This adds the Correlation_Value to the graph
geom_line(aes(x = `Data 1`$Year, #generates the id1 chronology specifies the use of data from `Data 1` and adds its definition to the legend
y = `Data 1`$Measure,
colour = id1)) +
geom_line(aes(x = `Data 2`$Year, #generates the id2 chronology specifies the use of data from `Data 2` and adds its definition to the legend
y = `Data 2`$Measure,
colour = id2)) +
scale_x_continuous(breaks = seq(Start, End, by = 10)) + # customizes the breaks in the x axis
theme_classic() + #Sets the theme this can be changed or modified
theme(legend.position = "top") #dictates the legends position
LS0tDQp0aXRsZTogIlRoZSBEZW5kcm8gVmlzdWFsLWluYXRvciINCmF1dGhvcjogIkJlbmphbWluIEEuIEMuIE1hY05laWxsIg0KZGF0ZTogIjIwMjYtMDItMjgiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpUaGlzIFIgTWFya2Rvd24gZmlsZSBjb250YWlucyBjb2RlIHdoaWNoIGFzc2lzdHMgaW4gdGhlIHZpc3VhbGl6YXRpb24gb2YgcGFydGljdWxhciBzYW1wbGVzIGluIGEgZGVuZHJvY2hyb25vbG9naWMgc2V0IGluIGEgcmVzdHJpY3RlZCB0aW1lIHJhbmdlLiBUaGlzIGlzIG1lYW50IHRvIGFzc2lzdCBjcm9zcy1kYXRpbmcgYnkgaWRlbnRpZnlpbmcgbWlzc2luZyByaW5ncyBpbiBpbmRpdmlkdWFsIHNlcmllcyB2aWEgdGhlIGNvbXBhcmlzb24gb2YgdGhlIHRhcmdldCBzYW1wbGUgd2l0aCBpdHMgc2lzdGVyIHNhbXBsZSBvciBhIHN0cm9uZyBtYXN0ZXIgY2hyb25vbG9neSBvZiB0aGUgZGVuZHJvY2hyb25vbG9naWNhbCBzZXJpZXMgYnkgZWZmaWNpZW50bHkgbW92aW5nIGFyb3VuZCB0aGUgZm9jYWwgc2FtcGxlIHRvIHNlZSBob3cgaXQgdmlzdWFsbHkgbWF0Y2hlcy4gQWRkaXRpb25hbGx5IHRoZSByZXN1bHRpbmcgZ3JhcGhzIHdpbGwgaW5kaWNhdGUgdGhlIHBlYXJzb24gY29ycmVsYXRpb24gY29lZmZpY2llbnQgb2YgdGhlIG92ZXJsYXBwZWQgc2VjdGlvbnMuIE5vdGUgdGhhdCBhbnkgcmVzdWx0cyBnbGVhbWVkIGZyb20gdGhpcyB0eXBlIG9mIHZpc3VhbGl6YXRpb24gc2hvdWxkIGJlIGNvbXBhcmVkIHRvIHRoZSBhY3R1YWwgZGVuZHJvY2hyb25vbG9naWMgc2FtcGxlIGFzIHRvIGF2b2lkIGZhbHNpZnlpbmcgZGF0YSBhbmQgdmlvbGF0aW5nIGFjYWRlbWljIGludGVncml0eS4gQ3VycmVudGx5ICJUaGUgRGVuZHJvIFZpc3VhbC1pbmF0b3IiIG9ubHkgc3VwcG9ydHMgdGhlIGNvbXBhcmlzb24gb2YgdHdvIHNhbXBsZXMgYXQgYSB0aW1lLCBidXQgaWYgeW91IG5lZWQgdG8gY29tcGFyZSBtb3JlIHRoYW4ganVzdCB0d28gc2FtcGxlcyB0aGFuIGp1c3QgYWRkIG1vcmUgY29kZSB0byB0aGUgZmlmdGggY29kZSBjaHVuayB3aGVyZSB0aGUgdmlzdWFsaXphdGlvbnMgb2NjdXIgZm9sbG93aW5nIHRoZSBuYW1pbmcgY29udmVudGlvbnMvY29kZSBvdXRsaW5lZCBpbiB0aHJvdWdob3V0IHRoZSBjaHVuayB0aG91Z2ggaG93IHRoaXMgd2lsbCB3b3JrIGZvciB0aGUgY29ycmVsYXRpb24gY29lZmZpY2llbnRzIGlzIHN0aWxsIHVua25vd24uIFRoaXMgd2FzIGNvZGUgd2FzIHdyaXR0ZW4gYW5kIGNyZWF0ZWQgYnkgQmVuamFtaW4gQS4gQy4gTWFjTmVpbGwgb24gMjcvMDIvMjAyNiBhbmQgaXMgdGhlIGZpcnN0IHZlcnNpb24gb2YgIlRoZSBEZW5kcm8gVmlzdWFsLWluYXRvciIuIFRoZSBjb3JlIGlkZWEgb2YgIlRoZSBEZW5kcm8gVmlzdWFsLWluYXRvciIgaXMgYmFzZWQgb24gYSBjb2RlZCBFeGNlbCBmaWxlIGNhbGxlZCAiVFJFRSBWaWV3ZXJfVjAuOCIgd2hpY2ggd2FzIGNyZWF0ZWQgYnkgR3JlZyBKb25haCB0aGF0IHBlcmZvcm1zIHRoZSBzYW1lIHRhc2sgZXhjZXB0IGZvciB0aGUgZGlzcGxheSBvZiB0aGUgY29ycmVsYXRpb24gY29lZmZpY2llbnQuIEFueW9uZSBjYW4gZmVlbCBmcmVlIHRvIHVzZSwgbW9kaWZ5LCBhbmQgZXhwZXJpbWVudCB3aXRoICJUaGUgRGVuZHJvIFZpc3VhbC1pbmF0b3IiIGFuZCBpZiB5b3UgaGF2ZSBhbnkgcXVlc3Rpb25zLCBzdWdnZXN0aW9ucywgb3IgaXNzdWVzIHBsZWFzZSBmZWVsIGZyZWUgdG8gcmVhY2ggb3V0IHRvIGJhbWFjbmVpbGxAbXRhLmNhLiBXYXJuaW5nIHNwZWxsaW5nIG1pc3Rha2VzIGFoZWFkIQ0KDQojI0luc3RhbGwgdGhlIFJlcXVpcmVkIFBhY2thZ2VzDQoNCmBgYHtyfQ0KaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikNCiNOb3RlIHRoYXQgZHBsUiBpcyBvbmx5IGhlcmUgdG8gcmVhZCByd2wgZmlsZXMgc28gaWYgeW91IGFyZSBpbXBvcnRpbmcgYSB0eHQgb3IgY3N2IHlvdSBkb24ndCBuZWVkIGl0DQppbnN0YWxsLnBhY2thZ2VzKCJkcGxSIikNCmBgYA0KDQojI0xvYWQgdGhlIFJlcXVpcmVkIFBhY2thZ2VzDQoNCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGRwbFIpDQpgYGANCg0KIyNJbXBvcnQgeW91ciBDaHJvbm9sb2d5IERhdGENCg0KTGlzdGVkIGJlbG93IGFyZSBzb21lIGNvbW1vbiBmaWxlIHR5cGVzIGFuZCB0aGUgY29kZSB0byBpbXBvcnQgdGhlbSwgdGhvdWdoIHRoZSB0eHQgYW5kIHJ3bCBhcmUgbW9yZSBleHBlcmltZW50YWwgYW5kIG1heSBuZWVkIHRvIGJlIGZpZGRsZWQgd2l0aC4NCg0KI0ltcG9ydCB5b3VyIENocm9ub2xvZ3kgRGF0YSAoY3N2KQ0KDQpgYGB7cn0NCiNOb3RlIHlvdSBjYW4gY2hhbmdlIHdoYXQgdHlwZSBvZiBkYXRhIGZpbGVzIHlvdSBpbXBvcnQgYnV0IHRoaXMgbWF5IHJlcXVpcmUgdGhlIGluc3RhbGxhdGlvbiBvZiBtb3JlIHBhY2thZ2VzDQpJbXBvcnRlZF9DaHJvbm9sb2d5X0RhdGEgPC0gcmVhZF9jc3YoZmlsZS5jaG9vc2UoKSkNCiN0aGUgZm9sbG93aW5nIGxpbmUgd2lsbCBkaXNwbGF5IHRoZSBkYXRhIGFuZCBjYW4gYmUgdXNlZCB0byBoZWxwIHVuZGVyc3RhbmQgaWYgdGhlcmUgd2FzIGFueSBpc3N1ZXMgd2l0aCB0aGUgaW1wb3J0DQpJbXBvcnRlZF9DaHJvbm9sb2d5X0RhdGENCmBgYA0KDQojSW1wb3J0IHlvdXIgQ2hyb25vbG9neSBEYXRhICh0eHQpDQoNCmBgYHtyfQ0KSW1wb3J0ZWRfQ2hyb25vbG9neV9EYXRhIDwtIHJlYWQuZGVsaW0oZmlsZS5jaG9vc2UoKSwgaGVhZGVyID0gVCkNCkltcG9ydGVkX0Nocm9ub2xvZ3lfRGF0YQ0KYGBgDQoNCiNJbXBvcnQgeW91ciBDaHJvbm9sb2d5IERhdGEgKHJ3bCkNCg0KYGBge3J9DQpJbXBvcnRlZF9DaHJvbm9sb2d5X0RhdGEgPC0gcmVhZC5yd2woZmlsZS5jaG9vc2UoKSwgaGVhZGVyID0gVCkNCkltcG9ydGVkX0Nocm9ub2xvZ3lfRGF0YQ0KYGBgDQoNCiMjRm9ybWF0IHlvdXIgSW1wb3J0ZWQgRGF0YTogUmVxdWlyZXMgYW4gSW5wdXQNCg0KYGBge3J9DQojSW5wdXQgdGhlIG51bWJlciBvZiBjb2x1bW5zIHRoYXQgYXJlIGN1cnJlbnRseSBpbiB0aGUgZGF0YQ0KQyA8LSA4NQ0KDQpGdWxsX0RlbmRyb2Nocm9ub2xvZ2ljX1NldCA8LSBwaXZvdF9sb25nZXIoSW1wb3J0ZWRfQ2hyb25vbG9neV9EYXRhLCAjU2VsZWN0IGRhdGENCiAgICAgICAgICAgICAgICAgICAgY29sID0gMjpDLCAjc2VsZWN0IGNvbHVtbnMgdG8gbWVyZ2UgYW5kIGNvbnZlcnQNCiAgICAgICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAiU2FtcGxlIiwgI2RldGVybWluZXMgdGhlIG5hbWUgb2YgdGhlIG5ldyBjb2x1bW4gd2hlcmUgdGhlIG9sZCBjb2x1bW4gbmFtZXMgd2lsbCBnbw0KICAgICAgICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAiTWVhc3VyZSIpICNkZXRlcm1pbmVzIHRoZSBuYW1lIG9mIHRoZSBjb2x1bW4gd2hlcmUgdGhlIG9sZCBjb2x1bW4gdmFsdWVzIHdpbGwgZ28NCiNUaGUgZm9sbG93aW5nIGNvZGUgd2lsbCBkaXNwbGF5IHRoZSBuZXdseSB0cmFuc2Zvcm1lZCBkYXRhIHRvIHNlZSBpZiBhbnl0aGluZyB3aGVuIHdyb25nDQpGdWxsX0RlbmRyb2Nocm9ub2xvZ2ljX1NldA0KYGBgDQoNCiMjVmlzdWFsaXplcg0KDQpgYGB7cn0NCiNJbnB1dCB0aGUgT2JqZWN0IHdoaWNoIGNvcnJlc3BvbmRzIHRvIHRoZSBpbXBvcnRlZCBsb25nIGZvcm1hdCBjaHJvbm9sb2d5IGRhdGENClRhcmdldF9DaHJvbm9sb2d5IDwtIEZ1bGxfRGVuZHJvY2hyb25vbG9naWNfU2V0DQojSW5wdXQgdGhlIHN0YXJ0IGFuZCBlbmQgeWVhcnMgb2YgdGhlIGRlc2lyZWQgc2VjdGlvbiB0byBiZSB2aXN1YWxpemVkLiBOb3RlIHRoYXQgeW91IHNob3VsZCB0cnkgdG8gbWluaW1pemUgdGhlIHRpbWUgcmFuZ2UgPjEwMCBvciA+MTUwIHllYXIgYXMgaXQgY2FuIGltcGFjdCB0aGUgcmVzb2x1dGlvbiBvZiB0aGUgY2hyb25vbG9neS4gQWRkaXRpb25hbGx5LCB0cnkgdG8gaW5zdXJlIHRoYXQgdGhlIHJhbmdlcyB3aWxsIGluY2x1ZGUgc3VmZmljaWVudCBkYXRhIHRvIGNhcHR1cmUgd2hlcmUgdGhlIGNocm9ub2xvZ2llcyBtYXkgbWF0Y2ggYW5kIG5vdCBtYXRjaCB0byBhbGxvdyBmb3IgZWFzaWVyIGlkZW50aWZpY2F0aW9uIG9mIG1pc3NpbmcgcmluZ3MuDQpTdGFydCA8LSAxODAwDQpFbmQgPC0gMTk0OQ0KDQojSW5wdXQgdGhlIG5hbWUgb2YgdGhlIHNlcmllcy9zYW1wbGUgb3IgY2hyb25vbG9neSB3aGljaCB3aWxsIGJlIHZpc3VhbGl6ZWQgDQppZDEgPC0gIjE2VEw1MTJBIg0KaWQyIDwtICIxNlRMNTEyQiINCg0KI0lucHV0IHRoZSBhbW91bnQgb2YgeWVhcnMgeW91IHdhbnQgZWFjaCBzZXJpZXMvc2FtcGxlIG9yIGNocm9ub2xvZ3kgdG8gbW92ZS4gTm90ZSB0aGF0IHRoZSBtdm10X0lEIG9iamVjdHMgZW4gd2l0aCBhIG51bWJlciB0aGF0IGNvcnJlc3BvbmRzIHRvIHRoZSBpZCMgb2YgdGhlIHByZXZpb3VzbHkgaW1wdXRlZCBjaHJvbm9sb2d5LiBOb3RlIHRoYXQgdGhhdCBwb3NpdGl2ZSB2YWx1ZXMgd2lsbCBtYWtlIHRoZSBjaHJvbm9sb2d5IG1vdmUgdG8gdGhlIHJpZ2h0IHdoaWxlIG5lZ2F0aXZlIG51bWJlcnMgd2lsbCBtb3ZlIHRoZW0gdG8gdGhlIGxlZnQgYW5kIDAgbWVhbnMgbm8gY2hhbmdlLg0KDQptdm10X0lEMSA8LSAwDQptdm10X0lEMiA8LSAwDQoNCiNUaGlzIE1hcmtzIHRoZSBlbmQgb2YgdGhlIGltcHV0YWJsZSBzZWN0aW9ucyB3aGF0IGZvbGxvd3MgaXMgdGhlIGNvZGUgdGhhdCBnZW5lcmF0ZXMgdGhlIGdyYXBoLiBOb3RlIHRoYXQgdGhlIHJlc3VsdGluZyBncmFwaCB3aWxsIGhhdmUgYSBudW1iZXIgaW4gdGhlIGxlZnQgaGFuZCBjb3JuZXIgd2hpY2ggaXMgdGhlIHBlYXJzb24gY29ycmVsYXRpb24gY29lZmZpY2llbnQgb2Ygd2hlcmUgdGhlIHR3byBzZWdtZW50cyBvdmVybGFwLiBBbHNvIG5vdCB0aGF0IHlvdSBjYW4gY2xpY2sgdGhlICJzaG93IGluIG5ldyB3aW5kb3ciIGJ1dHRvbiB0byBhbGxvdyBmb3IgeW91IHRvIGVmZmljaWVudGx5IGFkanVzdCB0aGVuIHZpZXcgdGhlIHBvc2l0aW9ucyBvZiB0aGUgc2VnbWVudHMgb24gdGhlIGdyYXBoLg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KDQoNCiNUaGlzIGNvZGUgaXMgZmlsdGVyaW5nIHRoZSBUYXJnZXRfQ2hyb25vbG9neSBzbyB0aGF0IGl0IGZhbGxzIHdpdGhpbiB0aGUgdGltZSByYW5nZSB3aGljaCB3YXMgcHJldmlvdXNseSBpbnB1dHRlZCwgYXR0YWNoaW5nIHRoZSByZXN1bHQgdG8gYSBuZXcgb2JqZWN0IGNhbGxlZCBUUk9DIChUaW1lIFJhbmdlIE9mIENocm9ub2xvZ3kpLg0KVFJPQyA8LSBUYXJnZXRfQ2hyb25vbG9neSAlPiUgDQogIGZpbHRlcihZZWFyID49IFN0YXJ0LCANCiAgICAgICAgIFllYXIgPD0gRW5kKQ0KI1RoZSBmb2xsb3dpbmcgY29kZSBpcyBmaWx0ZXJpbmcgdGhlIG5ld2x5IGNyZWF0ZWQgVFJPQyB0byBpc29sYXRlIHRoZSBkZXNpcmVkIHNhbXBsZS9zZXJpZXMvQ2hyb25vbG9neSBhbmQgYXR0YWNoaW5nIHRoZSByZXN1bHQgdG8gYSBuZXcgb2JqZWN0cyB3aGljaCBmb2xsb3cgdGhlIG5hbWluZyBjb252ZW50aW9uIEQjVGVtcCAoRGF0YSAjW2NvcnJlc3BvbmRzIHRvIGlkI10gVGVtcG9yYXJ5KS4gDQpEMVRlbXAgPC0gVFJPQyAlPiUgDQogIGZpbHRlcihTYW1wbGUgPT0gaWQxKQ0KRDJUZW1wIDwtIFRST0MgJT4lIA0KICBmaWx0ZXIoU2FtcGxlID09IGlkMikNCiNUaGUgZm9sbG93aW5nIGNvZGUgaXMgY3JlYXRpbmcgc2V0cyBvZiBvYmplY3RzIHdoaWNoIGFyZSBtb2RpZnlpbmcgdGhlIHJhbmdlIHZhbHVlcyBvZiB0aGUgY2hyb25vbG9naWVzIGFjY29yZGluZyB0byB0aGUgcHJldmlvdXNseSBpbXB1dGVkIG1vdmVtZW50cywgcmVzdWx0aW5nIGluIHR3byBvYmplY3RzIHBlciBzZXQgU3REIyAoU3RhcnQgRGF0YSAjIFtjb3JyZXNwb25kcyB0byBpZCNdKSBhbmQgRWREIyAoRW5kIERhdGEgIyBbY29ycmVzcG9uZHMgdG8gaWQjXSkuIE5vdGUgdGhhdA0KU3REMSA8LSBTdGFydCArIG12bXRfSUQxDQpFZEQxIDwtIEVuZCArIG12bXRfSUQxDQpTdEQyIDwtIFN0YXJ0ICsgbXZtdF9JRDINCkVkRDIgPC0gRW5kICsgbXZtdF9JRDINCiNUaGUgZm9sbG93aW5nIGNvZGUgaXMgY3JlYXRpbmcgdGhlIGRhdGEgZnJhbWVzIG9mIGVhY2ggc2VsZWN0ZWQgc2VyaWVzIHdpdGggdHdvIHZhcmlhYmxlcyB0aW1lIChjcmVhdGVkIGZyb20gdGhlIG1vdmVkIHRpbWUgcmFuZ2VzIChTdEQjOkVkRCMpKSBhbmQgbWVhc3VyZSAoZXh0cmFjdGVkIGZyb20gdGhlIHRlbXBvcmFyeSBkYXRhIChEI1RlbXApLCBhdHRhY2hpbmcgdGhlIHRoZSByZXN1bHQgdG8gYW4gb2JqZWN0IHdoaWNoIGZvbGxvd3MgdGhlIG5hbWluZyBzY2hlbWUgYERhdGEgI2AgKHRoZSBudW1iZXIgY29ycmVzcG9uZHMgdG8gdGhlIGlkIykuIA0KYERhdGEgMWAgPC0gZGF0YS5mcmFtZShZZWFyID0gU3REMTpFZEQxLA0KICAgICAgICAgICAgICAgICAgICAgIE1lYXN1cmUgPSBEMVRlbXAkTWVhc3VyZSkNCmBEYXRhIDJgIDwtIGRhdGEuZnJhbWUoWWVhciA9IFN0RDI6RWREMiwNCiAgICAgICAgICAgICAgICAgICAgICBNZWFzdXJlID0gRDJUZW1wJE1lYXN1cmUpDQojVGhlIGZvbGxvd2luZyBjb2RlIGlzIGpvaW5pbmcgdGhlIG1lYXN1cmVzIG9mIHRoZSBgRGF0YSAjYCBidXQgb25seSB0aGUgcm93cyB3aXRoIG92ZXJsYXBpbmcgeWVhcnMsIGF0dGFjaGluZyB0aGUgcmVzdWx0aW5nIGRhdGEgZnJhbWUgdG8gYW4gb2JqZWN0IGNhbGxlZCBDb3JyZWxhdGlvbi5kZi4NCkNvcnJlbGF0aW9uLmRmIDwtIGBEYXRhIDFgICU+JSANCiAgaW5uZXJfam9pbihgRGF0YSAyYCwgDQogICAgICAgICAgICAgYnkgPSAiWWVhciIpDQojVGhlIGZvbGxvd2luZyBjb2RlIGlzIGNhbGN1bGF0aW5nIHRoZSBQZWFyc29ucyBDb3JyZWxhdGlvbiBjb2VmZmljZW50IGJldHdlZW4gYm90aCBtZWFzdXJlcywgYXR0YXRjaGluZyB0aGUgcmVzdWx0IHRvIGFuIG9iamVjdCBjYWxsZWQgQ29ycmVsYXRpb25fVmFsdWUuIE5vdGUgdGhhdCB5b3UgY2FuIGNoYW5nZSB3aGF0IHR5cGUgb2YgY29ycmVsYXRpb24geW91IGFyZSBkb2luZyBieSB3cml0aW5nIGl0cyBuYW1lIChhbGwgbG93ZXJjYXNlKSBpbnRvIHRoZSAiIiBpbiB0aGUgIm1ldGhvZCA9ICJwZWFyc29uIiIgc2VjdGlvbiBvZiB0aGUgY29kZS4gQWRkaXRpb25hbGx5IGlmIHlvdSBhcmUgY29tcGFyaW5nIHRocmVlIHNlZ21lbnRzIGF0IG9uY2UgeW91IHdvdWxkIHdhbnQgdG8gYWRkIGFub3RoZXIgbGluZSB3aGljaCBjYWxscyB0aGUgbmV3IGRhdGEgbWVhc3VyZSB0aG91Z2ggSSBoYXZlIG5vdCB0ZXN0ZWQgdGhpcyB5ZXQuDQpDb3JyZWxhdGlvbl9WYWx1ZSA8LSBjb3IoQ29ycmVsYXRpb24uZGYkTWVhc3VyZS54LCANCiAgICAgICAgICAgICAgICAgICAgICAgICBDb3JyZWxhdGlvbi5kZiRNZWFzdXJlLnksDQogICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gInBlYXJzb24iKQ0KI1RoZSBmb2xsb3dpbmcgY29kZSBjcmVhdGVzIHRoZSBncmFwaCBhbmQgbm90ZXMgd2lsbCBiZSBhbm5vdGF0ZWQgdGhyb3VnaG91dA0KZ2dwbG90KEQxVGVtcCkgKyAjdGhpcyBkYXRhIHdhcyBjaG9zZW4gYXMgaXQgbWF0Y2hlcyB0aGUgbnVtYmVyIG9mIHllYXIgcHJlc2VudCBpbiB0aGUgYERhdGEgI2ANCiAgbGFicyh5ID0gIlJhZGlhbCBSaW5nIEdyb3d0aCAobW0pIiwgI2dlbmVyYXRlcyB0aGUgYXhpcyBhbmQgbGVnZW5kIGxhYmVscw0KICAgICAgIHggPSAiWWVhciIsDQogICAgICAgY29sb3VyID0gIlNlcmllcyIsDQogICAgICAgY2FwdGlvbiA9IENvcnJlbGF0aW9uX1ZhbHVlKSArICNUaGlzIGFkZHMgdGhlIENvcnJlbGF0aW9uX1ZhbHVlIHRvIHRoZSBncmFwaA0KICBnZW9tX2xpbmUoYWVzKHggPSBgRGF0YSAxYCRZZWFyLCAjZ2VuZXJhdGVzIHRoZSBpZDEgY2hyb25vbG9neSBzcGVjaWZpZXMgdGhlIHVzZSBvZiBkYXRhIGZyb20gYERhdGEgMWAgYW5kIGFkZHMgaXRzIGRlZmluaXRpb24gdG8gdGhlIGxlZ2VuZA0KICAgICAgICAgICAgeSA9IGBEYXRhIDFgJE1lYXN1cmUsDQogICAgICAgICAgICBjb2xvdXIgPSBpZDEpKSArDQogIGdlb21fbGluZShhZXMoeCA9IGBEYXRhIDJgJFllYXIsICNnZW5lcmF0ZXMgdGhlIGlkMiBjaHJvbm9sb2d5IHNwZWNpZmllcyB0aGUgdXNlIG9mIGRhdGEgZnJvbSBgRGF0YSAyYCBhbmQgYWRkcyBpdHMgZGVmaW5pdGlvbiB0byB0aGUgbGVnZW5kDQogICAgICAgICAgICAgICAgeSA9IGBEYXRhIDJgJE1lYXN1cmUsDQogICAgICAgICAgICAgICAgY29sb3VyID0gaWQyKSkgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKFN0YXJ0LCBFbmQsIGJ5ID0gMTApKSArICMgY3VzdG9taXplcyB0aGUgYnJlYWtzIGluIHRoZSB4IGF4aXMNCiAgdGhlbWVfY2xhc3NpYygpICsgI1NldHMgdGhlIHRoZW1lIHRoaXMgY2FuIGJlIGNoYW5nZWQgb3IgbW9kaWZpZWQNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpICNkaWN0YXRlcyB0aGUgbGVnZW5kcyBwb3NpdGlvbg0KYGBgDQo=