Les fichiers FCS exportés de FlowJo sont parfois incorrects : ils ne contiennent pas les mots clés $BEGINDATA et/ou $ENDDATA imposés par le standard FCS 3.0. De ce fait, ces fichiers ne sont pas compatibles avec CytoBank par exemple. Comment résoudre ce problème ?

On va utiliser quelques lignes de R pour lire le fichier exporté et le ré-écrire. En effet, le package flowCore a prévu l’absence de ces mots clés lors de la lecture. Lors de l’écriture des données FCS, tous les mots clés seront bien présents comme l’impose le standard.

Vous pouvez vérifier qu’un fichier respecte le standard FCS en l’envoyant pour un examen sur flowIO.

Version courte

Lancez RStudio (ou RGui) et tapez les commandes suivantes à adapter en fonction de l’emplacement de vos fichiers.

# Lancer flowCore
library(flowCore)
# Charger le fichier FCS dans la variable fr
# Le nom et l'emplacement du fichier FCS est défini dans la chaîne de caractères entre guillemets
# Windows: utiliser des / et non des \ pour séparer les dossiers
fr <- read.FCS("C:/KCT26-32/T-kct26-1514780-DIAG.exported.FCS3.fcs")
# Ecrire la variable fr dans un nouveau fichier FCS (nouveau nom)
write.FCS(fr, file = "C:/KCT26-32/T-kct26-1507258-DIAG_fixed.fcs")
# Le nouveau fcs peut être importé dans Cytobank et lu par VisNE et Citrus

Le nouveau fichier FCS peut être exporté dans Cytobank et lu par VisNE et Citrus.

Version détaillée

# Lancer flowCore
library(flowCore)

# Charger le fichier FCS dans la variable fr
# Le nom et l'emplacement du fichier FCS est défini dans la chaîne de caractères entre guillemets
# Windows: utiliser des / et non des \ pour séparer les dossiers
fr <- read.FCS("C:/KCT26-32/T-kct26-1514780-DIAG.exported.FCS3.fcs") 
## Warning messages:
## 1: Missing the required $BEGINDATA keyword! Reading data based on information in the FCS HEADER only.
## 2: Missing the required $ENDDATA keyword! Reading data based on information in the FCS HEADER only.
# Ecrire la variable fr dans un nouveau fichier FCS (nouveau nom)
write.FCS(fr,file="C:/KCT26-32/T-kct26-1507258-DIAG_fixed.fcs")
## [1] "C:/KCT26-32/T-kct26-1507258-DIAG_fixed.fcs"
## Warning message:
## In write.FCS(fr, file = "C:/KCT26-32/T-kct26-1507258-DIAG_fixed.fcs") :
## 'write.FCS' is not fully tested and should be considered as experimental.

Le nouveau fichier FCS peut être exporté dans Cytobank et lu par VisNE et Citrus.

Automatisation pour plusieurs fichiers

Pour ré-écrire plusieurs fichiers et automatiser cette correction, on va grouper les fichiers. Les fichiers FCS à corriger seront placés dans un dossier. Tous les fichiers de ce dossier seront lus et ré-écrits dans un autre dossier. On va réaliser une boucle qui va lire un par un les fichiers du dossier d’entrée, traiter le fichier courant (ici la correction est effectuée implicitement lors de la lecture) et écrire le résultat dans un fichier FCS dans le dossier de sortie (alias résultat). Ici on choisit d’enregistrer les fichiers de sortie dans un sous dossier nommé “fixed”. Le script suivant comporte une partie configuration et une partie traitement. Vous devez adapter la partie configuration à vos besoins en spécifiant le dossier où se situent les fichiers à corriger. Vous n’avez pas à changer la partie traitement. Une fois le code modifié, exécutez-le dans R. Comme l’écriture des fichiers ne se fait pas dans le même dossier que les fichiers d’entrée, ces derniers sont à l’abri (a priori).

# Configuration
# Localisation des fichiers à modifier
inputDir = "C:/Data/active/impact_scripts_R"
# Localisation du dossier de sortie
outputDir = file.path(inputDir, "fixed")
# Motif du nom des fichiers FCS
motif = "*.fcs"
# Traitement
if (!dir.exists(outputDir)) dir.create(outputDir)
# Les fichiers à modifier sont mis dans une liste de fichiers
files <- list.files(path = inputDir, pattern = motif, full.names = FALSE, recursive = FALSE)
# Boucle sur les fichiers : lecture, écriture
for (filename in files) {
  fr <- read.FCS(file.path(inputDir, filename)) # load file
  write.FCS(fr, file.path(outputDir, filename)) # write fixed version
}

A noter :

  • Vous devez changer C:/Data/active/impact_scripts_R par le nom complet du dossier qui contient les fichiers à corriger.
  • La fonction file.path permet d’assembler un nom de dossier parent à un nom de fichier ou de sous-dossier. Elle gère automatiquement le fait que le caractère séparant les dossiers est différent sous Windows, Mac et Linux.
  • Le dossier de sortie est créé s’il n’existe pas.
  • Le motif “*.fcs” permet de sélectionner tous les fichiers qui se terminent par .fcs. Le symbole “*” du motif correspond à “n’importe quoi”. Il est donc possible de définir un motif plus complexe avant “.fcs” pour sélectionner un sous-ensemble des fichiers.
  • La liste contient le nom des fichiers sans le chemin d’accès (option full.names = FALSE) et ne recherche que les fichiers du dossier d’entrée (option recursive = FALSE). On peut afficher le contenu de cette liste en tapant le nom de la variable, c’est à dire files, dans la console R.
  • L’instruction for réalise la boucle. On peut utiliser l’instruction lapply à la place comme ci-dessous.
lapply(files, function(x){
  fr <- read.FCS(file.path(mainDir, x)) # load file
  write.FCS(fr, file.path(mainDir, "fixed", x)) # write fixed version
})

Options de lecture

La fonction read.FCS comporte bon nombre d’options. Pour des fichiers de cytométrie de flux, il peut être intéressant de connaître ou d’ajouter les suivantes de façon à ne pas modifier les intensités lors de la lecture du fichier FCS :

  • transformation = FALSE
    La valeur par défaut est linearize, ce qui consiste à appliquer une transformation linéaire. La valeur FALSE indique de n’effectuer aucune transformation des intensités, et n’ajoute pas de mots clés flowcore_xxx dans l’entête des fichiers. Si le mot clé transformation est défini dans l’entête et vaut custom ou applied, aucune transformation d’intensité ne sera effectuée quelle que soit cette option.
  • min.limit = NULL
    La valeur par défaut est soit -111 (anciennes versions de flowCore), soit NULL (versions récentes). Cette option définit un plancher pour les intensités et s’aligne sur  le comportement de FlowJo qui utilise la valeur -111.
  • truncate_max_range = FALSE
    La valeur par défaut est TRUE, ce qui consiste à appliquer un plafond aux intensités. Le plafond est défini par le range propre à chaque marqueur (mot clé $PxR).
  • D’autres options sont disponibles voir la documentation de read.FCS.

Au final, l’instruction de lecture de fichier FCS peut être une commande plus riche :

fr <- read.FCS(file.path(inputDir, filename), transformation = FALSE, min.limit = NULL, truncate_max_range = FALSE)