<commit_before>import os
import logging
from sqlalchemy import Column, String, Integer, Text, ForeignKey
from sqlalchemy.dialects.postgres import JSONB
from sqlalchemy.orm import relationship, backref
from sqlalchemy import UniqueConstraint

from tmlib.models.base import Model, DateMixIn
from tmlib.models.status import FileUploadStatus as fus
from tmlib.models.utils import remove_location_upon_delete
from tmlib.utils import autocreate_directory_property

logger = logging.getLogger(__name__)

#: Format string for acquisition locations
ACQUISITION_LOCATION_FORMAT = 'acquisition_{id}'


@remove_location_upon_delete
class Acquisition(Model, DateMixIn):

    '''An *acquisition* contains all files belonging to one microscope image
    acquisition process. Note that in contrast to a *cycle*, an *acquisition*
    may contain more than one time point.

    The incentive to grouped files this way relates to the fact that most
    microscopes generate separate metadata files for each *acquisition*.

    Attributes
    ----------
    name: str
        name of the acquisition
    description: str
        description of the acquisition
    status: str
        processing status
    plate_id: int
        ID of the parent plate
    plate: tmlib.models.Plate
        parent plate to which the acquisition belongs
    microscope_image_files: List[tmlib.models.MicroscopeImageFile]
        image files generated by the microscope
    microscope_metadata_files: List[tmlib.models.MicroscopeMetadataFile]
        metadata files generated by the microscope
    ome_xml_files: List[tmlib.models.OmeXmlFile]
        OMEXML files extracted from microscope image files
    image_file_mappings: List[tmlib.models.ImageFileMapping]
        maps pixel planes to microscope image files
    '''

    #: str: name of the corresponding database table
    __tablename__ = 'acquisitions'

    __table_args__ = (UniqueConstraint('name', 'plate_id'), )

    # Table columns
    name = Column(String, index=True)
    description = Column(Text)
    plate_id = Column(
        Integer,
        ForeignKey('plates.id', onupdate='CASCADE', ondelete='CASCADE')
    )

    # Relationships to other tables
    plate = relationship(
        'Plate',
        backref=backref('acquisitions', cascade='all, delete-orphan')
    )

    def __init__(self, name, plate_id, description=''):
        '''
        Parameters
        ----------
        name: str
            name of the acquisition
        plate_id: int
            ID of the parent plate
        description: str, optional
            description of the acquisition
        '''
        # TODO: ensure that name is unique within plate
        self.name = name
        self.description = description
        self.plate_id = plate_id

    @autocreate_directory_property
    def location(self):
        '''str: location were the acquisition content is stored'''
        if self.id is None:
            raise AttributeError(
                'Acquisition "%s" doesn\'t have an entry in the database yet. '
                'Therefore, its location cannot be determined.' % self.name
            )
        return os.path.join(
            self.plate.acquisitions_location,
            ACQUISITION_LOCATION_FORMAT.format(id=self.id)
        )

    @autocreate_directory_property
    def microscope_images_location(self):
        '''str: location where microscope image files are stored'''
        return os.path.join(self.location, 'microscope_images')

    @autocreate_directory_property
    def microscope_metadata_location(self):
        '''str: location where microscope metadata files are stored'''
        return os.path.join(self.location, 'microscope_metadata')

    @autocreate_directory_property
    def omexml_location(self):
        '''str: location where extracted OMEXML files are stored'''
        return os.path.join(self.location, 'omexml')

    @property
    def status(self):
        '''str: upload status based on the status of microscope files'''
        child_status = set([
            f.upload_status for f in self.microscope_image_files
        ])
        child_status.union(set([
            f.upload_status for f in self.microscope_metadata_files
        ]))
        if fus.UPLOADING in child_status:
            return fus.UPLOADING
        elif len(child_status) == 1 and fus.COMPLETE in child_status:
            return fus.COMPLETE
        else:
            return fus.WAITING

    def as_dict(self):<commit_msg>Fix bug in reporting of acquisition status<commit_after>import os
