Quickstart

readfcs is a lightweight open-source Python package for loading fcs files into AnnData objects.

  • Simply use read to get started.

  • Use ReadFCS class to access advanced features such as compensation.

  • Use view to inspect the raw content of the FCS file and debug failures in reading.

import readfcs

Data

Here we use a fcs file from Oetjen18.

datapath = readfcs.datasets.Oetjen18_t1()
datapath
'oetjen18_t1.fcs'

High level read() function: fcs -> AnnData

adata = readfcs.read(datapath)

Metadata is stored as a dictionary in adata.uns.meta

adata
AnnData object with n_obs × n_vars = 241552 × 20
    var: 'n', 'channel', 'marker', 'PnR', 'PnB', 'PnE', 'PnV', 'PnG'
    uns: 'meta'
adata.var
n channel marker PnR PnB PnE PnV PnG
FSC-A 1 FSC-A 262144 32 0,0 510 1.0
FSC-H 2 FSC-H 262144 32 0,0 510 1.0
FSC-W 3 FSC-W 262144 32 0,0 510 1.0
SSC-A 4 SSC-A 262144 32 0,0 310 1.0
SSC-H 5 SSC-H 262144 32 0,0 310 1.0
SSC-W 6 SSC-W 262144 32 0,0 310 1.0
CD95 7 R660-A CD95 262144 32 0,0 490 1.0
CD8 8 R780-A CD8 262144 32 0,0 475 1.0
CD27 9 B515-A CD27 262144 32 0,0 470 1.0
CXCR4 10 B710-A CXCR4 262144 32 0,0 417 1.0
CCR7 11 V450-A CCR7 262144 32 0,0 400 1.0
LIVE/DEAD 12 V545-A LIVE/DEAD 262144 32 0,0 495 1.0
CD4 13 V605-A CD4 262144 32 0,0 400 1.0
CD45RA 14 V655-A CD45RA 262144 32 0,0 375 1.0
CD3 15 V800-A CD3 262144 32 0,0 400 1.0
CD49B 16 G560-A CD49B 262144 32 0,0 400 1.0
CD14/19 17 G610-A CD14/19 262144 32 0,0 415 1.0
CD69 18 G660-A CD69 262144 32 0,0 470 1.0
CD103 19 G780-A CD103 262144 32 0,0 435 1.0
Time 20 Time 262144 32 0,0 0.01
adata.uns["meta"]["spill"]
CD95 CD8 CD27 CXCR4 CCR7 LIVE/DEAD CD4 CD45RA CD3 CD49B CD14/19 CD69 CD103
CD95 1.000000 0.097352 0.000000 0.007011 0.003501 0.000000 0.000354 0.040952 0.008773 0.000067 0.001176 0.181536 0.005969
CD8 0.067916 1.000000 0.000000 0.000000 0.023879 0.000257 0.000000 0.003852 0.100139 0.000877 0.000000 0.008990 0.083250
CD27 0.007903 0.000000 1.000000 0.007492 0.010284 0.027712 0.003897 0.001299 0.000216 0.012664 0.002588 0.000000 0.000000
CXCR4 0.054363 0.100434 0.000000 1.000000 0.024458 0.001439 0.000000 0.056397 0.194799 0.000491 0.000000 0.400014 0.119091
CCR7 0.002288 0.000000 0.000000 0.000000 1.000000 0.034874 0.003729 0.000909 0.000282 0.000107 0.000000 0.000000 0.000000
LIVE/DEAD 0.000000 0.000000 0.003884 0.000705 0.014092 1.000000 0.447288 0.144758 0.025271 0.000000 0.000000 0.000000 0.000000
CD4 0.009741 0.000263 0.000000 0.028274 0.080674 0.005858 1.000000 0.434510 0.085092 0.055112 0.390481 0.290524 0.012522
CD45RA 0.275534 0.028670 0.000000 0.015079 0.102571 0.005517 0.180690 1.000000 0.169154 0.000643 0.014777 0.120247 0.005286
CD3 0.022068 0.073814 0.000000 0.000000 0.099510 0.006832 0.000891 0.003268 1.000000 0.000507 0.000000 0.000000 0.027061
CD49B 0.001869 0.000000 0.000000 0.048687 0.002103 0.009783 0.038672 0.008945 0.001060 1.000000 0.400143 0.148085 0.004221
CD14/19 0.006566 0.000262 0.000000 0.177725 0.006049 0.000889 0.065991 0.022692 0.003962 0.124522 1.000000 0.493361 0.019125
CD69 0.191802 0.032179 0.000000 0.396688 0.003517 0.000172 0.000497 0.026221 0.009804 0.022587 0.010298 1.000000 0.050517
CD103 0.005300 0.105676 0.000000 0.016745 0.006381 0.000771 0.000631 0.000561 0.126363 0.049163 0.018982 0.008683 1.000000
adata.write("oetjen18_t1.h5ad")

