Skip to content

Prep quickstart #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 61 commits into from
Mar 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
239d093
cut down number of dependencies
colearendt Jan 10, 2019
ebbe1f2
remove problematic line for connect
colearendt Jan 10, 2019
7cdccbf
name chunk
colearendt Jan 10, 2019
c3f99ff
add rproj file
colearendt Jan 10, 2019
3eccd5a
add gitignore to avoid tracking generated files
colearendt Jan 10, 2019
dbd42e7
add simple requirements.txt
colearendt Jan 10, 2019
4135828
add manifest.json for demo-notebook
colearendt Jan 10, 2019
624dbd8
add image link to .internal.yml
colearendt Jan 10, 2019
98434db
try adding python directly
colearendt Jan 10, 2019
a3e345c
add debug info
colearendt Jan 10, 2019
c0fcdbb
add print
colearendt Jan 10, 2019
7664a0e
rename .internal.yml to .connect.yml
colearendt Jan 22, 2019
8b0c0d5
rename name to title
colearendt Jan 22, 2019
30c891e
Merge remote-tracking branch 'origin/master' into prep-quickstart
colearendt Feb 1, 2019
e56ecec
add space
colearendt Feb 1, 2019
71fa9e1
fix connect.yml
colearendt Feb 1, 2019
22c2acb
update manifest
colearendt Feb 1, 2019
4b4ebb7
add .internal.yml temporarily until the quickstart changes its codebase
colearendt Feb 1, 2019
06286a8
Merge remote-tracking branch 'origin/master' into prep-quickstart
colearendt Feb 1, 2019
a153a03
add manifest for image-classifier
colearendt Feb 1, 2019
b2d9299
fix torch requirements.txt entry
colearendt Feb 1, 2019
99aa005
add image classification to .connect.yml
colearendt Feb 1, 2019
ca5c496
add gitlink placeholder
colearendt Feb 2, 2019
3126ec5
overhaul image path provisioning
colearendt Feb 2, 2019
464548d
add config.yml
colearendt Feb 2, 2019
4906e96
clean up semantics
colearendt Feb 2, 2019
9e940c2
add default images
colearendt Feb 2, 2019
58426a9
clean up default images
colearendt Feb 2, 2019
f254fe0
fix error handling
colearendt Feb 2, 2019
dc62b84
update config.yml
colearendt Feb 2, 2019
631b924
add image-classifier manifest
colearendt Feb 2, 2019
479ee3c
fix wrapping issue on the image
colearendt Feb 2, 2019
9c9d507
remove gitlink
colearendt Feb 4, 2019
9f0d5e4
change "download" to "fetch-image-url"
colearendt Feb 4, 2019
aac652b
update config file
colearendt Feb 4, 2019
123791b
scrub "download" from the app
colearendt Feb 4, 2019
0858cdf
add image classification with pytorch to .internal.yml for the quicks…
colearendt Feb 4, 2019
5e690ca
add pytorch logo
colearendt Feb 4, 2019
93f7de0
update image to use pytorch-logo
colearendt Feb 4, 2019
0008ea4
update .connect.yml to use the pytorch logo
colearendt Feb 4, 2019
72ea993
first pass at sentiment-analysis app
colearendt Feb 7, 2019
86b8fa4
add predict.py
colearendt Feb 7, 2019
26f5c3a
add namesgenerator.py
colearendt Feb 7, 2019
b531037
commit model trained on 10k movie reviews
colearendt Feb 7, 2019
8271a3c
add requirements.txt
colearendt Feb 7, 2019
61f568b
add rproj file
colearendt Feb 7, 2019
66c7a16
add (duplicate) train.Rmd :grimacing:
colearendt Feb 7, 2019
6d8a64f
add a br() to help with spacing
colearendt Feb 7, 2019
90a9bb5
change inputPanel layout
colearendt Feb 7, 2019
697a0e6
add some sample reviews
colearendt Feb 7, 2019
81d94ae
minor updates to the sentiment app
colearendt Feb 7, 2019
844d649
allow committing the model
colearendt Feb 7, 2019
91221ee
add another copy of the model for the api
colearendt Feb 7, 2019
fc66f02
clean up sentiment analysis api
colearendt Feb 8, 2019
dd238f0
generate manifest
colearendt Feb 8, 2019
baadea4
update manifest from connect
colearendt Feb 8, 2019
01e3d16
add spacy logo
colearendt Feb 8, 2019
384ae18
update connect.yml
colearendt Feb 8, 2019
024a6d6
update rmarkdown-notebook manifest
colearendt Feb 8, 2019
f2895d4
add api description
colearendt Feb 8, 2019
1d9c172
update internal.yml
colearendt Feb 8, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .connect.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
default:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the difference between this file and .internal.yml? Are they both necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeaaah. .internal.yml is what the QuickStart is using at the moment. Obviously both are configurable, but there are some minor differences that are not nailed down until we have a broader discussion as a team, and I would love to wait to eat that change until the change is nailed down. If you don't mind having both for the short term, it would make my life easier 😄

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mind having either files. this was mostly a curious question. If .internal.yml is being used for the QuickStart, then what is .connect.yml is being used for?

