From eb10dc5df139c4f88d53ce51da50a313c3180f48 Mon Sep 17 00:00:00 2001 From: Maximilian Bertsch Date: Mon, 24 Jan 2022 11:13:37 +0100 Subject: [PATCH 1/3] added only_text attribute Thereby only the header and text data can be read. --- flowio/flowdata.py | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/flowio/flowdata.py b/flowio/flowdata.py index b3188e9..6e5fbaf 100644 --- a/flowio/flowdata.py +++ b/flowio/flowdata.py @@ -30,7 +30,8 @@ class FlowData(object): :param filename_or_handle: a path string or a file handle for an FCS file :param ignore_offset_error: option to ignore data offset error (see above note), default is False """ - def __init__(self, filename_or_handle, ignore_offset_error=False): + + def __init__(self, filename_or_handle, ignore_offset_error=False, only_text=False): if isinstance(filename_or_handle, basestring): self._fh = open(str(filename_or_handle), 'rb') else: @@ -86,12 +87,15 @@ def __init__(self, filename_or_handle, ignore_offset_error=False): if d_stop > self.file_size: raise EOFError("FCS header indicates data section greater than file size") - self.events = self.__parse_data( - self.cur_offset, - d_start, - d_stop, - self.text - ) + if not only_text: + self.events = self.__parse_data( + self.cur_offset, + d_start, + d_stop, + self.text + ) + else: + self.events = None self.channels = self._parse_channels() @@ -338,8 +342,8 @@ def __format_integer(b): return 'I' else: raise ValueError( - "Invalid integer bit size (%d) for event data. Compatible sizes are 8, 16, & 32." % b - ) + "Invalid integer bit size (%d) for event data. Compatible sizes are 8, 16, & 32." % + b) def _parse_channels(self): """ @@ -377,6 +381,10 @@ def write_fcs(self, filename, extra=None, extra_non_standard=None): :param extra_non_standard: an optional dictionary for adding extra non-standard keywords/values :return: None """ + if self.events is None: + raise Exception(("FlowData doesn't contain event data. This might" + "happen cause the fcs file was read with only_text=True parameter.")) + pnn_labels = [''] * len(self.channels) pns_labels = [''] * len(self.channels) From e83cafad96f5cf5549e034e50b2f1f37e0bad154 Mon Sep 17 00:00:00 2001 From: whitews Date: Thu, 27 Jan 2022 10:48:05 -0500 Subject: [PATCH 2/3] add docstring for new only_text option & minor modification to PR 11 --- flowio/flowdata.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/flowio/flowdata.py b/flowio/flowdata.py index 6e5fbaf..a458c6e 100644 --- a/flowio/flowdata.py +++ b/flowio/flowdata.py @@ -29,8 +29,9 @@ class FlowData(object): :param filename_or_handle: a path string or a file handle for an FCS file :param ignore_offset_error: option to ignore data offset error (see above note), default is False + :param only_text: option to only read the "text" segment of the FCS file without loading event data, + default is False """ - def __init__(self, filename_or_handle, ignore_offset_error=False, only_text=False): if isinstance(filename_or_handle, basestring): self._fh = open(str(filename_or_handle), 'rb') @@ -87,15 +88,15 @@ def __init__(self, filename_or_handle, ignore_offset_error=False, only_text=Fals if d_stop > self.file_size: raise EOFError("FCS header indicates data section greater than file size") - if not only_text: + if only_text: + self.events = None + else: self.events = self.__parse_data( self.cur_offset, d_start, d_stop, self.text ) - else: - self.events = None self.channels = self._parse_channels() @@ -342,8 +343,8 @@ def __format_integer(b): return 'I' else: raise ValueError( - "Invalid integer bit size (%d) for event data. Compatible sizes are 8, 16, & 32." % - b) + "Invalid integer bit size (%d) for event data. Compatible sizes are 8, 16, & 32." % b + ) def _parse_channels(self): """ @@ -382,8 +383,10 @@ def write_fcs(self, filename, extra=None, extra_non_standard=None): :return: None """ if self.events is None: - raise Exception(("FlowData doesn't contain event data. This might" - "happen cause the fcs file was read with only_text=True parameter.")) + raise AttributeError( + "FlowData instance does not contain event data. This might" + "occur if the FCS file was read with the only_text=True option." + ) pnn_labels = [''] * len(self.channels) pns_labels = [''] * len(self.channels) From f92c0a0d9c121118eea44581a1fee29e32512f68 Mon Sep 17 00:00:00 2001 From: whitews Date: Thu, 27 Jan 2022 10:48:24 -0500 Subject: [PATCH 3/3] add test for new only_text option --- flowio/tests/flowdata_tests.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/flowio/tests/flowdata_tests.py b/flowio/tests/flowdata_tests.py index 6e585b0..677f4ad 100644 --- a/flowio/tests/flowdata_tests.py +++ b/flowio/tests/flowdata_tests.py @@ -27,6 +27,12 @@ def test_event_count(self): def test_get_text(self): self.assertEqual(self.flow_data.text['cyt'], 'FACScan') + def test_load_only_text(self): + flow_data = FlowData('examples/fcs_files/3FITC_4PE_004.fcs', only_text=True) + + self.assertIsNone(flow_data.events) + self.assertRaises(AttributeError, flow_data.write_fcs, 'delete_this_file.fcs') + @staticmethod def test_load_fcs_from_memory(): with open('examples/fcs_files/3FITC_4PE_004.fcs', 'rb') as f: