diff --git a/cellacdc/acdc_regex.py b/cellacdc/acdc_regex.py index fc355f4d..e4550bfb 100644 --- a/cellacdc/acdc_regex.py +++ b/cellacdc/acdc_regex.py @@ -23,13 +23,32 @@ def get_function_names(text, include_class_methods=True): pattern = r'\ndef\s+([a-zA-Z_]\w*)\s*\(' return re.findall(pattern, text) -def is_alphanumeric_filename(text, allow_space=True): +def is_alphanumeric_filename( + text, + allow_space=True, + allowed: str | list[str] | None=None + ): if allow_space: pattern = r'^[\w\-_. ]+$' else: pattern = r'^[\w\-_.]+$' - is_single_or_no_dot = len(re.findall(r'\.', text)) <= 1 - return bool(re.match(pattern, text)) and is_single_or_no_dot + + if allowed is None: + allowed = [] + + if isinstance(allowed, str): + allowed = (allowed,) + + max_num_dots = 1 + if allowed is not None: + max_num_dots += sum([txt.count('.') for txt in allowed]) + + for allowed_text in allowed: + allowed_text = re.escape(allowed_text) + pattern = pattern.replace(r'+$', fr'+({allowed_text})?$') + + is_less_max_num_dots = len(re.findall(r'\.', text)) <= max_num_dots + return bool(re.match(pattern, text)) and is_less_max_num_dots def get_non_alphanumeric_characters(text): return re.findall(r'[^\w\-.]', text) diff --git a/cellacdc/dataStruct.py b/cellacdc/dataStruct.py index b41dbbc2..c865ab0f 100755 --- a/cellacdc/dataStruct.py +++ b/cellacdc/dataStruct.py @@ -1927,8 +1927,11 @@ def checkFileFormat(self, raw_src_path): return files def checkFileNames(self, raw_filenames, raw_src_path): + allowed = ( + '.ome.tif', + ) for file in raw_filenames: - if not acdc_regex.is_alphanumeric_filename(file): + if not acdc_regex.is_alphanumeric_filename(file, allowed=allowed): msg = widgets.myMessageBox(wrapText=False) txt = html_utils.paragraph( f""" diff --git a/cellacdc/load.py b/cellacdc/load.py index 62a33646..60dc6ced 100755 --- a/cellacdc/load.py +++ b/cellacdc/load.py @@ -3659,8 +3659,12 @@ def __init__(self): class OMEXML_Channel: def __init__(self, Channel) -> None: - self.Name = Channel.attrib.get('Name', '') - self.node = Channel.attrib + if not Channel or Channel is None: + self.Name = 'not_found' + self.node = None + else: + self.Name = Channel.attrib.get('Name', '') + self.node = Channel.attrib class OMEXML_Pixels: def __init__(self, Pixels, node, ome_schema) -> None: @@ -3683,7 +3687,10 @@ def __init__(self, Pixels, node, ome_schema) -> None: self.PhysicalSizeZ = node.get('PhysicalSizeZ', 1.0) def Channel(self, channel_index=0): - Channel = self.Pixels.findall(f'{self.ome_schema}Channel')[channel_index] + try: + Channel = self.Pixels.findall(f'{self.ome_schema}Channel')[channel_index] + except Exception as err: + Channel = None return OMEXML_Channel(Channel) class OMEXML: @@ -3697,12 +3704,20 @@ def read_omexml_string(self): return tif.ome_metadata def parse_metadata(self): + self.root = None + self.ome_schema = None self.omexml_string = self.read_omexml_string() + if self.omexml_string is None: + return + self.root = ET.fromstring(self.omexml_string) self.ome_schema = re.findall(r'({.+})OME', self.root.tag)[0] def instrument(self): instrument = OMEXML_intrument() + if self.root is None: + return instrument + instrument_xml = self.root.find(f'{self.ome_schema}Instrument') if instrument_xml is None: return instrument @@ -3716,9 +3731,15 @@ def instrument(self): return instrument def get_image_count(self): + if self.root is None: + return 1 + return len(self.root.findall(f'{self.ome_schema}Image')) def image(self): + if self.root is None: + return OMEXML_image(None, 'not_found') + Image = self.root.find(f'{self.ome_schema}Image') Pixels = Image.find(f'{self.ome_schema}Pixels') image = OMEXML_image(Pixels, self.ome_schema)