Copy link
Contributor Author

@colearendt colearendt Feb 4, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the connectapi package (R package to simplify interacting with the Connect Server API). That's the experimental one that I want to chat with y'all about. I.e. the idea is that .connect.yml (or some other such thing) would replace .internal.yml. (I use it for testing the QuickStart stuff because it is much easier to use interactively)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, thank you for clarifying!

content:
- title: "Use Python with R"
path: "./rmarkdown-notebook"
description: "Use the reticulate package to integrate Python into an R Markdown notebook."
tag:
- "Demo Content|Python"
url: "/python/reticulate/"
image: "reticulated_python.png"
- title: "Sentiment Analysis with Python"
path: "./sentiment-analysis"
description: "A Plumber API that uses R and Python to evaluate sentiment in text input using a pretrained spaCy model."
tag:
- "Demo Content|Python"
url: "/python/sentiment-analysis/"
image: "sentiment-analysis/spacy_logo.jpg"
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,3 @@ __pycache__
.ipynb_checkpoints
*.html
rmarkdown-notebook/flights.csv
sentiment-analysis/model/
12 changes: 10 additions & 2 deletions .internal.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
default:
content:
- name: "Use Python with R"
path: "./reticulate"
path: "./rmarkdown-notebook"
description: "Use the reticulate package to integrate Python into an R Markdown notebook."
tag:
- "Demo Content|Python"
url: "/python/reticulate/"
url: "/python/reticulate/"
image: "reticulated_python.png"
- name: "Sentiment Analysis with Python"
path: "./sentiment-analysis"
description: "A Plumber API that uses R and Python to evaluate sentiment in text input using a pretrained spaCy model."
tag:
- "Demo Content|Python"
url: "/python/sentiment-analysis/"
image: "sentiment-analysis/spacy_logo.jpg"
118 changes: 67 additions & 51 deletions image-classifier/app.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,79 +3,95 @@ library(reticulate) # Used to call Tensorflow Python script
library(shiny)
library(shinycssloaders)

behavior <- config::get("image")
stopifnot(behavior %in% c("upload", "fetch-image-url"))

# Load source of Python image classifier script
source_python('image-classifier.py')