Using FCSFile class for accessing attributes and compensation

ReadFCS class offers additional functionalities such as .compensate

fcsfile = readfcs.ReadFCS(datapath)

Data is stored as a DataFrane in .data

fcsfile.data.iloc[:5, 5:10]
5 6 7 8 9
0 70533.507812 441.750000 3679.349854 2144.219971 653.639954
1 73205.625000 747.839966 5599.679688 560.039978 336.179993
2 71534.648438 727.890015 785.459961 1148.939941 294.839996
3 90882.062500 281.579987 1558.380005 873.599976 250.379990
4 73053.210938 354.540009 47.309998 60.059998 115.439995

Metadata is stored as a dict in .meta, note all keys are lower cased and without the starting $.

# cytometer
fcsfile.meta.get("cyt")
'LSRFortessa'

Channels.

fcsfile.channels
PnN PnS PnR PnB PnE PnV PnG
n
1 FSC-A 262144 32 0,0 510 1.0
2 FSC-H 262144 32 0,0 510 1.0
3 FSC-W 262144 32 0,0 510 1.0
4 SSC-A 262144 32 0,0 310 1.0
5 SSC-H 262144 32 0,0 310 1.0
6 SSC-W 262144 32 0,0 310 1.0
7 R660-A CD95 262144 32 0,0 490 1.0
8 R780-A CD8 262144 32 0,0 475 1.0
9 B515-A CD27 262144 32 0,0 470 1.0
10 B710-A CXCR4 262144 32 0,0 417 1.0
11 V450-A CCR7 262144 32 0,0 400 1.0
12 V545-A LIVE/DEAD 262144 32 0,0 495 1.0
13 V605-A CD4 262144 32 0,0 400 1.0
14 V655-A CD45RA 262144 32 0,0 375 1.0
15 V800-A CD3 262144 32 0,0 400 1.0
16 G560-A CD49B 262144 32 0,0 400 1.0
17 G610-A CD14/19 262144 32 0,0 415 1.0
18 G660-A CD69 262144 32 0,0 470 1.0
19 G780-A CD103 262144 32 0,0 435 1.0
20 Time 262144 32 0,0 0.01

Header.

fcsfile.header
{'version': '3.0',
 'text_start': 256,
 'text_stop': 6333,
 'data_start': 6339,
 'data_stop': 19330498,
 'analysis_start': 0,
 'analysis_stop': 0}

Perform compensation.

fcsfile.compensate()

Check the compensated data.

fcsfile.data.iloc[:5, 5:10]
5 6 7 8 9
0 70533.507812 148.825683 3467.270412 2136.198753 412.369569
1 73205.625000 157.868760 5301.498694 526.322225 202.245785
2 71534.648438 -200.469627 424.040430 985.303260 89.175059
3 90882.062500 173.088739 1459.551784 870.436857 213.942965
4 73053.210938 343.537853 10.319622 59.458471 -10.948951

View the FCS file content

When reading in FCS file fails, you may view the content of the file to debug:

