Most of the time, if you are resorting to "search/replace" technique, more than one pass may be required. To make this process easy, FlowJo supports a scripted language to aid you. You can create external text files which will contain the types of rules and changes, and execute them as "scripts". FlowJo's scripting mechanism will allow you to change keywords for as many samples and as many values as you require.
This post will amend the existing documentation on this topic, found here.
What you will need:
- FlowJo V8
- some plain-text editor
- at least one round tuit (optional)
Note: All scripts mentioned below will be loaded into FlowJo using the button "Load and Execute Changes", available in the "Replace Keyword Values" dialog. To open this dialog, click Workspace menu, Search/replace...
Note: we will be using TAB character to separate the terms, unless otherwise noted. If you copy/paste bits of code from this post, the tabs will be converted to spaces - FYI.
Note: K=keyword, E=evaluator or logic statement, A=action, V=value
Search and Replace
Syntax:
Search K E V1 S V2
where:
K is the keywords' name
E is your choice of {equals,contains,starts,ends}
V1 and V2 are the original and replacement values, respectively.
S is your choice of {Replace search, Replace keyword}
Note: Replace "search" vs. "keyword": if you replace "search" then you're matching against just the portion of the keyword value, ex. the "FITC" in "CD3 FITC". If you replace "keyword" then you're replacing the whole keyword value if it contains your search string. So "CD4 FITC" and "CD3 FITC" will both be replaced to "fluorescein" - ie. both will be identical!!!
Tip: if you leave V1 blank, this is equivalent to the wildcard *anykeyword*.
Examples:
Search $P3S contains FITC Replace search Fluorescein
If a sample keyword $P3S is "CD3 FITC" then the value is replaced with "CD3 Fluorescein".
Search $P3S equals Replace keyword Fluorescein
You might think this statement is missing "V1, but in fact V1 is a blank (ie. two tabs between "equals and Replace). THIS WILL NOT WORK. if you want to fill-in values into blank keywords, use "define" (see below.)
Copy EXPERIMENT NAME $date
Search $date starts prefix- Replace search
Search $date ends -suffix1 Replace search
Search $date ends -suffix2 Replace search
// end of file
This is an example script based on a support call from today. This will take a bit longer to explain - this researcher has data files which are missing $date keyword. The date was instead buried in the value of another keyword "EXPERIMENT NAME", with the syntax "prefix-date-suffix1" or "prefix-date-suffix2". Also, this person was using "experiment name" keyword in another script (compensation) so we could not alter the values directly.
The script above copies all values of "EXPERIMENT NAME" for all files into a new (or existing) keyword $date. It then strips the values of the new $date keyword of prefixes and suffices, leaving only "date".
The last character on each of the "Search" lines is a tab - therefore it was necessary to add the additional //end of file line. Otherwise the script would not run.
Search and Define (Insert)
Syntax:
Define K1 E V1 K2 V2
where:
K1 and K2 are the original and destination keywords, respectively.
E is your choice of {equals,contains,starts,ends}
V1 and V2 are the original and replacement values, respectively.
Examples:
Define $PAR equals 5 $numberOfParameters five
If your $PAR keyword (number of parameters) was set to 5, this script would create (or fill an existing keyword) $numberOfParameters and set the value to "five".
"define" will play an important role in the "complex operations" section below.
Copy KW value
Syntax:
Copy K1 K2
where K1,K2 are original and destination keywords, respectively. If K2 does not exist, it will be created. This works like "define" but without the matching part.
Merge KW value
Syntax:
Merge K1 K2
For each sample, copy the value of K1 into K2, but only if the K2 does not already have a value in it. (I.e., Copy if blank destination).
Example:
This command seems silly, since if K2 is blank, this is just a copy.. I'll investigate. To be revisited..
Concatenate KW's.
Syntax:
Concatenate K V1 V2 Vn
This command concatenates multiple values (V1, V2...Vn) and stores the result into the keyword "K". V1 and V2 could either be keywords, or text. If text, include "double quotes" around it. If K does not exist, it will be created.
Example:
Concatenate $patient name $firstname $lastname
assuming values $firstname=maciej $lastname=simm, this returns a keyword "$patient name" with a value "maciejsimm". What if we want to separate them with a coma and a space character?
Concatenate $temp $lastnmame ", "
Concatenate $patient name $temp $firstname
This time, we write a temporary keyword where the value of keyword "$firstname" is merged with the text ", ". Then, we merge that temp keyword with the lastname and store the result "Simm, Maciej" in the keyword $patien name.
Complex Operations
As you may have already noticed, a few examples above include more than one statement. These are examples of complex operations - ie. a series of search/replace operations done in some kind of sequential order.
syntax:
Join
Match K {values..}
Define K {values..}
Conditional K {values..} K2 E V
EndJoinNote: "Conditional" operator is a special case of "Define" where a destination keyword "K2" is "E"valuated (equals, contains, starts, ends) for "V"alue.
Complex operations are put inside Join/EndJoin statements. Between, you can have as many match/define/conditional statements as you need to.
Let's try some examples:
You have multiple "panels" (sets of reagents) in your acquisition, but there is no keyword "panel". However, each panel has different combinations of reagents. Reagents are annotated in the $P# keywords.
Your FlowJo template relies on the value of $panel to route samples towards different gating trees. Therefore you need to assign values to this keyword, by hard-coding these reagent combos into a script and ask flowjo to assign a "panel" value based on this. Let's assume 2 panels for simplicity, first two tubes are a "T cell" panel, last two a "B cell" panel:
$p3 $p4 $p5 $panel
CD45 CD3 TCRgd
CD3 CD4 CD8
Cd45 CD19 CD20
CD19 Kappa Lambda
We know if a tube has {$p3="CD3" & $p4="CD4" & $p5="CD8" } it is a T panel, etc.. Here's a script which will fill the $panels for us:
Join
Match $p3 CD45 CD3 CD45 CD19
Match $p4 CD3 CD4 CD19 Kappa
Match $p5 TCRgd CD8 CD20 Lambda
Define $panel T T B B
EndJoin
This reads the same as:
If $p3=CD45 and $p4=CD3 and $p5=TCRgd, make $panel="T"
If $p3=CD19 and $p4=Kappa and $p5=Lambda, make $panel="B"
To see the difference between "define" and "conditional", let's throw in a kink where we want to make this adjustment only on $date=01/02/2003:
Join
Match $p3 CD45 CD3 CD45 CD19
Match $p4 CD3 CD4 CD19 Kappa
Match $p5 TCRgd CD8 CD20 Lambda
Conditional $panel T T B B $date equals 01/02/2003
EndJoin
Comments