server <- function(input, output, session) {

output$contents <- renderTable({
# After the user uploads a file, the image will be classified and the predictions will be shown.

# where the image that should be classified is on disk
image_path <- reactiveVal("./img/cat.jpg")

image_prefix <- "pytorch_image"

# the configurable selector for fetch-image-url vs. upload
output$image_selector <- renderUI({
if (behavior == "fetch-image-url") {
list(
textInput("file1", label = h5("Enter Image URL:"), value = ""),
actionButton("fetch-image-url", "Fetch Image")
)
} else if (behavior == "upload") {
fileInput("file_upload", label = h5("Upload an Image:"))
} else {
stop("Invalid configuration. Please chose 'fetch-image-url' or 'upload'")
}
})

# handle upload
observe({
req(input$file_upload)
upload_file <- input$file_upload
image_path(upload_file$datapath[[1]])
})

# handle fetch-image-url
observeEvent(input[["fetch-image-url"]], {
req(input$file1)
tryCatch({
# Fetch image from URL
temp_fetch_image_url <- fs::file_temp(image_prefix, ext = ".jpg")
downloader::download(input$file1, temp_fetch_image_url)

image_path(temp_fetch_image_url)
}, error = function(e){
# usually, you would not expose this to the user
# without a little sanitization
showNotification(as.character(safeError(e)), type = "warning")
})
})

output$contents <- renderTable({
req(image_path())

tryCatch(
{
# Download image from URL
downloader::download(input$file1, "image")

# Call function from PyTorch Python script to classify image
results <- classify_image_pytorch(image_path="image")
results <- classify_image_pytorch(image_path=image_path())
},
error = function(e) {
stop(safeError(e))
# usually, you would not expose this to the user
# without a little sanitization
showNotification(as.character(safeError(e)), type = "warning")
}
)
return(results)
})

# render the image
output$image1 <- renderImage({
req(input$file1)
tryCatch(
{
input$file1
},
error = function(e) {
stop(safeError(e))
}
)
req(image_path())

# Copy the image to temp space
new_path <- fs::file_copy(image_path(), fs::file_temp(image_prefix, ext = ".jpg"))

# Return a list containing the filename
if(is.null(input$file1)) {
if(is.null(new_path)) {
return(NULL)
}
else {
return(list(src = "image"))
return(list(src = new_path, style = htmltools::css(width = "100%")))
}
})

observe({
x = input$oil_platform
image_url = "https://upload.wikimedia.org/wikipedia/commons/a/a1/Oil_platform.jpeg"
updateTextInput(session, "file1", value = paste(image_url))
})

observe({
x = input$truck
image_url = "https://upload.wikimedia.org/wikipedia/commons/6/6c/Toyota-1984-truck.jpg"
updateTextInput(session, "file1", value = paste(image_url))
})

observe({
x = input$flower
image_url = "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fd/Aster_Tataricus.JPG/612px-Aster_Tataricus.JPG"
updateTextInput(session, "file1", value = paste(image_url))
})

observe({
x = input$cat
image_url = "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7f/Egyptian_Mau_Bronze.jpg/611px-Egyptian_Mau_Bronze.jpg"
updateTextInput(session, "file1", value = paste(image_url))
})

observe({
x = input$dog
image_url = "https://upload.wikimedia.org/wikipedia/commons/e/e4/Border_Collie_600.jpg"
updateTextInput(session, "file1", value = paste(image_url))
})
# default images
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for making these example images self-contained!

observeEvent(input$oil_platform, image_path("./img/oil_platform.jpg"))
observeEvent(input$truck, image_path("./img/truck.jpg"))
observeEvent(input$flower, image_path("./img/flower.jpg"))
observeEvent(input$cat, image_path("./img/cat.jpg"))
observeEvent(input$dog, image_path("./img/dog.jpg"))

}

Expand All @@ -84,8 +100,8 @@ ui <- fluidPage(
titlePanel("Image Classifier"),
sidebarLayout(
sidebarPanel(
textInput("file1", label = h5("Enter Image URL:"), value = ""),
helpText("Your image will be downloaded and classified using Tensorflow in Python."),
uiOutput("image_selector"),
helpText("Your image will be classified using Tensorflow in Python."),
helpText("The resulting predictions will be shown along with their confidence level."),
hr(),
helpText("Or, choose an example image:"),
Expand All @@ -103,7 +119,7 @@ ui <- fluidPage(
mainPanel(
# Output
tableOutput("contents") %>% withSpinner(),
imageOutput("image1") %>% withSpinner(color = "#ffffff")
imageOutput("image1", height = NULL) %>% withSpinner(color = "#ffffff")
)
)
)
Expand Down
4 changes: 4 additions & 0 deletions image-classifier/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
default:
image: "fetch-image-url"
quickstart:
image: "upload"
Binary file added image-classifier/img/cat.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image-classifier/img/dog.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image-classifier/img/flower.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image-classifier/img/oil_platform.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image-classifier/img/truck.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading