数年前、FCSファイルをタブ区切り形式に変換するPythonスクリプトを作成しました。フォーマットの説明が提供するすべての可能性を処理することにはほど遠いものでしたが、少なくとも私たちのマシンの1つで生成されたファイルのいくつかでは機能しました: http://www.igh.cnrs.fr/equip/Seitz/ en_equipe-programmes.html
私が見つけたフォーマットドキュメントはデコードを有効にしましたが(あなたが言及したpdfのセクション3を参照)、バイナリモードでデータを読み取る必要があります。
この形式(および、おそらく他の多くのバイナリ形式)の一般的な考え方は、ファイルの先頭にヘッダーゾーンがあり、ファイルの残りの部分がどのように構成されているかを示す番号をエンコードするフィールドの数が定義されていることです。したがって、最初のフェーズは、フォーマットのドキュメントに記載されている説明に従って、このヘッダーを解析することです。ヘッダーから抽出された情報は、フォーマットのドキュメントに記載されているルールに従って、データの場所とエンコード方法を示します。
これが役立つ場合があります。記録としては、次のとおりです。上記のスクリプトからのコード(コメントを削除し、その一部はフォーマットドキュメントからコピーしただけで、いくつか追加した後):
#!/ usr / bin / env python "" "このスクリプトは、FCSフローサイトメトリーデータを読み取ろうとします。ここにある情報に触発されたフォーマット解析:http://isac-net.org/Resources-for-Cytometrists/Data-Standards/ Data-File-Standards / Flow-Cytometry-Data-File-Format-Standards.aspx "" "import re#バイナリエンコードされたデータをデコードするにはimport structimport sysclass Parameter(object):" ""このオブジェクトは、次のようなパラメータータイプの1つを表します。 FCSファイルのDATAセグメントに存在します。 "" "__slots__ =(" p_name "、" p_bits "、" p_range "、" p_ampl "、" parser ")def __init __(self、p_name、p_bits、p_range、p_am pl):self.p_name = p_name self.p_bits = p_bits self.p_range = p_range self.p_ampl = p_ampl
#データセグメント内のパラメータの値を解析するための関数self.parser = None ################################ ###############ここで、他の部分がどこにあるかを示すヘッダー部分##の解析を開始します。 ############################################### f =オープン(sys.argv [1]、 "rb")#フォーマット名は6文字でエンコードされます#ASCII文字は1つのoctetfile_format = "" .join([f.read(1)for __ in range(6)でコード化されます])sys.stdout.write( "Format:%s \ n"%file_format)#フォーマットの説明では、スキップする4つのオクテットを予約しています= f.read(4)#8つのオクテットチャンクは、異なる部分の開始位置と終了位置をエンコードしますdatatext_start = int(f.read(8).strip( ""))text_end = int(f.read(8).strip( ""))data_start = int(f.read(8).strip( " "))data_end = int(f.read(8).strip(" "))analysis_start = int(f.read(8).strip(" "))analysis_end = int(f.read(8).strip( ""))if(analysis_start and analysis_end):sys.stderr.write( "FCSファイルのANALYSISセグメントを処理できません。\ n")################## ###################################ここで、「TEXT」部分##の解析を開始します。適切なデータは整理されています############################################# ######## f.seek(text_start)#最初の文字プライマリTEXTセグメントにはASCII区切り文字があります。sep= f.read(1)if sep not in ["_"、 "@"]:alt_sep = "_ @ _" elif sep not in ["_"、 " | "]:alt_sep =" _ | _ "else:sep not in [" + "、" | "] alt_sep =" + | + "text_segment = f.read(text_end --text_start)fields = text_segment.split(sep )info = {} i = 0while i < len(fields)-1:key = fields [i] i + = 1 val = fields [i] i + = 1#キーワードは大文字と小文字を区別せず、ファイルに書き込むことができます小文字、大文字、またはその2つの#混合。ただし、FCSファイルリーダーはキーワードの大文字小文字を無視する必要があります。キーワード値は、#小文字、大文字、またはその2つの組み合わせにすることができます。キーワード値では大文字と小文字が区別されます。 info [key.upper()] = val
「%sイベントが検出されました。」と出力します。 %info ["$ TOT"] print "各イベントは%sパラメータによって特徴付けられます"%info ["$ PAR"] if info ["$ NEXTDATA"]!= "0":sys.stderr.write( "その他データはファイルに存在しますが、解析されていません。\ n ")#L-リストモード。イベントごとに、各パラメーターの値は、#パラメーターが記述されている順序で保管されます。パラメータ1に予約されているビット数は、#$ P1Bキーワードを使用して記述されます。データセットごとにリストモードデータのセットは1つだけです。 $ DATATYPE#キーワードは、データ形式を記述します。モードCおよびモードUのデータはモードLのデータから作成できるため、これはフロー#サイトメトリーデータの保存に最も用途の広いモードです。assertinfo["$ MODE"] == "L" parameters = []#インデックスparametersp_indices = range(1、int(info ["$ PAR"])+ 1)for i in p_indices:p_name = info ["$ P%dN"%i] p_bits = info ["$ P%dB"%i] p_range = info ["$ P%dR"%i] p_ampl = info ["$ P%dE"%i] parameters.append(Parameter(p_name、p_bits、p_range、p_ampl))sys.stdout.write( "パラメーターare:\ n%s \ n "%" \ t ".join([パラメーターのパラメーターのpar.p_name]))#32ビットワードはどのように編成されますかif info [" $ BYTEORD "] ==" 4,3,2 、1 ":endianness =" > "else:endianness =" < "assert info [" $ BYTEORD "] ==" 1,2,3,4 "#ドキュメントの単なるコピーである長いコメントを削除しました#データのタイプ:ifinfo ["$ DATATYPE"] == "I":パラメーターのパラメーターの場合:nb_bits = int(par.p_bits)assert nb_bits%8 == 0 nb_bytes = nb_bits / 8#unpackiのフォーマット文字列を決定しますng(https://docs.python.org/2/library/struct.htmlを参照)if nb_bytes == 1:c_type = "B" #unsigned char elif nb_bytes == 2:c_type = "H" #unsigned short elif nb_bytes == 4:c_type = "L" #unsigned long elif nb_bytes == 8:c_type = "Q" #unsigned long long else:
ValueError、 "バイト数(%d)が整数に対して無効です(https://docs.python.org/2/library/struct.html#byte-order-size-and-alignmentを参照)。" %nb_bytes fmt = "%s%s"%(endianness、c_type)p_range = int(par.p_range)def parser(data):value = struct.unpack(fmt、data.read(nb_bytes))[0] try: AssertionErrorを除く値<p_rangeをアサートします:print "Value%s high than%d"%(str(value)、p_range)return value par.parser = parser passelse:raise NotImplementedError、 "これまでに実装されたのは整数値の解析のみです。 "out_file = open(sys.argv [2]、" w ")out_file.write("#増幅_types \ t "+" \ t ".join([par.p_ampl for par in parameters])+" \ n " )out_file.write( "parameters \ t" + "\ t" .join([par.p_name for par in parameters])+ "\ n")i = 1 ############# ##################################ここで、適切なデータの解析を開始します######## ####################################### f.seek(data_start)while f.tell( )< data_end:values = [] for par in parameters:values.append(par.parser(f))out_f ile.write( "%d \ t"%i + "\ t" .join(map(str、values))+ "\ n")i + = 1out_file.close()f.close()