import logging
from sqlalchemy import Column, String, Integer, Text, ForeignKey
from sqlalchemy.dialects.postgres import JSONB
from sqlalchemy.orm import relationship, backref
from sqlalchemy import UniqueConstraint

from tmlib.models.base import Model, DateMixIn
from tmlib.models.status import FileUploadStatus as fus
from tmlib.models.utils import remove_location_upon_delete
from tmlib.utils import autocreate_directory_property

logger = logging.getLogger(__name__)

#: Format string for acquisition locations
ACQUISITION_LOCATION_FORMAT = 'acquisition_{id}'


@remove_location_upon_delete
class Acquisition(Model, DateMixIn):

    '''An *acquisition* contains all files belonging to one microscope image
    acquisition process. Note that in contrast to a *cycle*, an *acquisition*
    may contain more than one time point.

    The incentive to grouped files this way relates to the fact that most
    microscopes generate separate metadata files for each *acquisition*.

    Attributes
    ----------
    name: str
        name of the acquisition
    description: str
        description of the acquisition
    status: str
        processing status
    plate_id: int
        ID of the parent plate
    plate: tmlib.models.Plate
        parent plate to which the acquisition belongs
    microscope_image_files: List[tmlib.models.MicroscopeImageFile]
        image files generated by the microscope
    microscope_metadata_files: List[tmlib.models.MicroscopeMetadataFile]
        metadata files generated by the microscope
    ome_xml_files: List[tmlib.models.OmeXmlFile]
        OMEXML files extracted from microscope image files
    image_file_mappings: List[tmlib.models.ImageFileMapping]
        maps pixel planes to microscope image files
    '''

    #: str: name of the corresponding database table
    __tablename__ = 'acquisitions'

    __table_args__ = (UniqueConstraint('name', 'plate_id'), )

    # Table columns
    name = Column(String, index=True)
    description = Column(Text)
    plate_id = Column(
        Integer,
        ForeignKey('plates.id', onupdate='CASCADE', ondelete='CASCADE')
    )

    # Relationships to other tables
    plate = relationship(
        'Plate',
        backref=backref('acquisitions', cascade='all, delete-orphan')
    )

    def __init__(self, name, plate_id, description=''):
        '''
        Parameters
        ----------
        name: str
            name of the acquisition
        plate_id: int
            ID of the parent plate
        description: str, optional
            description of the acquisition
        '''
        # TODO: ensure that name is unique within plate
        self.name = name
        self.description = description
        self.plate_id = plate_id

    @autocreate_directory_property
    def location(self):
        '''str: location were the acquisition content is stored'''
        if self.id is None:
            raise AttributeError(
                'Acquisition "%s" doesn\'t have an entry in the database yet. '
                'Therefore, its location cannot be determined.' % self.name
            )
        return os.path.join(
            self.plate.acquisitions_location,
            ACQUISITION_LOCATION_FORMAT.format(id=self.id)
        )

    @autocreate_directory_property
    def microscope_images_location(self):
        '''str: location where microscope image files are stored'''
        return os.path.join(self.location, 'microscope_images')

    @autocreate_directory_property
    def microscope_metadata_location(self):
        '''str: location where microscope metadata files are stored'''
        return os.path.join(self.location, 'microscope_metadata')

    @autocreate_directory_property
    def omexml_location(self):
        '''str: location where extracted OMEXML files are stored'''
        return os.path.join(self.location, 'omexml')

    @property
    def status(self):
        '''str: upload status based on the status of microscope files'''
        child_status = set([
            f.upload_status for f in self.microscope_image_files
        ]).union(set([
            f.upload_status for f in self.microscope_metadata_files
        ]))
        if fus.UPLOADING in child_status:
            return fus.UPLOADING
        elif len(child_status) == 1 and fus.COMPLETE in child_status:
            return fus.COMPLETE
        else:
            return fus.WAITING

    def as_dict(self):
{'fraction_non_alphanumeric': 0.07342735616745019, 'fraction_numerical': 0.00022386389075442132, 'mean_word_length': 2.8053662691652472, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 6}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4380084', 'n_tokens_mistral': 2430, 'n_tokens_neox': 2308, 'n_words': 755}