meta, data = readfcs.view(datapath)
meta
{'beginanalysis': '0',
 'endanalysis': '0',
 'beginstext': '0',
 'endstext': '0',
 'begindata': '6339',
 'enddata': '19330498           ',
 'fil': '2-13-17 T cell Panel_T_E_G05_004.fcs',
 'sys': 'Windows 7 6.1',
 'tot': '241552             ',
 'par': '20',
 'mode': 'L',
 'byteord': '4,3,2,1',
 'datatype': 'F',
 'nextdata': '0',
 'creator': 'BD FACSDiva Software Version 8.0',
 'tube name': 'T_E',
 'src': '2-13-17 T cell Panel',
 'experiment name': 'T_Memory_01-24-17',
 'guid': '641fcb4b-10df-4636-9325-31d9c563ae6b',
 'date': '10-SEP-2018',
 'btim': '16:02:38',
 'etim': '16:02:38',
 'cyt': 'LSRFortessa',
 'settings': 'Cytometer',
 'cytnum': 'H64717700086',
 'window extension': '10.00',
 'export user name': 'Administrator',
 'export time': '10-SEP-2018-16:02:38',
 'op': 'Administrator',
 'fsc asf': '0.69',
 'autobs': 'TRUE',
 'inst': ' ',
 'laser1name': 'Blue',
 'laser1delay': '0.00',
 'laser1asf': '0.78',
 'laser2name': 'Green',
 'laser2delay': '129.57',
 'laser2asf': '0.75',
 'laser3name': 'Red',
 'laser3delay': '97.14',
 'laser3asf': '0.57',
 'laser4name': 'UV',
 'laser4delay': '65.51',
 'laser4asf': '0.77',
 'laser5name': 'Violet',
 'laser5delay': '34.39',
 'laser5asf': '0.88',
 'plate name': '2-13-17 T-memory',
 'well id': 'G05',
 'plate id': 'dac8255f-b7a7-4020-97d4-b2f6547e9b8b',
 'timestep': '0.01',
 'spill': '13,R660-A,R780-A,B515-A,B710-A,V450-A,V545-A,V605-A,V655-A,V800-A,G560-A,G610-A,G660-A,G780-A,1,0.09735204394858232,0,0.007011172658837619,0.0035011622991608943,0,0.00035404250977172716,0.04095187696764509,0.008772588241008515,0.00006718020813517101,0.0011757471425244775,0.18153569419613963,0.005968917221960132,0.06791644502371093,1,0,0,0.023879362252194135,0.00025670476553774226,0,0.0038515097025606584,0.10013933246492365,0.0008770213569619933,0,0.00898974609423693,0.08325038424368773,0.007903499293392215,0,1,0.007492393786301646,0.010283780654816615,0.027712124248782985,0.0038970121720466712,0.0012990020263950173,0.00021629858651356506,0.01266409607946262,0.0025882796145041556,0,0,0.05436312961231171,0.10043354629620793,0,1,0.024457762534528842,0.001438755465565026,0,0.056396675477137725,0.19479870707404334,0.000491448523178251,0,0.40001423048531476,0.1190912528716946,0.002287714239639772,0,0,0,1,0.03487442489089123,0.0037287139545777908,0.0009086773768937114,0.00028199849105311033,0.00010702921799101015,0,0,0,0,0,0.0038836205805840925,0.0007053289300151003,0.014091525138545245,1,0.44728798423591304,0.14475792628516834,0.025271493638284688,0,0,0,0,0.00974125419862363,0.0002632132492050533,0,0.028274442964530383,0.08067419666935374,0.005858194367548331,1,0.434510053021289,0.08509239460644547,0.05511239401998082,0.3904807885835627,0.2905240045157824,0.012521708087597751,0.2755338450115204,0.028669650806175347,0,0.015079483546644151,0.102570606503713,0.005517449433296845,0.18068968375282926,1,0.1691535921475564,0.0006425502129023819,0.014776528843108972,0.12024655594625697,0.005286186820275574,0.022068162838460997,0.07381386891333566,0,0,0.099510015568334,0.006832379999899456,0.0008911834617986114,0.003267506538950563,1,0.0005074772359286441,0,0,0.027061076438995062,0.0018686282052520868,0,0,0.04868731478774934,0.0021034272836935267,0.009782626583969086,0.0386724857643002,0.00894462348769668,0.0010604166688987216,1,0.4001430473835212,0.14808536564415026,0.004220634283512854,0.006566059761305688,0.00026249819602128244,0,0.1777247143714281,0.006048688795358408,0.000888593600713252,0.06599068699071457,0.0226917657843669,0.003962258512920238,0.12452216889188006,1,0.4933609577028777,0.019125294105050362,0.19180239226858745,0.03217920077179705,0,0.3966881695505515,0.0035165238828971284,0.0001720123679770089,0.000496902183943976,0.026221297612479304,0.00980396608434816,0.022587068268836587,0.010298003599584191,1,0.050516820746677044,0.005299504824161491,0.10567559749222866,0,0.016744741148072208,0.006381246196506204,0.0007714156592623044,0.0006311226304001263,0.0005609946143672685,0.1263631034468686,0.049162630766073634,0.01898239672234503,0.008682800049188222,1',
 'apply compensation': 'TRUE',
 'threshold': 'FSC,5000',
 'p1n': 'FSC-A',
 'p1r': '262144',
 'p1b': '32',
 'p1e': '0,0',
 'p1v': '510',
 'p1g': '1.0',
 'p1display': 'LIN',
 'p1bs': '0',
 'p1ms': '0',
 'p2n': 'FSC-H',
 'p2r': '262144',
 'p2b': '32',
 'p2e': '0,0',
 'p2v': '510',
 'p2g': '1.0',
 'p2display': 'LIN',
 'p2bs': '0',
 'p2ms': '0',
 'p3n': 'FSC-W',
 'p3r': '262144',
 'p3b': '32',
 'p3e': '0,0',
 'p3v': '510',
 'p3g': '1.0',
 'p3bs': '-1',
 'p3ms': '0',
 'p4n': 'SSC-A',
 'p4r': '262144',
 'p4b': '32',
 'p4e': '0,0',
 'p4v': '310',
 'p4g': '1.0',
 'p4display': 'LIN',
 'p4bs': '0',
 'p4ms': '0',
 'p5n': 'SSC-H',
 'p5r': '262144',
 'p5b': '32',
 'p5e': '0,0',
 'p5v': '310',
 'p5g': '1.0',
 'p5display': 'LIN',
 'p5bs': '0',
 'p5ms': '0',
 'p6n': 'SSC-W',
 'p6r': '262144',
 'p6b': '32',
 'p6e': '0,0',
 'p6v': '310',
 'p6g': '1.0',
 'p6bs': '-1',
 'p6ms': '0',
 'p7n': 'R660-A',
 'p7s': 'CD95',
 'p7r': '262144',
 'p7b': '32',
 'p7e': '0,0',
 'p7v': '490',
 'p7g': '1.0',
 'p7display': 'LOG',
 'p7bs': '5464',
 'p7ms': '0',
 'p8n': 'R780-A',
 'p8s': 'CD8',
 'p8r': '262144',
 'p8b': '32',
 'p8e': '0,0',
 'p8v': '475',
 'p8g': '1.0',
 'p8display': 'LOG',
 'p8bs': '157',
 'p8ms': '0',
 'p9n': 'B515-A',
 'p9s': 'CD27',
 'p9r': '262144',
 'p9b': '32',
 'p9e': '0,0',
 'p9v': '470',
 'p9g': '1.0',
 'p9display': 'LOG',
 'p9bs': '102',
 'p9ms': '0',
 'p10n': 'B710-A',
 'p10s': 'CXCR4',
 'p10r': '262144',
 'p10b': '32',
 'p10e': '0,0',
 'p10v': '417',
 'p10g': '1.0',
 'p10display': 'LOG',
 'p10bs': '4284',
 'p10ms': '0',
 'p11n': 'V450-A',
 'p11s': 'CCR7',
 'p11r': '262144',
 'p11b': '32',
 'p11e': '0,0',
 'p11v': '400',
 'p11g': '1.0',
 'p11display': 'LOG',
 'p11bs': '682',
 'p11ms': '0',
 'p12n': 'V545-A',
 'p12s': 'LIVE/DEAD',
 'p12r': '262144',
 'p12b': '32',
 'p12e': '0,0',
 'p12v': '495',
 'p12g': '1.0',
 'p12display': 'LOG',
 'p12bs': '177',
 'p12ms': '0',
 'p13n': 'V605-A',
 'p13s': 'CD4',
 'p13r': '262144',
 'p13b': '32',
 'p13e': '0,0',
 'p13v': '400',
 'p13g': '1.0',
 'p13display': 'LOG',
 'p13bs': '2348',
 'p13ms': '0',
 'p14n': 'V655-A',
 'p14s': 'CD45RA',
 'p14r': '262144',
 'p14b': '32',
 'p14e': '0,0',
 'p14v': '375',
 'p14g': '1.0',
 'p14display': 'LOG',
 'p14bs': '2322',
 'p14ms': '0',
 'p15n': 'V800-A',
 'p15s': 'CD3',
 'p15r': '262144',
 'p15b': '32',
 'p15e': '0,0',
 'p15v': '400',
 'p15g': '1.0',
 'p15display': 'LOG',
 'p15bs': '700',
 'p15ms': '0',
 'p16n': 'G560-A',
 'p16s': 'CD49B',
 'p16r': '262144',
 'p16b': '32',
 'p16e': '0,0',
 'p16v': '400',
 'p16g': '1.0',
 'p16display': 'LOG',
 'p16bs': '679',
 'p16ms': '0',
 'p17n': 'G610-A',
 'p17s': 'CD14/19',
 'p17r': '262144',
 'p17b': '32',
 'p17e': '0,0',
 'p17v': '415',
 'p17g': '1.0',
 'p17display': 'LOG',
 'p17bs': '4480',
 'p17ms': '0',
 'p18n': 'G660-A',
 'p18s': 'CD69',
 'p18r': '262144',
 'p18b': '32',
 'p18e': '0,0',
 'p18v': '470',
 'p18g': '1.0',
 'p18display': 'LOG',
 'p18bs': '3799',
 'p18ms': '0',
 'p19n': 'G780-A',
 'p19s': 'CD103',
 'p19r': '262144',
 'p19b': '32',
 'p19e': '0,0',
 'p19v': '435',
 'p19g': '1.0',
 'p19display': 'LOG',
 'p19bs': '225',
 'p19ms': '0',
 'p20n': 'Time',
 'p20r': '262144',
 'p20b': '32',
 'p20e': '0,0',
 'p20g': '0.01',
 'p20bs': '0',
 'p20ms': '0',
 'cst setup status': 'SUCCESS',
 'cst beads lot id': '74538',
 'cytometer config name': 'Copy of 5 Lasers UV SORP  2B 6V 2UV 3R 5Gr',
 'cytometer config create date': '2014-01-29T14:36:56-08:00',
 'cst setup date': '2016-12-21T08:52:55-08:00',
 'cst baseline date': '2016-10-28T10:11:58-07:00',
 'cst beads expired': 'False',
 'cst performance expired': '2016-12-22T08:52:55-08:00',
 'cst regulatory status': 'RUO Performance Check'}
data
array([[ 1.9179240e+04,  1.8276000e+04,  6.8774938e+04, ...,
         7.9200000e+02,  1.6515000e+03,  6.1099998e+01],
       [ 8.3688031e+04,  7.4669000e+04,  7.3451891e+04, ...,
         5.0250000e+02,  1.0297500e+03,  6.1200001e+01],
       [ 5.8169762e+04,  4.8933000e+04,  7.7906797e+04, ...,
         7.6650000e+02,  3.7425000e+02,  6.1299999e+01],
       ...,
       [ 8.4283496e+03,  8.4600000e+03,  6.5290824e+04, ...,
         2.4000000e+02, -2.0250000e+01,  9.9905000e+03],
       [ 1.3052868e+05,  1.1605300e+05,  7.3710523e+04, ...,
         1.3522500e+03,  7.6500000e+01,  9.9905996e+03],
       [ 1.0954095e+05,  9.8525000e+04,  7.2863508e+04, ...,
         9.1725000e+02,  4.9500000e+01,  9.9907002e+03]],
      shape=(241552, 20), dtype=float32)