Intro to working with surface measurements

Heike Hofmann

Working with microscope scans

Outline

Working together

CSAFE has a github organization: https://github.com/CSAFE-ISU

Please email Sam (sctyner) your github handle to get signed up as members

The slides for today are in the slides repo (pull it/fork it) or follow along on https://csafe-isu.github.io/slides/01_intro-to-scans/intro-x3p.html

A bit of motivation

Main goal: same source problem, i.e. were two bullets fired from the same barrel?

Can we automate the process of matching individual characteristics?

Goal: fully automate the matching

pros:

Data Format

x3p format

b1 <- bulletr::read_x3p("data/Br1 Bullet 1-5.x3p")
str(b1)
## List of 2
##  $ header.info   :List of 4
##   ..$ num_profiles       : num 502
##   ..$ num_obs_per_profile: num 1522
##   ..$ profile_inc        : num 1.56
##   ..$ obs_inc            : num 1.56
##  $ surface.matrix: num [1:1522, 1:502] NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ...
b1$surface.matrix[1:5,1:9]
##      [,1] [,2] [,3]     [,4]     [,5]    [,6]     [,7]     [,8]     [,9]
## [1,]  NaN  NaN  NaN      NaN 2.585551     NaN 4.551897 5.793091 6.245047
## [2,]  NaN  NaN  NaN 2.649634      NaN     NaN 5.543503 6.032560 6.113507
## [3,]  NaN  NaN  NaN 2.349454 3.590647     NaN 6.025814 5.860547 6.315876
## [4,]  NaN  NaN  NaN      NaN 3.695204 5.56374 5.958358 5.938121 6.835288
## [5,]  NaN  NaN  NaN      NaN      NaN 5.86392 5.799836 6.390078      NaN

Functions

fortify_x3p turns x3p in x-y-value format:

b1_df <- bulletr::fortify_x3p(b1) 
b1_df %>% glimpse()
## Observations: 764,044
## Variables: 3
## $ x     <dbl> 0.0000, 1.5625, 3.1250, 4.6875, 6.2500, 7.8125, 9.3750, ...
## $ y     <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
## $ value <dbl> NaN, NaN, NaN, NaN, 2.585551, NaN, 4.551897, 5.793091, 6...
summary(b1_df)
##        x               y              value        
##  Min.   :  0.0   Min.   :   0.0   Min.   :  2.349  
##  1st Qu.:195.3   1st Qu.: 593.8   1st Qu.:125.309  
##  Median :391.4   Median :1188.3   Median :169.435  
##  Mean   :391.4   Mean   :1188.3   Mean   :159.588  
##  3rd Qu.:587.5   3rd Qu.:1782.8   3rd Qu.:196.084  
##  Max.   :782.8   Max.   :2376.6   Max.   :216.718  
##                                   NA's   :31497

Scan Profiles

At the heel (bottom) of the bullet there is some break-off

b1_df %>% filter(between(x, 10,20)) %>%
  ggplot(aes(x = y, y = value)) + geom_point(size=.1)
## Warning: Removed 2009 rows containing missing values (geom_point).

Profiles of bullets

Higher up there is a nicely expressed profile

b1_df %>% filter(between(x, 100,110)) %>%
  ggplot(aes(x = y, y = value)) + geom_point(size=.1)
## Warning: Removed 837 rows containing missing values (geom_point).

Profiles of bullets

Even higher the profile becomes flatter:

b1_df %>% filter(between(x, 500,510)) %>%
  ggplot(aes(x = y, y = value)) + geom_point(size=.1)
## Warning: Removed 295 rows containing missing values (geom_point).

Grooves and Shoulders

The chunks on the left and the right are the shoulders. The lowest spots just inside the shoulders are the grooves. Automatically identifying the grooves is problematic.

b1_df %>% filter(between(x, 100,101)) %>% 
  bulletr::get_grooves()
## $groove
## [1]  178.125 2101.562
## 
## $plot

Finding grooves is problematic

b1_df %>% filter(between(x, 100,110)) %>% 
  bulletr::get_grooves()
## $groove
##  [1]   50.0000   50.0000   50.0000   50.0000   51.5625   51.5625   51.5625
##  [8] 2300.0000 2300.0000 2300.0000 2301.5625 2301.5625 2301.5625 2301.5625
## 
## $plot

Finding grooves is problematic

get_crosscut extracts the profile from the scan that is closest to the specified x

get_crosscut(bullet = b1, x = 100) %>% bulletr::get_grooves()
## $groove
## [1]  178.125 2101.562
## 
## $plot

Your turn

Accessing the data

Three major sources:

Local database

You will need to log in to the RStudio server at https://isu-csafe.stat.iastate.edu/rstudio/

library(RMySQL)

###
### DB Connection
###
dbname <- "bullets"
user <- "buser"
password <- readLines("buser_pass.txt")
host <- "127.0.0.1"

con <- src_mysql(dbname, host, user=user, password=password)

Database schematic

Your Turn

Our ‘own’ data

Files hosted temporarily on the Isilon server

smb://my.files.iastate.edu/las/research/csafe

Instructions for mounting file space: https://researchit.las.iastate.edu/how-mount-folders-isilon

Reading local scans

Files are in x-y-value format .dat, read_dat converts them to (smaller) x3p format

b2 <- read_dat("/Volumes/csafe/bullet-scans/land-replicate/H44-GX-1b.dat")
> b2 %>% glimpse()
List of 2
 $ header.info   :List of 4
  ..$ num_profiles       : int 1023
  ..$ num_obs_per_profile: int 3639
  ..$ profile_inc        : num 0.645
  ..$ obs_inc            : num 0.645
 $ surface.matrix: num [1:3639, 1:1023] 24.4 24.5 24.8 25.2 25.6 ...

Getting help