From c64837f50073971c91e44682e7d453444ddf259c Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Thu, 14 Mar 2024 17:47:27 +0100 Subject: [PATCH 01/61] added pydantic schemas for bed and bedset tables --- bbconf/_version.py | 2 +- bbconf/model_parser.py | 125 ++++++++++++++++++++++++++++ bbconf/models.py | 18 ++++ bbconf/schemas/bedfiles_schema.yaml | 3 - docs/changelog.md | 6 ++ 5 files changed, 150 insertions(+), 4 deletions(-) create mode 100644 bbconf/model_parser.py diff --git a/bbconf/_version.py b/bbconf/_version.py index df124332..36370558 100644 --- a/bbconf/_version.py +++ b/bbconf/_version.py @@ -1 +1 @@ -__version__ = "0.4.2" +__version__ = "0.5.0a1" diff --git a/bbconf/model_parser.py b/bbconf/model_parser.py new file mode 100644 index 00000000..3cb69ba6 --- /dev/null +++ b/bbconf/model_parser.py @@ -0,0 +1,125 @@ +from pydantic import create_model, Field, ConfigDict +import logging +from typing import Union, Tuple, Dict, Any, List +from pathlib import Path +import os +from ubiquerg import expandpath +from oyaml import safe_load +import datetime + + +# TODO: This should be moved to pipestat or bedhost + +_LOGGER = logging.getLogger("bedhost") + +CLASSES_BY_TYPE = { + "object": dict, + "number": float, + "integer": int, + "string": str, + "path": Path, + "boolean": bool, + "file": str, + "image": str, + "link": str, + "array": List[Dict], +} + + +def _get_data_type(type_name): + t = CLASSES_BY_TYPE[type_name] + return t + + +def _add_dates_to_schema(schema: dict) -> dict: + """ + Add date fields to the schema + + :param schema: schema dictionary + :return: schema dictionary with date fields + """ + + schema["pipestat_created_time"] = ( + Union[datetime.datetime, str, None], + Field( + default=None, + nullable=True, + ), + ) + schema["pipestat_modified_time"] = ( + Union[datetime.datetime, str, None], + Field( + default=None, + nullable=True, + ), + ) + return schema + + +def read_yaml_data(path: Union[str, Path], what: str) -> Tuple[str, Dict[str, Any]]: + """ + Safely read YAML file and log message + + :param str path: YAML file to read + :param str what: context + :return (str, dict): absolute path to the read file and the read data + """ + if isinstance(path, Path): + test = lambda p: p.is_file() + elif isinstance(path, str): + path = expandpath(path) + test = os.path.isfile + else: + raise TypeError( + f"Alleged path to YAML file to read is neither path nor string: {path}" + ) + assert test(path), FileNotFoundError(f"File not found: {path}") + _LOGGER.debug(f"Reading {what} from '{path}'") + with open(path, "r") as f: + return path, safe_load(f) + + +def get_fields_dict(schema: dict) -> Dict[str, Field]: + """ + Get the field dictionary from the schema + + :param schema: schema dictionary + + :return: field dictionary + """ + defs = {} + samples = schema["properties"].get("samples") + for name, value in samples["properties"].items(): + + defs[name] = ( + Union[_get_data_type(value["type"]), None], + Field( + default=value.get("default"), + nullable=True, + description=value.get("description"), + ), + ) + return defs + + +def yaml_to_pydantic(name: str, data: Union[str, dict]): + """ + Convert yaml to pydantic model + + :param data: path to yaml file + :param name: name of the model + + :return: pydantic model + """ + if not isinstance(data, dict): + _, data = read_yaml_data(data, "schema") + from pipestat.parsed_schema import replace_JSON_refs + + data = replace_JSON_refs(data, data) + fields_dict = get_fields_dict(data) + + # This step is necessary because the pipestat schema does not include the dates and adds additional fields + fields_dict = _add_dates_to_schema(fields_dict) + config = ConfigDict(extra="ignore") + + return create_model(name, __config__=config, **fields_dict) diff --git a/bbconf/models.py b/bbconf/models.py index cd1cb403..acc99d72 100644 --- a/bbconf/models.py +++ b/bbconf/models.py @@ -1,8 +1,12 @@ import datetime from typing import Optional, List +import os +import pathlib from pydantic import BaseModel +from bbconf.model_parser import yaml_to_pydantic + class AccessURL(BaseModel): url: str @@ -26,3 +30,17 @@ class DRSModel(BaseModel): checksums: str access_methods: List[AccessMethod] description: Optional[str] = None + + +BedFileTableModel = yaml_to_pydantic( + "BedFile", + os.path.join( + pathlib.Path(__file__).parent.resolve(), "schemas", "bedfiles_schema.yaml" + ), +) +BedSetTableModel = yaml_to_pydantic( + "BedSet", + os.path.join( + pathlib.Path(__file__).parent.resolve(), "schemas", "bedsets_schema.yaml" + ), +) diff --git a/bbconf/schemas/bedfiles_schema.yaml b/bbconf/schemas/bedfiles_schema.yaml index 650c3b33..2b9f4563 100644 --- a/bbconf/schemas/bedfiles_schema.yaml +++ b/bbconf/schemas/bedfiles_schema.yaml @@ -116,9 +116,6 @@ properties: $ref: "#/$defs/image" label: Open_chromatin description: Cell specific enrichment for open chromatin plot - other: - type: object - description: Other, not categorized BED file metadata upload_status: type: object description: "Status of the upload to the databases: Dict[s3, qdrant, pephub]" diff --git a/docs/changelog.md b/docs/changelog.md index d15891cd..a65d5bd1 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -2,6 +2,12 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) and [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) format. +# [0.5.0] - 2024-XX-XX +### Added + +- pydantic schema for bedfile and bedset table + + ## [0.4.2] - 2024-03-12 ### Change - Updated logger From 4c6ef334f9aa2aeb2edb0fe9fe37090ae5206fd5 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Fri, 15 Mar 2024 19:01:16 +0100 Subject: [PATCH 02/61] some work --- bbconf/bbconf.py | 6 +-- bbconf/db_utils.py | 92 ++++++++++++++++++++++++++++++++++++++ bbconf/modules/__init__.py | 0 bbconf/modules/bedfiles.py | 0 bbconf/modules/bedsets.py | 0 5 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 bbconf/db_utils.py create mode 100644 bbconf/modules/__init__.py create mode 100644 bbconf/modules/bedfiles.py create mode 100644 bbconf/modules/bedsets.py diff --git a/bbconf/bbconf.py b/bbconf/bbconf.py index 28a03523..e0868eb7 100644 --- a/bbconf/bbconf.py +++ b/bbconf/bbconf.py @@ -12,6 +12,7 @@ from sqlalchemy.orm import relationship from sqlalchemy import inspect +import numpy as np from bbconf.const import ( CFG_PATH_KEY, @@ -565,10 +566,7 @@ def add_bed_to_qdrant( reg_2_vec_obj = Region2VecExModel(self.region2vec_model) else: reg_2_vec_obj = region_to_vec - bed_embedding = reg_2_vec_obj.encode( - bed_region_set, - pooling="mean", - ) + bed_embedding = np.mean(reg_2_vec_obj.encode(bed_region_set), axis=0) # Upload bed file vector to the database vec_dim = bed_embedding.shape[0] diff --git a/bbconf/db_utils.py b/bbconf/db_utils.py new file mode 100644 index 00000000..85b0e428 --- /dev/null +++ b/bbconf/db_utils.py @@ -0,0 +1,92 @@ +import datetime +import logging +from typing import Optional, List + +from sqlalchemy import ( + BigInteger, + FetchedValue, + Result, + Select, + String, + event, + select, + TIMESTAMP, + ForeignKey, + UniqueConstraint, +) +from sqlalchemy.dialects.postgresql import JSON +from sqlalchemy.engine import URL, create_engine +from sqlalchemy.exc import ProgrammingError +from sqlalchemy.ext.compiler import compiles +from sqlalchemy.orm import ( + DeclarativeBase, + Mapped, + Session, + mapped_column, + relationship, +) + +from bbconf.const import PKG_NAME + + +_LOGGER = logging.getLogger(PKG_NAME) + + +POSTGRES_DIALECT = "postgresql+psycopg" + + +class BIGSERIAL(BigInteger): + pass + + +@compiles(BIGSERIAL, POSTGRES_DIALECT) +def compile_bigserial_pg(type_, compiler, **kw): + return "BIGSERIAL" + + +@compiles(JSON, POSTGRES_DIALECT) +def compile_jsonb_pg(type_, compiler, **kw): + return "JSONB" + + +class Base(DeclarativeBase): + type_annotation_map = {datetime.datetime: TIMESTAMP(timezone=True)} + + +@event.listens_for(Base.metadata, "after_create") +def receive_after_create(target, connection, tables, **kw): + """ + listen for the 'after_create' event + """ + if tables: + _LOGGER.info("A table was created") + else: + _LOGGER.info("A table was not created") + +def deliver_update_date(context): + return datetime.datetime.now(datetime.timezone.utc) + + +class Bedfiles(Base): + + __tablename__ = "bedfiles" + + id: Mapped[int] = mapped_column(primary_key=True) + name: Mapped[str] = Mapped[Optional[str]] + genome_alias: Mapped[Optional[str]] + genome_digest: Mapped[Optional[str]] + bed_type: Mapped[str] = mapped_column(default="bed3") + bed_format: Mapped[str] = mapped_column(default="bed") + indexed: Mapped[bool] = mapped_column(default=False, description="Whether sample was added to qdrant") + pephub: Mapped[bool] = mapped_column(default=False, description="Whether sample was added to pephub") + submission_date: Mapped[datetime.datetime] + last_update_date: Mapped[Optional[datetime.datetime]] = mapped_column( + default=deliver_update_date, # onupdate=deliver_update_date, # This field should not be updated, while we are adding project to favorites + ) + +class Files(Base): + __tablename__ = "files" + + id: Mapped[int] = mapped_column(primary_key=True) + name: Mapped[str] = mapped_column(nullable=False, description="Name of the file, e.g. bed, bigBed") + path: Mapped[str] diff --git a/bbconf/modules/__init__.py b/bbconf/modules/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py new file mode 100644 index 00000000..e69de29b diff --git a/bbconf/modules/bedsets.py b/bbconf/modules/bedsets.py new file mode 100644 index 00000000..e69de29b From 8e9bd95dd7e2c224ec797fd10d4863c1a5571266 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Fri, 15 Mar 2024 20:24:07 +0100 Subject: [PATCH 03/61] some work --- bbconf/bbagent.py | 50 ++++++ bbconf/db_utils.py | 189 ++++++++++++++++++++++- tests/README.md | 6 +- tests/conftest.py | 35 +---- tests/{ => old}/__init__.py | 0 tests/old/conftest.py | 37 +++++ tests/{ => old}/data/config.yaml | 0 tests/{ => old}/data/config_invalid.yaml | 0 tests/{ => old}/data/config_min.yaml | 0 tests/{ => old}/data/config_noport.yaml | 0 tests/{ => old}/test_bbconf.py | 0 tests/test_bbagent.py | 25 +++ 12 files changed, 300 insertions(+), 42 deletions(-) create mode 100644 bbconf/bbagent.py rename tests/{ => old}/__init__.py (100%) create mode 100644 tests/old/conftest.py rename tests/{ => old}/data/config.yaml (100%) rename tests/{ => old}/data/config_invalid.yaml (100%) rename tests/{ => old}/data/config_min.yaml (100%) rename tests/{ => old}/data/config_noport.yaml (100%) rename tests/{ => old}/test_bbconf.py (100%) create mode 100644 tests/test_bbagent.py diff --git a/bbconf/bbagent.py b/bbconf/bbagent.py new file mode 100644 index 00000000..1d9d113a --- /dev/null +++ b/bbconf/bbagent.py @@ -0,0 +1,50 @@ +from bbconf.db_utils import POSTGRES_DIALECT, BaseEngine + + +class BedBaseAgent(object): + def __init__( + self, + host="localhost", + port=5432, + database="pep-db", + user=None, + password=None, + drivername=POSTGRES_DIALECT, + dsn=None, + echo=False, + ): + """ + Initialize connection to the pep_db database. You can use The basic connection parameters + or libpq connection string. + :param host: database server address e.g., localhost or an IP address. + :param port: the port number that defaults to 5432 if it is not provided. + :param database: the name of the database that you want to connect. + :param user: the username used to authenticate. + :param password: password used to authenticate. + :param drivername: driver of the database [Default: postgresql] + :param dsn: libpq connection string using the dsn parameter + (e.g. "localhost://username:password@pdp_db:5432") + """ + + pep_db_engine = BaseEngine( + host=host, + port=port, + database=database, + user=user, + password=password, + drivername=drivername, + dsn=dsn, + echo=echo, + ) + sa_engine = pep_db_engine.engine + + # self.__sa_engine = sa_engine + # + # self.__project = PEPDatabaseProject(pep_db_engine) + # self.__annotation = PEPDatabaseAnnotation(pep_db_engine) + # self.__namespace = PEPDatabaseNamespace(pep_db_engine) + # self.__sample = PEPDatabaseSample(pep_db_engine) + # self.__user = PEPDatabaseUser(pep_db_engine) + # self.__view = PEPDatabaseView(pep_db_engine) + + return sa_engine diff --git a/bbconf/db_utils.py b/bbconf/db_utils.py index 85b0e428..5b422c85 100644 --- a/bbconf/db_utils.py +++ b/bbconf/db_utils.py @@ -35,6 +35,11 @@ POSTGRES_DIALECT = "postgresql+psycopg" +class SchemaError(Exception): + def __init__(self): + super().__init__("""PEP_db connection error! The schema of connected db is incorrect""") + + class BIGSERIAL(BigInteger): pass @@ -63,30 +68,204 @@ def receive_after_create(target, connection, tables, **kw): else: _LOGGER.info("A table was not created") + def deliver_update_date(context): return datetime.datetime.now(datetime.timezone.utc) -class Bedfiles(Base): +class BedFiles(Base): __tablename__ = "bedfiles" - id: Mapped[int] = mapped_column(primary_key=True) + id: Mapped[int] = mapped_column(primary_key=True, ) name: Mapped[str] = Mapped[Optional[str]] genome_alias: Mapped[Optional[str]] genome_digest: Mapped[Optional[str]] bed_type: Mapped[str] = mapped_column(default="bed3") bed_format: Mapped[str] = mapped_column(default="bed") - indexed: Mapped[bool] = mapped_column(default=False, description="Whether sample was added to qdrant") - pephub: Mapped[bool] = mapped_column(default=False, description="Whether sample was added to pephub") + indexed: Mapped[bool] = mapped_column(default=False, comment="Whether sample was added to qdrant") + pephub: Mapped[bool] = mapped_column(default=False, comment="Whether sample was added to pephub") + submission_date: Mapped[datetime.datetime] last_update_date: Mapped[Optional[datetime.datetime]] = mapped_column( default=deliver_update_date, # onupdate=deliver_update_date, # This field should not be updated, while we are adding project to favorites ) + # statistics: + number_of_regions: Mapped[Optional[int]] + gc_content: Mapped[Optional[int]] + median_tss_dist: Mapped[Optional[int]] + mean_region_width: Mapped[Optional[int]] + exon_frequency: Mapped[Optional[int]] + intron_frequency: Mapped[Optional[int]] + promoterprox_frequency: Mapped[Optional[int]] + intergenic_frequency: Mapped[Optional[int]] + promotercore_frequency: Mapped[Optional[int]] + fiveutr_frequency: Mapped[Optional[int]] + threeutr_frequency: Mapped[Optional[int]] + fiveutr_percentage: Mapped[Optional[int]] + threeutr_percentage: Mapped[Optional[int]] + promoterprox_percentage: Mapped[Optional[int]] + exon_percentage: Mapped[Optional[int]] + intron_percentage: Mapped[Optional[int]] + intergenic_percentage: Mapped[Optional[int]] + promotercore_percentage: Mapped[Optional[int]] + tssdist: Mapped[Optional[int]] + + # relations: + plots: Mapped[List["Plots"]] = relationship("Plots", back_populates="bedfile") + files: Mapped[List["Files"]] = relationship("Files", back_populates="bedfile") + + bedsets: Mapped[List["BedFileBedSetRelation"]] = relationship("BedFileBedSetRelation", back_populates="bedfile") + + class Files(Base): __tablename__ = "files" id: Mapped[int] = mapped_column(primary_key=True) - name: Mapped[str] = mapped_column(nullable=False, description="Name of the file, e.g. bed, bigBed") + name: Mapped[str] = mapped_column(nullable=False, comment="Name of the file, e.g. bed, bigBed") path: Mapped[str] + description: Mapped[Optional[str]] + + bedfile_id: Mapped[int] = mapped_column(ForeignKey("bedfiles.id"), nullable=True) + bedset_id: Mapped[int] = mapped_column(ForeignKey("bedsets.id"), nullable=True) + + bedfile: Mapped["BedFiles"] = relationship("BedFiles", back_populates="files") + bedset: Mapped["BedSets"] = relationship("BedSets", back_populates="files") + + +class Plots(Base): + __tablename__ = "plots" + + id: Mapped[int] = mapped_column(primary_key=True) + name: Mapped[str] = mapped_column(nullable=False, comment="Name of the plot") + description: Mapped[Optional[str]] = mapped_column(comment="Description of the plot") + path: Mapped[str] = mapped_column(comment="Path to the plot file") + path_thumbnail: Mapped[str] = mapped_column(nullable=True, comment="Path to the thumbnail of the plot file") + + bedfile_id: Mapped[int] = mapped_column(ForeignKey("bedfiles.id"), nullable=True) + bedset_id: Mapped[int] = mapped_column(ForeignKey("bedsets.id"), nullable=True) + + bedfile: Mapped["BedFiles"] = relationship("BedFiles", back_populates="plots") + bedset: Mapped["BedSets"] = relationship("BedSets", back_populates="plots") + + +class BedFileBedSetRelation(Base): + __tablename__ = "bedfile_bedset_relation" + bedset_id: Mapped[int] = mapped_column(ForeignKey("bedsets.id"), primary_key=True) + bedfile_id: Mapped[int] = mapped_column(ForeignKey("bedfiles.id"), primary_key=True) + + bedset: Mapped["BedSets"] = relationship("BedSets", back_populates="bedfiles") + bedfile: Mapped["BedFiles"] = relationship("BedFiles", back_populates="bedsets") + + +class BedSets(Base): + __tablename__ = "bedsets" + + id: Mapped[int] = mapped_column(primary_key=True) + name: Mapped[str] = mapped_column(nullable=False, comment="Name of the bedset") + description: Mapped[Optional[str]] = mapped_column(comment="Description of the bedset") + submission_date: Mapped[datetime.datetime] + last_update_date: Mapped[Optional[datetime.datetime]] = mapped_column( + default=deliver_update_date, + ) + + bedfiles: Mapped[List["BedFileBedSetRelation"]] = relationship("BedFileBedSetRelation", back_populates="bedset") + plots: Mapped[List["Plots"]] = relationship("Plots", back_populates="bedset") + files: Mapped[List["Files"]] = relationship("Files", back_populates="bedset") + + +class BaseEngine: + """ + A class with base methods, that are used in several classes. + """ + + def __init__( + self, + *, + host: str = "localhost", + port: int = 5432, + database: str = "bedbase", + user: str = None, + password: str = None, + drivername: str = POSTGRES_DIALECT, + dsn: str = None, + echo: bool = False, + ): + """ + Initialize connection to the pep_db database. You can use The basic connection parameters + or libpq connection string. + :param host: database server address e.g., localhost or an IP address. + :param port: the port number that defaults to 5432 if it is not provided. + :param database: the name of the database that you want to connect. + :param user: the username used to authenticate. + :param password: password used to authenticate. + :param drivername: driver used in + :param dsn: libpq connection string using the dsn parameter + (e.g. 'postgresql://user_name:password@host_name:port/db_name') + """ + if not dsn: + dsn = URL.create( + host=host, + port=port, + database=database, + username=user, + password=password, + drivername=drivername, + ) + + self._engine = create_engine(dsn, echo=echo) + self.create_schema(self._engine) + self.check_db_connection() + + def create_schema(self, engine=None): + """ + Create sql schema in the database. + + :param engine: sqlalchemy engine [Default: None] + :return: None + """ + if not engine: + engine = self._engine + Base.metadata.create_all(engine) + return None + + def session_execute(self, statement: Select) -> Result: + """ + Execute statement using sqlalchemy statement + + :param statement: SQL query or a SQL expression that is constructed using + SQLAlchemy's SQL expression language + :return: query result represented with declarative base + """ + _LOGGER.debug(f"Executing statement: {statement}") + with Session(self._engine) as session: + query_result = session.execute(statement) + + return query_result + + @property + def session(self): + """ + :return: started sqlalchemy session + """ + return self._start_session() + + @property + def engine(self): + return self._engine + + def _start_session(self): + session = Session(self.engine) + try: + session.execute(select(BedFiles).limit(1)) + except ProgrammingError: + raise SchemaError() + + return session + + def check_db_connection(self): + try: + self.session_execute(select(BedFiles).limit(1)) + except ProgrammingError: + raise SchemaError() diff --git a/tests/README.md b/tests/README.md index a619e52d..41765907 100644 --- a/tests/README.md +++ b/tests/README.md @@ -3,9 +3,9 @@ ### To create a test database for testing : ``` -docker run --rm -it --name pipestat-test \ +docker run --rm -it --name bedbase-test \ -e POSTGRES_USER=postgres \ - -e POSTGRES_PASSWORD=dockerpassword \ - -e POSTGRES_DB=pipestat-test \ + -e POSTGRES_PASSWORD=docker\ + -e POSTGRES_DB=bedbase \ -p 5432:5432 postgres ``` \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py index 57a718ae..c6e04d6d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,37 +1,4 @@ -""" Test suite shared objects and setup """ -import os -import pytest -@pytest.fixture -def test_data_bed(): - s = "test_string" - return {"name": s, "bedfile": {"path": s, "title": s}, "regions_no": 1} - - -@pytest.fixture -def test_data_bedset(): - s = "test_string" - return { - "name": s, - "bedset_means": { - "exon_frequency": 271, - "exon_percentage": 0.081, - }, - } - - -@pytest.fixture -def data_path(): - return os.path.join(os.path.dirname(os.path.abspath(__file__)), "data") - - -@pytest.fixture -def cfg_pth(data_path): - return os.path.join(data_path, "config.yaml") - - -@pytest.fixture -def invalid_cfg_pth(data_path): - return os.path.join(data_path, "config_invalid.yaml") +DNS = "postgresql+psycopg://postgres:docker@localhost:5432/bedbase" \ No newline at end of file diff --git a/tests/__init__.py b/tests/old/__init__.py similarity index 100% rename from tests/__init__.py rename to tests/old/__init__.py diff --git a/tests/old/conftest.py b/tests/old/conftest.py new file mode 100644 index 00000000..57a718ae --- /dev/null +++ b/tests/old/conftest.py @@ -0,0 +1,37 @@ +""" Test suite shared objects and setup """ + +import os +import pytest + + +@pytest.fixture +def test_data_bed(): + s = "test_string" + return {"name": s, "bedfile": {"path": s, "title": s}, "regions_no": 1} + + +@pytest.fixture +def test_data_bedset(): + s = "test_string" + return { + "name": s, + "bedset_means": { + "exon_frequency": 271, + "exon_percentage": 0.081, + }, + } + + +@pytest.fixture +def data_path(): + return os.path.join(os.path.dirname(os.path.abspath(__file__)), "data") + + +@pytest.fixture +def cfg_pth(data_path): + return os.path.join(data_path, "config.yaml") + + +@pytest.fixture +def invalid_cfg_pth(data_path): + return os.path.join(data_path, "config_invalid.yaml") diff --git a/tests/data/config.yaml b/tests/old/data/config.yaml similarity index 100% rename from tests/data/config.yaml rename to tests/old/data/config.yaml diff --git a/tests/data/config_invalid.yaml b/tests/old/data/config_invalid.yaml similarity index 100% rename from tests/data/config_invalid.yaml rename to tests/old/data/config_invalid.yaml diff --git a/tests/data/config_min.yaml b/tests/old/data/config_min.yaml similarity index 100% rename from tests/data/config_min.yaml rename to tests/old/data/config_min.yaml diff --git a/tests/data/config_noport.yaml b/tests/old/data/config_noport.yaml similarity index 100% rename from tests/data/config_noport.yaml rename to tests/old/data/config_noport.yaml diff --git a/tests/test_bbconf.py b/tests/old/test_bbconf.py similarity index 100% rename from tests/test_bbconf.py rename to tests/old/test_bbconf.py diff --git a/tests/test_bbagent.py b/tests/test_bbagent.py new file mode 100644 index 00000000..3f9aa9b5 --- /dev/null +++ b/tests/test_bbagent.py @@ -0,0 +1,25 @@ +import warnings +from bbconf.bbagent import BedBaseAgent + +from sqlalchemy.exc import OperationalError + +# from .conftest import DNS + +DNS = "postgresql+psycopg://postgres:docker@localhost:5432/bedbase" + +def db_setup(): + # Check if the database is setup + try: + BedBaseAgent(dsn=DNS) + except OperationalError: + warnings.warn( + UserWarning( + f"Skipping tests, because DB is not setup. {DNS}. To setup DB go to README.md" + ) + ) + return False + return True + + +def test_pepdbagent(): + assert db_setup() \ No newline at end of file From 5271380bdc2aa527b8d509a151d3ce6e9c1bfd58 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Mon, 18 Mar 2024 21:59:23 +0100 Subject: [PATCH 04/61] more work --- MANIFEST.in | 2 + bbconf/bbagent.py | 220 ++++++++++++++--- bbconf/config_parser/__init__.py | 0 bbconf/config_parser/bedbaseconfig.py | 189 +++++++++++++++ bbconf/config_parser/const.py | 1 + bbconf/config_parser/models.py | 69 ++++++ bbconf/const_new.py | 70 ++++++ bbconf/db_utils.py | 49 ++-- bbconf/helpers.py | 2 +- bbconf/models.py | 7 +- bbconf/modules/__init__.py | 2 + bbconf/modules/bedfiles.py | 333 ++++++++++++++++++++++++++ bbconf/modules/bedsets.py | 44 ++++ bbconf/modules/models.py | 84 +++++++ bbconf/modules/objects.py | 22 ++ tests/test_bbagent.py | 4 +- 16 files changed, 1036 insertions(+), 62 deletions(-) create mode 100644 bbconf/config_parser/__init__.py create mode 100644 bbconf/config_parser/bedbaseconfig.py create mode 100644 bbconf/config_parser/const.py create mode 100644 bbconf/config_parser/models.py create mode 100644 bbconf/const_new.py create mode 100644 bbconf/modules/models.py create mode 100644 bbconf/modules/objects.py diff --git a/MANIFEST.in b/MANIFEST.in index 9547f624..e95406d7 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -2,3 +2,5 @@ include README.md include LICENSE.txt include requirements/* include bbconf/schemas/* +include bbconf/modules/* +include bbconf/config_parser/* diff --git a/bbconf/bbagent.py b/bbconf/bbagent.py index 1d9d113a..60c24d03 100644 --- a/bbconf/bbagent.py +++ b/bbconf/bbagent.py @@ -1,50 +1,194 @@ +from pathlib import Path +from typing import Union, List + +from bbconf.config_parser.bedbaseconfig import BedBaseConfig + from bbconf.db_utils import POSTGRES_DIALECT, BaseEngine +from bbconf.modules.bedfiles import BedAgentBedFile +from bbconf.modules.bedsets import BedAgentBedSet +from bbconf.modules.objects import BBObjects class BedBaseAgent(object): def __init__( self, - host="localhost", - port=5432, - database="pep-db", - user=None, - password=None, - drivername=POSTGRES_DIALECT, - dsn=None, - echo=False, + config: Union[Path, str], ): """ Initialize connection to the pep_db database. You can use The basic connection parameters or libpq connection string. - :param host: database server address e.g., localhost or an IP address. - :param port: the port number that defaults to 5432 if it is not provided. - :param database: the name of the database that you want to connect. - :param user: the username used to authenticate. - :param password: password used to authenticate. - :param drivername: driver of the database [Default: postgresql] - :param dsn: libpq connection string using the dsn parameter - (e.g. "localhost://username:password@pdp_db:5432") + """ - pep_db_engine = BaseEngine( - host=host, - port=port, - database=database, - user=user, - password=password, - drivername=drivername, - dsn=dsn, - echo=echo, - ) - sa_engine = pep_db_engine.engine - - # self.__sa_engine = sa_engine - # - # self.__project = PEPDatabaseProject(pep_db_engine) - # self.__annotation = PEPDatabaseAnnotation(pep_db_engine) - # self.__namespace = PEPDatabaseNamespace(pep_db_engine) - # self.__sample = PEPDatabaseSample(pep_db_engine) - # self.__user = PEPDatabaseUser(pep_db_engine) - # self.__view = PEPDatabaseView(pep_db_engine) - - return sa_engine + self.config = BedBaseConfig(config) + + self.__bed = BedAgentBedFile(self.config) + + # ff = self.__bed.add("test", {"number_of_regions": 44}) + + #ff + + # self.__bedset = BedAgentBedSet(self.config) + # self.__objects = BBObjects(self.config) + + @property + def bed(self) -> BedAgentBedFile: + return self.__bed + + # @property + # def bedset(self): + # return self.__bedset + # + # @property + # def objects(self): + # return self.__objects + + # def get_prefixed_uri(self, postfix: str, access_id: str) -> str: + # """ + # Return uri with correct prefix (schema) + # + # :param postfix: postfix of the uri (or everything after uri schema) + # :param access_id: access method name + # :return: full uri path + # """ + # + # try: + # prefix = self.config[CFG_ACCESS_METHOD_KEY][access_id]["prefix"] + # return os.path.join(prefix, postfix) + # except KeyError: + # _LOGGER.error(f"Access method {access_id} is not defined.") + # raise BadAccessMethodError(f"Access method {access_id} is not defined.") + # + # def get_thumbnail_uri( + # self, + # record_type: Literal["bed", "bedset"], + # record_id: str, + # result_id: str, + # access_id: str = "http", + # ) -> str: + # """ + # Create URL to access a bed- or bedset-associated thumbnail + # + # :param record_type: table_name ["bed", "bedset"] + # :param record_id: record identifier + # :param result_id: column name (result name) + # :param access_id: access id (e.g. http, s3, etc.) + # :return: string with thumbnail + # """ + # + # try: + # result = self.get_result(record_type, record_id, result_id) + # return self.get_prefixed_uri(result["thumbnail_path"], access_id) + # except KeyError: + # _LOGGER.error( + # f"Thumbnail for {record_type} {record_id} {result_id} is not defined." + # ) + # raise MissingThumbnailError( + # f"Thumbnail for {record_type} {record_id} {result_id} is not defined." + # ) + # + # def get_object_uri( + # self, + # record_type: Literal["bed", "bedset"], + # record_id: str, + # result_id: str, + # access_id: str, + # ) -> str: + # """ + # Create URL to access a bed- or bedset-associated file + # + # :param record_type: table_name ["bed", "bedset"] + # :param record_id: record identifier + # :param result_id: column name (result name) + # :param access_id: access id (e.g. http, s3, etc.) + # :return: + # """ + # result = self.get_result(record_type, record_id, result_id) + # return self.get_prefixed_uri(result["path"], access_id) + # + # def get_result( + # self, + # record_type: Literal["bed", "bedset"], + # record_id: str, + # result_id: Union[str, List[str]], + # ) -> dict: + # """ + # Generic getter that can return a result from either bed or bedset + # + # :param record_type: table_name ["bed", "bedset"] + # :param record_id: record identifier + # :param result_id: column name (result name) + # :return: pipestat result + # """ + # if record_type == "bed": + # result = self.bed.retrieve_one(record_id, result_id) + # elif record_type == "bedset": + # result = self.bedset.retrieve_one(record_id, result_id) + # else: + # raise BedBaseConfError( + # f"Record type {record_type} is not supported. Only bed and bedset are supported." + # ) + # + # _LOGGER.info(f"Getting uri for {record_type} {record_id} {result_id}") + # _LOGGER.info(f"Result: {result}") + # return result + # + # def get_drs_metadata( + # self, + # record_type: Literal["bed", "bedset"], + # record_id: str, + # result_id: str, + # base_uri: str, + # ) -> DRSModel: + # """ + # Get DRS metadata for a bed- or bedset-associated file + # + # :param record_type: bed or bedset + # :param record_id: record identifier + # :param result_id: name of the result file to get metadata for + # :param base_uri: base uri to use for the self_uri field (server hostname of DRS broker) + # :return: DRS metadata + # """ + # + # access_methods = [] + # object_id = f"{record_type}.{record_id}.{result_id}" + # result_ids = [result_id, "pipestat_created_time", "pipestat_modified_time"] + # record_metadata = self.get_result( + # record_type, record_id, result_ids + # ) # only get result once + # if not record_metadata: + # raise RecordNotFoundError("This record does not exist") + # + # if not record_metadata[result_id] or not record_metadata[result_id]["path"]: + # raise MissingObjectError("This object does not exist") + # + # path = record_metadata[result_id]["path"] + # for access_id in self.config[CFG_ACCESS_METHOD_KEY].keys(): + # access_dict = AccessMethod( + # type=access_id, + # access_id=access_id, + # access_url=AccessURL(url=self.get_prefixed_uri(path, access_id)), + # region=self.config[CFG_ACCESS_METHOD_KEY][access_id].get( + # "region", None + # ), + # ) + # access_methods.append(access_dict) + # drs_dict = DRSModel( + # id=object_id, + # self_uri=f"drs://{base_uri}/{object_id}", + # size=record_metadata[result_id].get("size", "unknown"), + # created_time=record_metadata.get("pipestat_created_time", "unknown"), + # updated_time=record_metadata.get("pipestat_modified_time", "unknown"), + # checksums=object_id, + # access_methods=access_methods, + # ) + # + # return drs_dict + # + # def _read_config_file(self, config_path: str) -> dict: + # """ + # Read configuration file + # + # :param config_path: path to the configuration file + # :return: configuration dictionary + # """ diff --git a/bbconf/config_parser/__init__.py b/bbconf/config_parser/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/bbconf/config_parser/bedbaseconfig.py b/bbconf/config_parser/bedbaseconfig.py new file mode 100644 index 00000000..618e3332 --- /dev/null +++ b/bbconf/config_parser/bedbaseconfig.py @@ -0,0 +1,189 @@ +from pathlib import Path +from typing import Union +import yacman +import logging +from geniml.search import QdrantBackend +import qdrant_client +from geniml.text2bednn import text2bednn +from fastembed.embedding import FlagEmbedding +from geniml.region2vec import Region2VecExModel +from geniml.io import RegionSet + +from pephubclient import PEPHubClient +from bbconf import BedBaseConf +import boto3 + + +from bbconf.db_utils import BaseEngine +from bbconf.const_new import ( + CFG_PATH_KEY, + PKG_NAME, +) +from bbconf.helpers import get_bedbase_cfg +from bbconf.config_parser.models import ConfigFile + +_LOGGER = logging.getLogger(PKG_NAME) + + +class BedBaseConfig: + def __init__(self, config: Union[Path, str]): + + self.cfg_path = get_bedbase_cfg(config) + self._config = self._read_config_file(self.cfg_path) + + self._db_engine = self._init_db_engine() + self._qdrant_engine = self._init_qdrant_backend() + self._t2bsi = self._init_t2bsi_object() + + self._phc = self._init_pephubclient() + self._boto3_client = self._init_boto3_client() + + @staticmethod + def _read_config_file(config_path: str) -> ConfigFile: + """ + Read configuration file and insert default values if not set + + :param config_path: configuration file path + :return: None + :raises: raise_missing_key (if config key is missing) + """ + _config = yacman.YAMLConfigManager(filepath=config_path).exp + + config_dict = {} + for field_name, annotation in ConfigFile.model_fields.items(): + try: + config_dict[field_name] = annotation.annotation(**_config.get(field_name)) + except TypeError: + # TODO: this should be more specific + config_dict[field_name] = annotation.annotation() + + return ConfigFile(**config_dict) + + @property + def config(self) -> ConfigFile: + """ + Get configuration + + :return: configuration object + """ + return self._config + + @property + def db_engine(self) -> BaseEngine: + """ + Get database engine + + :return: database engine + """ + return self._db_engine + + @property + def t2bsi(self) -> Union[text2bednn.Text2BEDSearchInterface, None]: + """ + Get text2bednn object + + :return: text2bednn object + """ + return self._t2bsi + + @property + def qdrant_engine(self) -> QdrantBackend: + """ + Get qdrant engine + + :return: qdrant engine + """ + return self._qdrant_engine + + @property + def phc(self) -> PEPHubClient: + """ + Get PEPHub client + + :return: PEPHub client + """ + return self._phc + + @property + def boto3_client(self) -> boto3.client: + """ + Get boto3 client + + :return: boto3 client + """ + return self._boto3_client + + def _init_db_engine(self) -> BaseEngine: + return BaseEngine( + host=self._config.database.host, + port=self._config.database.port, + database=self._config.database.database, + user=self._config.database.user, + password=self._config.database.password, + drivername="postgresql+psycopg", + ) + + def _init_qdrant_backend(self) -> QdrantBackend: + """ + Create qdrant client object using credentials provided in config file + + :return: QdrantClient + """ + try: + return QdrantBackend( + collection=self._config.qdrant.collection, + qdrant_host=self._config.qdrant.host, + qdrant_port=self._config.qdrant.port, + qdrant_api_key=self._config.qdrant.api_key, + ) + except qdrant_client.http.exceptions.ResponseHandlingException as err: + _LOGGER.error(f"error in Connection to qdrant! skipping... Error: {err}") + + def _init_t2bsi_object(self) -> Union[text2bednn.Text2BEDSearchInterface, None]: + """ + Create Text 2 BED search interface and return this object + + :return: Text2BEDSearchInterface object + + # TODO: should it be text 2 vec? + """ + + try: + return text2bednn.Text2BEDSearchInterface( + nl2vec_model=FlagEmbedding(model_name=self._config.path.text2vec), + vec2vec_model=self._config.path.vec2vec, + search_backend=self.qdrant_engine, + ) + except Exception as e: + _LOGGER.error("Error in creating Text2BEDSearchInterface object: " + str(e)) + return None + + @staticmethod + def _init_pephubclient() -> PEPHubClient: + """ + Create Pephub client object using credentials provided in config file + + :return: PephubClient + """ + try: + return PEPHubClient() + except Exception as e: + _LOGGER.error(f"Error in creating PephubClient object: {e}") + return None + + def _init_boto3_client(self,) -> boto3.client: + """ + Create Pephub client object using credentials provided in config file + + :return: PephubClient + """ + try: + return boto3.client( + "s3", + endpoint_url=self._config.s3.endpoint_url, + aws_access_key_id=self._config.s3.aws_access_key_id, + aws_secret_access_key=self._config.s3.aws_secret_access_key, + ) + except Exception as e: + _LOGGER.error(f"Error in creating boto3 client object: {e}") + return None \ No newline at end of file diff --git a/bbconf/config_parser/const.py b/bbconf/config_parser/const.py new file mode 100644 index 00000000..9f5ffeac --- /dev/null +++ b/bbconf/config_parser/const.py @@ -0,0 +1 @@ +# TODO: add defaults here \ No newline at end of file diff --git a/bbconf/config_parser/models.py b/bbconf/config_parser/models.py new file mode 100644 index 00000000..85100607 --- /dev/null +++ b/bbconf/config_parser/models.py @@ -0,0 +1,69 @@ +from typing import Optional, List, Union +from pydantic import BaseModel, ConfigDict + +from bbconf.const_new import DEFAULT_VEC2VEC_MODEL, DEFAULT_TEXT2VEC_MODEL, DEFAULT_REGION2_VEC_MODEL + + +class ConfigDB(BaseModel): + host: str + port: int = 5432 + user: str + password: str + database: str = "bedbase" + dialect: str = "postgresql" + driver: Optional[str] = "psycopg" + + +class ConfigQdrant(BaseModel): + host: str + port: int = 6333 + api_key: Optional[str] = None + collection: str = "bedbase" + + +class ConfigServer(BaseModel): + host: str = "0.0.0.0" + port: int = 8000 + + +class ConfigPath(BaseModel): + region2vec: str = DEFAULT_REGION2_VEC_MODEL + vec2vec: str = DEFAULT_VEC2VEC_MODEL + text2vec: str = DEFAULT_TEXT2VEC_MODEL + + +class AccessMethodsStruct(BaseModel): + type: str + description: str = None + prefix: str + + +class AccessMethods(BaseModel): + http: AccessMethodsStruct = None + s3: AccessMethodsStruct = None + local: AccessMethodsStruct = None + + +class ConfigS3(BaseModel): + endpoint_url: Union[str, None] = None + aws_access_key_id: Union[str, None] = None + aws_secret_access_key: Union[str, None] = None + bucket: Union[str, None] = "bedbase" + + +class ConfigPepHubClient(BaseModel): + namespace: Union[str, None] = "databio" + name: Union[str, None] = "allbeds" + tag: Union[str, None] = "bedbase" + + +class ConfigFile(BaseModel): + database: ConfigDB + qdrant: ConfigQdrant + server: ConfigServer + path: ConfigPath + access_methods: AccessMethods = None + s3: ConfigS3 = None + phc: ConfigPepHubClient = None + + model_config = ConfigDict(extra="allow") diff --git a/bbconf/const_new.py b/bbconf/const_new.py new file mode 100644 index 00000000..d20ad51a --- /dev/null +++ b/bbconf/const_new.py @@ -0,0 +1,70 @@ +PKG_NAME = "bbconf" + + +# config file constants +CFG_PATH_KEY = "path" +CFG_PATH_REGION2VEC_KEY = "region2vec" +CFG_PATH_VEC2VEC_KEY = "vec2vec" +CFG_PATH_TEXT2VEC_KEY = "text2vec" + +CFG_DATABASE_KEY = "database" +CFG_DATABASE_NAME_KEY = "name" +CFG_DATABASE_HOST_KEY = "host" +CFG_DATABASE_PORT_KEY = "port" +CFG_DATABASE_PASSWORD_KEY = "password" +CFG_DATABASE_USER_KEY = "user" + +CFG_QDRANT_KEY = "qdrant" + +CFG_QDRANT_HOST_KEY = "host" +CFG_QDRANT_PORT_KEY = "port" +CFG_QDRANT_API_KEY = "api_key" +CFG_QDRANT_COLLECTION_NAME_KEY = "collection" + +CFG_SERVER_KEY = "server" +CFG_SERVER_HOST_KEY = "host" +CFG_SERVER_PORT_KEY = "port" + +CFG_REMOTE_KEY = "remotes" + +DB_DEFAULT_HOST = "localhost" +DB_DEFAULT_USER = "postgres" +DB_DEFAULT_PASSWORD = "bedbasepassword" +DB_DEFAULT_NAME = "postgres" +DB_DEFAULT_PORT = 5432 +DB_DEFAULT_DIALECT = "postgresql" + +CFG_ACCESS_METHOD_KEY = "access_methods" + +DEFAULT_QDRANT_HOST = "localhost" +DEFAULT_QDRANT_PORT = 6333 +DEFAULT_QDRANT_COLLECTION_NAME = "bedbase" +DEFAULT_QDRANT_API_KEY = None + +SERVER_DEFAULT_PORT = 80 +SERVER_DEFAULT_HOST = "0.0.0.0" + +DEFAULT_SECTION_VALUES = { + CFG_DATABASE_KEY: { + CFG_DATABASE_USER_KEY: DB_DEFAULT_USER, + CFG_DATABASE_PASSWORD_KEY: DB_DEFAULT_PASSWORD, + CFG_DATABASE_NAME_KEY: DB_DEFAULT_NAME, + CFG_DATABASE_PORT_KEY: DB_DEFAULT_PORT, + CFG_DATABASE_HOST_KEY: DB_DEFAULT_HOST, + }, + CFG_SERVER_KEY: { + CFG_SERVER_HOST_KEY: SERVER_DEFAULT_HOST, + CFG_SERVER_PORT_KEY: SERVER_DEFAULT_PORT, + }, + CFG_QDRANT_KEY: { + CFG_QDRANT_HOST_KEY: DEFAULT_QDRANT_HOST, + CFG_QDRANT_PORT_KEY: DEFAULT_QDRANT_PORT, + CFG_QDRANT_COLLECTION_NAME_KEY: DEFAULT_QDRANT_COLLECTION_NAME, + CFG_QDRANT_API_KEY: DEFAULT_QDRANT_API_KEY, + }, +} + + +DEFAULT_TEXT2VEC_MODEL = "sentence-transformers/all-MiniLM-L6-v2" +DEFAULT_VEC2VEC_MODEL = "databio/v2v-MiniLM-v2-ATAC-hg38" +DEFAULT_REGION2_VEC_MODEL = "databio/r2v-ChIP-atlas-hg38" \ No newline at end of file diff --git a/bbconf/db_utils.py b/bbconf/db_utils.py index 5b422c85..bb65ed20 100644 --- a/bbconf/db_utils.py +++ b/bbconf/db_utils.py @@ -15,7 +15,7 @@ UniqueConstraint, ) from sqlalchemy.dialects.postgresql import JSON -from sqlalchemy.engine import URL, create_engine +from sqlalchemy.engine import URL, create_engine, Engine from sqlalchemy.exc import ProgrammingError from sqlalchemy.ext.compiler import compiles from sqlalchemy.orm import ( @@ -37,7 +37,7 @@ class SchemaError(Exception): def __init__(self): - super().__init__("""PEP_db connection error! The schema of connected db is incorrect""") + super().__init__("""PEP_db connection error! The schema of connected db is incorrect!""") class BIGSERIAL(BigInteger): @@ -73,11 +73,11 @@ def deliver_update_date(context): return datetime.datetime.now(datetime.timezone.utc) -class BedFiles(Base): +class Bed(Base): - __tablename__ = "bedfiles" + __tablename__ = "bed" - id: Mapped[int] = mapped_column(primary_key=True, ) + id: Mapped[str] = mapped_column(primary_key=True, ) name: Mapped[str] = Mapped[Optional[str]] genome_alias: Mapped[Optional[str]] genome_digest: Mapped[Optional[str]] @@ -86,9 +86,9 @@ class BedFiles(Base): indexed: Mapped[bool] = mapped_column(default=False, comment="Whether sample was added to qdrant") pephub: Mapped[bool] = mapped_column(default=False, comment="Whether sample was added to pephub") - submission_date: Mapped[datetime.datetime] + submission_date: Mapped[datetime.datetime] = mapped_column(default=deliver_update_date) last_update_date: Mapped[Optional[datetime.datetime]] = mapped_column( - default=deliver_update_date, # onupdate=deliver_update_date, # This field should not be updated, while we are adding project to favorites + default=deliver_update_date, onupdate=deliver_update_date, ) # statistics: @@ -127,10 +127,10 @@ class Files(Base): path: Mapped[str] description: Mapped[Optional[str]] - bedfile_id: Mapped[int] = mapped_column(ForeignKey("bedfiles.id"), nullable=True) + bedfile_id: Mapped[int] = mapped_column(ForeignKey("bed.id"), nullable=True) bedset_id: Mapped[int] = mapped_column(ForeignKey("bedsets.id"), nullable=True) - bedfile: Mapped["BedFiles"] = relationship("BedFiles", back_populates="files") + bedfile: Mapped["Bed"] = relationship("Bed", back_populates="files") bedset: Mapped["BedSets"] = relationship("BedSets", back_populates="files") @@ -143,32 +143,37 @@ class Plots(Base): path: Mapped[str] = mapped_column(comment="Path to the plot file") path_thumbnail: Mapped[str] = mapped_column(nullable=True, comment="Path to the thumbnail of the plot file") - bedfile_id: Mapped[int] = mapped_column(ForeignKey("bedfiles.id"), nullable=True) + bedfile_id: Mapped[int] = mapped_column(ForeignKey("bed.id"), nullable=True) bedset_id: Mapped[int] = mapped_column(ForeignKey("bedsets.id"), nullable=True) - bedfile: Mapped["BedFiles"] = relationship("BedFiles", back_populates="plots") + bedfile: Mapped["Bed"] = relationship("Bed", back_populates="plots") bedset: Mapped["BedSets"] = relationship("BedSets", back_populates="plots") class BedFileBedSetRelation(Base): __tablename__ = "bedfile_bedset_relation" bedset_id: Mapped[int] = mapped_column(ForeignKey("bedsets.id"), primary_key=True) - bedfile_id: Mapped[int] = mapped_column(ForeignKey("bedfiles.id"), primary_key=True) + bedfile_id: Mapped[int] = mapped_column(ForeignKey("bed.id"), primary_key=True) bedset: Mapped["BedSets"] = relationship("BedSets", back_populates="bedfiles") - bedfile: Mapped["BedFiles"] = relationship("BedFiles", back_populates="bedsets") + bedfile: Mapped["Bed"] = relationship("Bed", back_populates="bedsets") class BedSets(Base): __tablename__ = "bedsets" - id: Mapped[int] = mapped_column(primary_key=True) + id: Mapped[str] = mapped_column(primary_key=True) name: Mapped[str] = mapped_column(nullable=False, comment="Name of the bedset") description: Mapped[Optional[str]] = mapped_column(comment="Description of the bedset") - submission_date: Mapped[datetime.datetime] + submission_date: Mapped[datetime.datetime] = mapped_column(default=deliver_update_date) last_update_date: Mapped[Optional[datetime.datetime]] = mapped_column( - default=deliver_update_date, + default=deliver_update_date, onupdate=deliver_update_date, ) + md5sum: Mapped[Optional[str]] = mapped_column(comment="MD5 sum of the bedset") + + bedset_means: Mapped[Optional[dict]] = mapped_column(JSON, comment="Mean values of the bedset") + bedset_standard_deviation: Mapped[Optional[dict]] = mapped_column(JSON, comment="Median values of the bedset") + bedfiles: Mapped[List["BedFileBedSetRelation"]] = relationship("BedFileBedSetRelation", back_populates="bedset") plots: Mapped[List["Plots"]] = relationship("Plots", back_populates="bedset") @@ -193,8 +198,9 @@ def __init__( echo: bool = False, ): """ - Initialize connection to the pep_db database. You can use The basic connection parameters + Initialize connection to the bedbase database. You can use The basic connection parameters or libpq connection string. + :param host: database server address e.g., localhost or an IP address. :param port: the port number that defaults to 5432 if it is not provided. :param database: the name of the database that you want to connect. @@ -252,13 +258,16 @@ def session(self): return self._start_session() @property - def engine(self): + def engine(self) -> Engine: + """ + :return: sqlalchemy engine + """ return self._engine def _start_session(self): session = Session(self.engine) try: - session.execute(select(BedFiles).limit(1)) + session.execute(select(Bed).limit(1)) except ProgrammingError: raise SchemaError() @@ -266,6 +275,6 @@ def _start_session(self): def check_db_connection(self): try: - self.session_execute(select(BedFiles).limit(1)) + self.session_execute(select(Bed).limit(1)) except ProgrammingError: raise SchemaError() diff --git a/bbconf/helpers.py b/bbconf/helpers.py index 9672fde5..09ed54bf 100644 --- a/bbconf/helpers.py +++ b/bbconf/helpers.py @@ -34,4 +34,4 @@ def raise_missing_key(key: str) -> NoReturn: Raise missing key with message """ - raise MissingConfigDataError(f"Config lacks '{key}' key") + raise MissingConfigDataError(f"BedBaseConfig lacks '{key}' key") diff --git a/bbconf/models.py b/bbconf/models.py index acc99d72..c0415239 100644 --- a/bbconf/models.py +++ b/bbconf/models.py @@ -1,13 +1,16 @@ import datetime -from typing import Optional, List +from typing import Optional, List, Union import os import pathlib -from pydantic import BaseModel +from pydantic import BaseModel, ConfigDict from bbconf.model_parser import yaml_to_pydantic +from bbconf.const_new import DEFAULT_VEC2VEC_MODEL, DEFAULT_TEXT2VEC_MODEL, DEFAULT_REGION2_VEC_MODEL + +# DRS Models class AccessURL(BaseModel): url: str headers: Optional[dict] = None diff --git a/bbconf/modules/__init__.py b/bbconf/modules/__init__.py index e69de29b..66ff56bf 100644 --- a/bbconf/modules/__init__.py +++ b/bbconf/modules/__init__.py @@ -0,0 +1,2 @@ +# from bedfiles import BedAgentBedFile +# from bedsets import BedAgentBedSet \ No newline at end of file diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index e69de29b..589b67da 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -0,0 +1,333 @@ + +import warnings +from logging import getLogger +from typing import List, Optional, Dict, Union, Literal +import numpy as np + +from geniml.region2vec import Region2VecExModel +from geniml.io import RegionSet + +from sqlalchemy.orm import Session +from sqlalchemy import select + +import os + +from bbconf.const import ( + PKG_NAME, +) +from bbconf.modules.models import BedMetadata, BedFiles, Files +from bbconf.exceptions import ( + BedBaseConfError, +) +from bbconf.db_utils import BaseEngine, Bed +from bbconf.config_parser.bedbaseconfig import BedBaseConfig + +_LOGGER = getLogger(PKG_NAME) + + +class BedAgentBedFile: + """ + Class that represents Bedfile in Database. + + This class has method to add, delete, get files and metadata from the database. + """ + + def __init__(self, config: BedBaseConfig): + """ + :param config: config object with database and qdrant engine and credentials + """ + self._sa_engine = config.db_engine.engine + self._db_engine = config.db_engine + self._qdrant_engine = config.qdrant_engine + self._boto3_client = config.boto3_client + self._config = config + + def get(self, identifier: str) -> BedMetadata: + """ + Get file metadata by identifier. + + :param identifier: bed file identifier + :return: project metadata + """ + statement = select(Bed).where(Bed.id == identifier) + + with Session(self._sa_engine) as session: + bed_object = session.scalar(statement) + + + + + + + def get_stats(self, identifier: str) -> dict: + """ + Get file statistics by identifier. + + :param identifier: bed file identifier + :return: project statistics + """ + ... + + def get_plots(self, identifier: str) -> dict: + """ + Get file plots by identifier. + + :param identifier: bed file identifier + :return: project plots + """ + ... + + def get_files(self, identifier: str) -> dict: + """ + Get file files by identifier. + + :param identifier: bed file identifier + :return: project files + """ + ... + + def get_metadata(self, identifier: str) -> dict: + """ + Get file metadata by identifier. + + :param identifier: bed file identifier + :return: project metadata + """ + ... + + def get_classification(self, identifier: str) -> dict: + """ + Get file classification by identifier. + + :param identifier: bed file identifier + :return: project classification + """ + ... + + def add(self, + identifier: str, + stats: dict, + metadata: dict = None, + plots: dict = None, + files: dict = None, + add_to_qdrant: bool = False, + upload_pephub: bool = False, + upload_s3: bool = False, + overwrite: bool = False) -> None: + """ + Add bed file to the database. + + :param identifier: bed file identifier + :param stats: bed file results {statistics, plots, files, metadata} + :param metadata: bed file metadata (will be saved in pephub) + :param add_to_qdrant: add bed file to qdrant indexs + :param upload_pephub: add bed file to pephub + :param upload_s3: upload files to s3 + :param overwrite: overwrite bed file if it already exists + :return: None + """ + _LOGGER.info(f"Adding bed file to database. bed_id: {identifier}") + + if upload_pephub: + self.upload_pephub(identifier, metadata, overwrite) + else: + _LOGGER.info("upload_pephub set to false. Skipping pephub..") + + if add_to_qdrant: + # TODO: rethink it + bed_file_path = files.get("bed_file") + self.upload_qdrant(identifier, bed_file_path, metadata) + else: + _LOGGER.info("add_to_qdrant set to false. Skipping qdrant..") + + # Upload files to s3 + if files: + self.upload_files_s3(files) + + if plots: + self.upload_plots_s3(identifier, plots) + + stats["id"] = identifier + + new_bed = Bed( + **stats + ) + + with Session(self._sa_engine) as session: + session.add(new_bed) + session.commit() + + print(new_bed) + + def delete(self, identifier: str) -> None: + """ + Delete bed file from the database. + + :param identifier: bed file identifier + :return: None + """ + ... + + def upload_files_s3(self, files: List[Files]) -> BedFiles: + """ + Upload files to s3. + + :param files: dictionary with files to upload + :return: None + """ + bed_files_object = BedFiles() + for file in files: + if file.name == "bed_file": + + file_base_name = os.path.basename(file.path) + + bed_file = file.path + bed_s3_path = os.path.join("bed_files", file_base_name[0], file_base_name[1], os.path.basename(bed_file)) + self._upload_s3(bed_file, bed_s3_path) + + bed_files_object["bed_file"] = Files( + name="bedfile", + path=bed_s3_path, + ) + + elif file.name == "bigbed_file": + file_base_name = os.path.basename(file.path) + + bed_file = file.path + bed_s3_path = os.path.join("bigbed_files", file_base_name[0], file_base_name[1], + os.path.basename(bed_file)) + self._upload_s3(bed_file, bed_s3_path) + + bed_files_object["bed_file"] = Files( + name="bigbedfile", + path=bed_s3_path, + ) + + else: + warnings.warn(f"Provided file name: {file.name} is not supported. Skipping..") + return bed_files_object + + def upload_plots_s3(self, identifier: str, plots: dict) -> dict: + """ + Upload plots to s3. + + :param identifier: bed file identifier + :param plots: dictionary with plots to upload + :return: None + """ + return_dict = {} + _LOGGER.info(f"Uploading plots to S3...") + for key, value in plots.items(): + self._upload_s3(value["local_path"], value["s3_path"]) + return_dict[key] = value["s3_path"] + + _LOGGER.info(f"Data for '{identifier}' uploaded to S3 successfully!") + return return_dict + + def _upload_s3(self, file_path: str, s3_path: str) -> None: + """ + Upload file to s3. + + :param file_path: local path to the file + :param s3_path: path to the file in s3 with file name + :return: None + """ + self._config.boto3_client.upload_file(file_path, + self._config.config.s3.bucket, + s3_path) + + def upload_pephub(self, identifier: str, metadata: dict, overwrite: bool = False): + if not metadata: + _LOGGER.warning("No metadata provided. Skipping pephub upload..") + return False + self._config.phc.sample.create( + namespace=self._config.config.phc.namespace, + name=self._config.config.phc.name, + tag=self._config.config.phc.tag, + sample_name=identifier, + sample_dict=metadata, + overwrite=overwrite, + ) + + def upload_qdrant( + self, + bed_id: str, + bed_file: Union[str, RegionSet], + payload: dict = None, + region_to_vec: Region2VecExModel = None, + ) -> None: + """ + Convert bed file to vector and add it to qdrant database + + :param bed_id: bed file id + :param bed_file: path to the bed file, or RegionSet object + :param payload: additional metadata to store alongside vectors + :param region_to_vec: initiated region to vector model. If None, new object will be created. + :return: None + """ + + _LOGGER.info(f"Adding bed file to qdrant. bed_id: {bed_id}") + if isinstance(bed_file, str): + bed_region_set = RegionSet(bed_file) + elif isinstance(bed_file, RegionSet): + bed_region_set = bed_file + else: + raise BedBaseConfError( + "Could not add add region to qdrant. Invalid type, or path. " + ) + if not region_to_vec and isinstance(self._config.config.path.region2vec, str): + reg_2_vec_obj = Region2VecExModel(self._config.config.path.region2vec) + else: + reg_2_vec_obj = region_to_vec + bed_embedding = np.mean(reg_2_vec_obj.encode(bed_region_set), axis=0) + + # Upload bed file vector to the database + vec_dim = bed_embedding.shape[0] + self._qdrant_engine.load( + ids=[bed_id], + vectors=bed_embedding.reshape(1, vec_dim), + payloads=[{**payload}], + ) + return None + + def text_to_bed_search(self, query: str, limit: int = 10, offset: int = 0): + """ + Search for bed files by text query in qdrant database + + :param query: text query + :param limit: number of results to return + :param offset: offset to start from + + :return: list of bed file metadata + """ + _LOGGER.info(f"Looking for: {query}") + _LOGGER.info(f"Using backend: {self._config.t2bsi}") + + # TODO: FIX it! + results = self._config.t2bsi.nl_vec_search(query, limit=limit, offset=offset) + for result in results: + try: + # qdrant automatically adds hypens to the ids. remove them. + result["metadata"] = bbc.bed.retrieve_one(result["id"].replace("-", "")) + except RecordNotFoundError: + _LOGGER.info( + f"Couldn't find qdrant result in bedbase for id: {result['id']}" + ) + return results + + def _verify_results(self, results: dict) -> tuple: + """ + Verify if results are in the correct format + + :param results: results to verify + :return: True if results are correct, False if not + """ + table_annotations = Bed.__annotations__.keys() + correct_results = {} + unknown_results = {} + for key, value in results.items(): + if key in table_annotations: + correct_results[key] = value + else: + unknown_results[key] = value + return correct_results, unknown_results diff --git a/bbconf/modules/bedsets.py b/bbconf/modules/bedsets.py index e69de29b..bd0e850b 100644 --- a/bbconf/modules/bedsets.py +++ b/bbconf/modules/bedsets.py @@ -0,0 +1,44 @@ +from bbconf.db_utils import BaseEngine + + +class BedAgentBedSet: + """ + Class that represents Bedset in Database. + + This class has method to add, delete, get files and metadata from the database. + """ + + def __init__(self, db_engine: BaseEngine): + """ + :param db_engine: pepdbengine object with sa engine + """ + self._sa_engine = db_engine.engine + self._db_engine = db_engine + + def get(self, identifier: str) -> dict: + """ + Get file metadata by identifier. + + :param identifier: bed file identifier + :return: project metadata + """ + ... + + def create(self): + ... + + def delete(self, identifier: str) -> None: + """ + Delete bed file from the database. + + :param identifier: bed file identifier + :return: None + """ + ... + + def add_bedfile(self, identifier: str, bedfile: str) -> None: + ... + + def delete_bedfile(self, identifier: str, bedfile: str) -> None: + ... + diff --git a/bbconf/modules/models.py b/bbconf/modules/models.py new file mode 100644 index 00000000..ea5b7e7f --- /dev/null +++ b/bbconf/modules/models.py @@ -0,0 +1,84 @@ +import datetime +from typing import Optional, List, Union +import os +import pathlib + +from pydantic import BaseModel, ConfigDict, Field + +from bbconf.model_parser import yaml_to_pydantic + +from bbconf.const_new import DEFAULT_VEC2VEC_MODEL, DEFAULT_TEXT2VEC_MODEL, DEFAULT_REGION2_VEC_MODEL + + +class Plot(BaseModel): + name: str = Field(alias="title") + path: str + path_thumbnail: Optional[str] = None + description: Optional[str] = None + + +class BedPlots(BaseModel): + chrombins: Plot = None + gccontent: Plot = None + partitions: Plot = None + expected_partitions: Plot = None + cumulative_partitions: Plot = None + widths_histogram: Plot = None + neighbor_distances: Plot = None + open_chromatin: Plot = None + + +class Files(BaseModel): + name: str = Field(alias="title") + path: str + description: Optional[str] = None + + +class BedFiles(BaseModel): + bed_file: Files = Field(None, alias="bedfile") + bigbed_file: Files = Field(None, alias="bigbedfile") + + model_config = ConfigDict( + populate_by_name=True, + extra="allow", + ) + +class BedClassification(BaseModel): + name: str + genome_alias: str = None + genome_digest: str = None + bed_type: str = None + bed_format: str = None + + +class BedStats(BaseModel): + number_of_regions: Optional[float] = None + gc_content: Optional[float] = None + median_tss_dist: Optional[float] = None + mean_region_width: Optional[float] = None + exon_frequency: Optional[float] = None + intron_frequency: Optional[float] = None + promoterprox_frequency: Optional[float] = None + intergenic_frequency: Optional[float] = None + promotercore_frequency: Optional[float] = None + fiveutr_frequency: Optional[float] = None + threeutr_frequency: Optional[float] = None + fiveutr_percentage: Optional[float] = None + threeutr_percentage: Optional[float] = None + promoterprox_percentage: Optional[float] = None + exon_percentage: Optional[float] = None + intron_percentage: Optional[float] = None + intergenic_percentage: Optional[float] = None + promotercore_percentage: Optional[float] = None + + +class BedMetadata(BaseModel): + id: str + name: str + description: Optional[str] = None + submission_date: datetime.datetime = None + last_update_date: Optional[datetime.datetime] = None + stats: BedStats = None + classification: BedClassification = None + plots: BedPlots = None + files: BedFiles = None \ No newline at end of file diff --git a/bbconf/modules/objects.py b/bbconf/modules/objects.py new file mode 100644 index 00000000..7ae28598 --- /dev/null +++ b/bbconf/modules/objects.py @@ -0,0 +1,22 @@ +from bbconf.db_utils import BaseEngine + + +class BBObjects: + """ + """ + + def __init__(self, db_engine: BaseEngine): + """ + :param db_engine: pepdbengine object with sa engine + """ + self._sa_engine = db_engine.engine + self._db_engine = db_engine + + def get(self, identifier: str) -> dict: + """ + Get file metadata by identifier. + + :param identifier: bed file identifier + :return: project metadata + """ + ... diff --git a/tests/test_bbagent.py b/tests/test_bbagent.py index 3f9aa9b5..1c920fee 100644 --- a/tests/test_bbagent.py +++ b/tests/test_bbagent.py @@ -7,10 +7,12 @@ DNS = "postgresql+psycopg://postgres:docker@localhost:5432/bedbase" +config = "/home/bnt4me/virginia/repos/bbuploader/config_db_local.yaml" + def db_setup(): # Check if the database is setup try: - BedBaseAgent(dsn=DNS) + BedBaseAgent(config=config) except OperationalError: warnings.warn( UserWarning( From ddc5e21469aff045ccf032d91efc8546e1af921b Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Tue, 19 Mar 2024 04:02:03 +0100 Subject: [PATCH 05/61] more more more work --- bbconf/bbagent.py | 2 +- bbconf/bbconf.py | 2 +- bbconf/config_parser/bedbaseconfig.py | 12 +- bbconf/config_parser/const.py | 2 +- bbconf/config_parser/models.py | 6 +- bbconf/const_new.py | 2 +- bbconf/db_utils.py | 64 ++++++--- bbconf/models.py | 6 +- bbconf/modules/__init__.py | 2 +- bbconf/modules/bedfiles.py | 181 +++++++++++++++++--------- bbconf/modules/bedsets.py | 10 +- bbconf/modules/models.py | 51 +++++++- bbconf/modules/objects.py | 3 +- tests/conftest.py | 5 +- tests/test_bbagent.py | 3 +- 15 files changed, 241 insertions(+), 110 deletions(-) diff --git a/bbconf/bbagent.py b/bbconf/bbagent.py index 60c24d03..f87e9bc3 100644 --- a/bbconf/bbagent.py +++ b/bbconf/bbagent.py @@ -26,7 +26,7 @@ def __init__( # ff = self.__bed.add("test", {"number_of_regions": 44}) - #ff + # ff # self.__bedset = BedAgentBedSet(self.config) # self.__objects = BBObjects(self.config) diff --git a/bbconf/bbconf.py b/bbconf/bbconf.py index e0868eb7..5a4d9c08 100644 --- a/bbconf/bbconf.py +++ b/bbconf/bbconf.py @@ -12,7 +12,7 @@ from sqlalchemy.orm import relationship from sqlalchemy import inspect -import numpy as np +import numpy as np from bbconf.const import ( CFG_PATH_KEY, diff --git a/bbconf/config_parser/bedbaseconfig.py b/bbconf/config_parser/bedbaseconfig.py index 618e3332..7c557458 100644 --- a/bbconf/config_parser/bedbaseconfig.py +++ b/bbconf/config_parser/bedbaseconfig.py @@ -52,7 +52,9 @@ def _read_config_file(config_path: str) -> ConfigFile: config_dict = {} for field_name, annotation in ConfigFile.model_fields.items(): try: - config_dict[field_name] = annotation.annotation(**_config.get(field_name)) + config_dict[field_name] = annotation.annotation( + **_config.get(field_name) + ) except TypeError: # TODO: this should be more specific config_dict[field_name] = annotation.annotation() @@ -171,7 +173,9 @@ def _init_pephubclient() -> PEPHubClient: _LOGGER.error(f"Error in creating PephubClient object: {e}") return None - def _init_boto3_client(self,) -> boto3.client: + def _init_boto3_client( + self, + ) -> boto3.client: """ Create Pephub client object using credentials provided in config file @@ -183,7 +187,7 @@ def _init_boto3_client(self,) -> boto3.client: endpoint_url=self._config.s3.endpoint_url, aws_access_key_id=self._config.s3.aws_access_key_id, aws_secret_access_key=self._config.s3.aws_secret_access_key, - ) + ) except Exception as e: _LOGGER.error(f"Error in creating boto3 client object: {e}") - return None \ No newline at end of file + return None diff --git a/bbconf/config_parser/const.py b/bbconf/config_parser/const.py index 9f5ffeac..d4a02324 100644 --- a/bbconf/config_parser/const.py +++ b/bbconf/config_parser/const.py @@ -1 +1 @@ -# TODO: add defaults here \ No newline at end of file +# TODO: add defaults here diff --git a/bbconf/config_parser/models.py b/bbconf/config_parser/models.py index 85100607..b1347d6b 100644 --- a/bbconf/config_parser/models.py +++ b/bbconf/config_parser/models.py @@ -1,7 +1,11 @@ from typing import Optional, List, Union from pydantic import BaseModel, ConfigDict -from bbconf.const_new import DEFAULT_VEC2VEC_MODEL, DEFAULT_TEXT2VEC_MODEL, DEFAULT_REGION2_VEC_MODEL +from bbconf.const_new import ( + DEFAULT_VEC2VEC_MODEL, + DEFAULT_TEXT2VEC_MODEL, + DEFAULT_REGION2_VEC_MODEL, +) class ConfigDB(BaseModel): diff --git a/bbconf/const_new.py b/bbconf/const_new.py index d20ad51a..b15acdac 100644 --- a/bbconf/const_new.py +++ b/bbconf/const_new.py @@ -67,4 +67,4 @@ DEFAULT_TEXT2VEC_MODEL = "sentence-transformers/all-MiniLM-L6-v2" DEFAULT_VEC2VEC_MODEL = "databio/v2v-MiniLM-v2-ATAC-hg38" -DEFAULT_REGION2_VEC_MODEL = "databio/r2v-ChIP-atlas-hg38" \ No newline at end of file +DEFAULT_REGION2_VEC_MODEL = "databio/r2v-ChIP-atlas-hg38" diff --git a/bbconf/db_utils.py b/bbconf/db_utils.py index bb65ed20..96150a21 100644 --- a/bbconf/db_utils.py +++ b/bbconf/db_utils.py @@ -37,7 +37,9 @@ class SchemaError(Exception): def __init__(self): - super().__init__("""PEP_db connection error! The schema of connected db is incorrect!""") + super().__init__( + """PEP_db connection error! The schema of connected db is incorrect!""" + ) class BIGSERIAL(BigInteger): @@ -77,18 +79,27 @@ class Bed(Base): __tablename__ = "bed" - id: Mapped[str] = mapped_column(primary_key=True, ) + id: Mapped[str] = mapped_column( + primary_key=True, + ) name: Mapped[str] = Mapped[Optional[str]] genome_alias: Mapped[Optional[str]] genome_digest: Mapped[Optional[str]] bed_type: Mapped[str] = mapped_column(default="bed3") bed_format: Mapped[str] = mapped_column(default="bed") - indexed: Mapped[bool] = mapped_column(default=False, comment="Whether sample was added to qdrant") - pephub: Mapped[bool] = mapped_column(default=False, comment="Whether sample was added to pephub") + indexed: Mapped[bool] = mapped_column( + default=False, comment="Whether sample was added to qdrant" + ) + pephub: Mapped[bool] = mapped_column( + default=False, comment="Whether sample was added to pephub" + ) - submission_date: Mapped[datetime.datetime] = mapped_column(default=deliver_update_date) + submission_date: Mapped[datetime.datetime] = mapped_column( + default=deliver_update_date + ) last_update_date: Mapped[Optional[datetime.datetime]] = mapped_column( - default=deliver_update_date, onupdate=deliver_update_date, + default=deliver_update_date, + onupdate=deliver_update_date, ) # statistics: @@ -116,16 +127,21 @@ class Bed(Base): plots: Mapped[List["Plots"]] = relationship("Plots", back_populates="bedfile") files: Mapped[List["Files"]] = relationship("Files", back_populates="bedfile") - bedsets: Mapped[List["BedFileBedSetRelation"]] = relationship("BedFileBedSetRelation", back_populates="bedfile") + bedsets: Mapped[List["BedFileBedSetRelation"]] = relationship( + "BedFileBedSetRelation", back_populates="bedfile" + ) class Files(Base): __tablename__ = "files" id: Mapped[int] = mapped_column(primary_key=True) - name: Mapped[str] = mapped_column(nullable=False, comment="Name of the file, e.g. bed, bigBed") + name: Mapped[str] = mapped_column( + nullable=False, comment="Name of the file, e.g. bed, bigBed" + ) path: Mapped[str] description: Mapped[Optional[str]] + size: Mapped[Optional[str]] = mapped_column(comment="Size of the file") bedfile_id: Mapped[int] = mapped_column(ForeignKey("bed.id"), nullable=True) bedset_id: Mapped[int] = mapped_column(ForeignKey("bedsets.id"), nullable=True) @@ -139,9 +155,13 @@ class Plots(Base): id: Mapped[int] = mapped_column(primary_key=True) name: Mapped[str] = mapped_column(nullable=False, comment="Name of the plot") - description: Mapped[Optional[str]] = mapped_column(comment="Description of the plot") + description: Mapped[Optional[str]] = mapped_column( + comment="Description of the plot" + ) path: Mapped[str] = mapped_column(comment="Path to the plot file") - path_thumbnail: Mapped[str] = mapped_column(nullable=True, comment="Path to the thumbnail of the plot file") + path_thumbnail: Mapped[str] = mapped_column( + nullable=True, comment="Path to the thumbnail of the plot file" + ) bedfile_id: Mapped[int] = mapped_column(ForeignKey("bed.id"), nullable=True) bedset_id: Mapped[int] = mapped_column(ForeignKey("bedsets.id"), nullable=True) @@ -164,18 +184,28 @@ class BedSets(Base): id: Mapped[str] = mapped_column(primary_key=True) name: Mapped[str] = mapped_column(nullable=False, comment="Name of the bedset") - description: Mapped[Optional[str]] = mapped_column(comment="Description of the bedset") - submission_date: Mapped[datetime.datetime] = mapped_column(default=deliver_update_date) + description: Mapped[Optional[str]] = mapped_column( + comment="Description of the bedset" + ) + submission_date: Mapped[datetime.datetime] = mapped_column( + default=deliver_update_date + ) last_update_date: Mapped[Optional[datetime.datetime]] = mapped_column( - default=deliver_update_date, onupdate=deliver_update_date, + default=deliver_update_date, + onupdate=deliver_update_date, ) md5sum: Mapped[Optional[str]] = mapped_column(comment="MD5 sum of the bedset") - bedset_means: Mapped[Optional[dict]] = mapped_column(JSON, comment="Mean values of the bedset") - bedset_standard_deviation: Mapped[Optional[dict]] = mapped_column(JSON, comment="Median values of the bedset") - + bedset_means: Mapped[Optional[dict]] = mapped_column( + JSON, comment="Mean values of the bedset" + ) + bedset_standard_deviation: Mapped[Optional[dict]] = mapped_column( + JSON, comment="Median values of the bedset" + ) - bedfiles: Mapped[List["BedFileBedSetRelation"]] = relationship("BedFileBedSetRelation", back_populates="bedset") + bedfiles: Mapped[List["BedFileBedSetRelation"]] = relationship( + "BedFileBedSetRelation", back_populates="bedset" + ) plots: Mapped[List["Plots"]] = relationship("Plots", back_populates="bedset") files: Mapped[List["Files"]] = relationship("Files", back_populates="bedset") diff --git a/bbconf/models.py b/bbconf/models.py index c0415239..e449b338 100644 --- a/bbconf/models.py +++ b/bbconf/models.py @@ -7,7 +7,11 @@ from bbconf.model_parser import yaml_to_pydantic -from bbconf.const_new import DEFAULT_VEC2VEC_MODEL, DEFAULT_TEXT2VEC_MODEL, DEFAULT_REGION2_VEC_MODEL +from bbconf.const_new import ( + DEFAULT_VEC2VEC_MODEL, + DEFAULT_TEXT2VEC_MODEL, + DEFAULT_REGION2_VEC_MODEL, +) # DRS Models diff --git a/bbconf/modules/__init__.py b/bbconf/modules/__init__.py index 66ff56bf..935a5e3f 100644 --- a/bbconf/modules/__init__.py +++ b/bbconf/modules/__init__.py @@ -1,2 +1,2 @@ # from bedfiles import BedAgentBedFile -# from bedsets import BedAgentBedSet \ No newline at end of file +# from bedsets import BedAgentBedSet diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index 589b67da..5b6d014b 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -1,4 +1,3 @@ - import warnings from logging import getLogger from typing import List, Optional, Dict, Union, Literal @@ -15,7 +14,15 @@ from bbconf.const import ( PKG_NAME, ) -from bbconf.modules.models import BedMetadata, BedFiles, Files +from bbconf.modules.models import ( + BedMetadata, + BedFiles, + Files, + BedPlots, + BedClassification, + BedStats, + Plot, +) from bbconf.exceptions import ( BedBaseConfError, ) @@ -25,6 +32,11 @@ _LOGGER = getLogger(PKG_NAME) +BIGBED_PATH_FOLDER = "bigbed_files" +BED_PATH_FOLDER = "bed_files" +PLOTS_PATH_FOLDER = "stats" + + class BedAgentBedFile: """ Class that represents Bedfile in Database. @@ -54,11 +66,6 @@ def get(self, identifier: str) -> BedMetadata: with Session(self._sa_engine) as session: bed_object = session.scalar(statement) - - - - - def get_stats(self, identifier: str) -> dict: """ Get file statistics by identifier. @@ -104,55 +111,71 @@ def get_classification(self, identifier: str) -> dict: """ ... - def add(self, - identifier: str, - stats: dict, - metadata: dict = None, - plots: dict = None, - files: dict = None, - add_to_qdrant: bool = False, - upload_pephub: bool = False, - upload_s3: bool = False, - overwrite: bool = False) -> None: + def add( + self, + identifier: str, + stats: dict, + metadata: dict = None, + plots: dict = None, + files: dict = None, + classification: dict = None, + add_to_qdrant: bool = False, + upload_pephub: bool = False, + upload_s3: bool = False, + local_path: str = None, + overwrite: bool = False, + ) -> None: """ Add bed file to the database. :param identifier: bed file identifier :param stats: bed file results {statistics, plots, files, metadata} :param metadata: bed file metadata (will be saved in pephub) + :param plots: bed file plots + :param files: bed file files + :param classification: bed file classification :param add_to_qdrant: add bed file to qdrant indexs :param upload_pephub: add bed file to pephub :param upload_s3: upload files to s3 + :param local_path: local path to the output files :param overwrite: overwrite bed file if it already exists :return: None """ _LOGGER.info(f"Adding bed file to database. bed_id: {identifier}") + stats = BedStats(**stats) + plots = BedPlots(**plots) + files = BedFiles(**files) + metadata = BedMetadata(**metadata) + classification = BedClassification(**classification) + if upload_pephub: - self.upload_pephub(identifier, metadata, overwrite) + self.upload_pephub(identifier, metadata.model_dump(), overwrite) else: _LOGGER.info("upload_pephub set to false. Skipping pephub..") if add_to_qdrant: - # TODO: rethink it - bed_file_path = files.get("bed_file") - self.upload_qdrant(identifier, bed_file_path, metadata) + self.upload_qdrant(identifier, files.bed_file.path, metadata.model_dump()) else: _LOGGER.info("add_to_qdrant set to false. Skipping qdrant..") # Upload files to s3 - if files: - self.upload_files_s3(files) - - if plots: - self.upload_plots_s3(identifier, plots) + if upload_s3: + if files: + files = self.upload_files_s3(files) - stats["id"] = identifier + if plots: + plots = self.upload_plots_s3( + identifier, output_path=local_path, plots=plots + ) new_bed = Bed( - **stats + id=identifier, + **stats.model_dump(), + **classification.model_dump(), ) + # TODO: add plots to the file with Session(self._sa_engine) as session: session.add(new_bed) session.commit() @@ -168,61 +191,93 @@ def delete(self, identifier: str) -> None: """ ... - def upload_files_s3(self, files: List[Files]) -> BedFiles: + def upload_files_s3(self, files: BedFiles) -> BedFiles: """ Upload files to s3. :param files: dictionary with files to upload :return: None """ - bed_files_object = BedFiles() - for file in files: - if file.name == "bed_file": - file_base_name = os.path.basename(file.path) + if files.bed_file: + file_base_name = os.path.basename(files.bed_file.path) - bed_file = file.path - bed_s3_path = os.path.join("bed_files", file_base_name[0], file_base_name[1], os.path.basename(bed_file)) - self._upload_s3(bed_file, bed_s3_path) + bed_file_path = files.bed_file.path + bed_s3_path = os.path.join( + BED_PATH_FOLDER, + file_base_name[0], + file_base_name[1], + os.path.basename(bed_file_path), + ) + self._upload_s3(bed_file_path, bed_s3_path) - bed_files_object["bed_file"] = Files( - name="bedfile", - path=bed_s3_path, - ) + files.bed_file.path = bed_s3_path - elif file.name == "bigbed_file": - file_base_name = os.path.basename(file.path) + if files.bigbed_file: + file_base_name = os.path.basename(files.bigbed_file.path) - bed_file = file.path - bed_s3_path = os.path.join("bigbed_files", file_base_name[0], file_base_name[1], - os.path.basename(bed_file)) - self._upload_s3(bed_file, bed_s3_path) + bed_file = files.bigbed_file.path + bigbed_s3_path = os.path.join( + BIGBED_PATH_FOLDER, + file_base_name[0], + file_base_name[1], + os.path.basename(bed_file), + ) + self._upload_s3(bed_file, bigbed_s3_path) - bed_files_object["bed_file"] = Files( - name="bigbedfile", - path=bed_s3_path, - ) + files.bigbed_file.path = bigbed_s3_path - else: - warnings.warn(f"Provided file name: {file.name} is not supported. Skipping..") - return bed_files_object + return files - def upload_plots_s3(self, identifier: str, plots: dict) -> dict: + def upload_plots_s3( + self, identifier: str, output_path: str, plots: BedPlots + ) -> BedPlots: """ Upload plots to s3. :param identifier: bed file identifier :param plots: dictionary with plots to upload + :param output_path: local path to the output files :return: None """ - return_dict = {} _LOGGER.info(f"Uploading plots to S3...") - for key, value in plots.items(): - self._upload_s3(value["local_path"], value["s3_path"]) - return_dict[key] = value["s3_path"] - _LOGGER.info(f"Data for '{identifier}' uploaded to S3 successfully!") - return return_dict + plots_output = BedPlots() + output_folder = os.path.join(PLOTS_PATH_FOLDER, identifier) + + for key, value in plots: + if value: + if value.path: + file_s3_path = os.path.join( + output_folder, os.path.basename(value.path) + ) + local_path = os.path.join(output_path, value.path) + self._upload_s3(local_path, file_s3_path) + else: + file_s3_path = None + if value.path_thumbnail: + file_s3_path_thumbnail = os.path.join( + output_folder, os.path.basename(value.path_thumbnail) + ) + local_path_thumbnail = os.path.join( + output_path, value.path_thumbnail + ) + self._upload_s3(local_path_thumbnail, file_s3_path_thumbnail) + else: + file_s3_path_thumbnail = None + + setattr( + plots_output, + key, + Plot( + name=value.name, + path=file_s3_path, + path_thumbnail=file_s3_path_thumbnail, + description=value.description, + ), + ) + + return plots_output def _upload_s3(self, file_path: str, s3_path: str) -> None: """ @@ -232,9 +287,9 @@ def _upload_s3(self, file_path: str, s3_path: str) -> None: :param s3_path: path to the file in s3 with file name :return: None """ - self._config.boto3_client.upload_file(file_path, - self._config.config.s3.bucket, - s3_path) + self._config.boto3_client.upload_file( + file_path, self._config.config.s3.bucket, s3_path + ) def upload_pephub(self, identifier: str, metadata: dict, overwrite: bool = False): if not metadata: diff --git a/bbconf/modules/bedsets.py b/bbconf/modules/bedsets.py index bd0e850b..a0978bcb 100644 --- a/bbconf/modules/bedsets.py +++ b/bbconf/modules/bedsets.py @@ -24,8 +24,7 @@ def get(self, identifier: str) -> dict: """ ... - def create(self): - ... + def create(self): ... def delete(self, identifier: str) -> None: """ @@ -36,9 +35,6 @@ def delete(self, identifier: str) -> None: """ ... - def add_bedfile(self, identifier: str, bedfile: str) -> None: - ... - - def delete_bedfile(self, identifier: str, bedfile: str) -> None: - ... + def add_bedfile(self, identifier: str, bedfile: str) -> None: ... + def delete_bedfile(self, identifier: str, bedfile: str) -> None: ... diff --git a/bbconf/modules/models.py b/bbconf/modules/models.py index ea5b7e7f..78c43587 100644 --- a/bbconf/modules/models.py +++ b/bbconf/modules/models.py @@ -7,14 +7,20 @@ from bbconf.model_parser import yaml_to_pydantic -from bbconf.const_new import DEFAULT_VEC2VEC_MODEL, DEFAULT_TEXT2VEC_MODEL, DEFAULT_REGION2_VEC_MODEL +from bbconf.const_new import ( + DEFAULT_VEC2VEC_MODEL, + DEFAULT_TEXT2VEC_MODEL, + DEFAULT_REGION2_VEC_MODEL, +) class Plot(BaseModel): name: str = Field(alias="title") path: str - path_thumbnail: Optional[str] = None - description: Optional[str] = None + path_thumbnail: Optional[Union[str, None]] = Field(None, alias="thumbnail_path") + description: Optional[Union[str, None]] = None + + model_config = ConfigDict(populate_by_name=True) class BedPlots(BaseModel): @@ -32,6 +38,9 @@ class Files(BaseModel): name: str = Field(alias="title") path: str description: Optional[str] = None + size: Optional[str] = None + + model_config = ConfigDict(populate_by_name=True) class BedFiles(BaseModel): @@ -43,11 +52,14 @@ class BedFiles(BaseModel): extra="allow", ) + class BedClassification(BaseModel): name: str genome_alias: str = None genome_digest: str = None - bed_type: str = None + bed_type: str = Field( + default="bed3", pattern="^bed(?:[3-9]|1[0-5])(?:\+|$)[0-9]?+$" + ) bed_format: str = None @@ -81,4 +93,33 @@ class BedMetadata(BaseModel): stats: BedStats = None classification: BedClassification = None plots: BedPlots = None - files: BedFiles = None \ No newline at end of file + files: BedFiles = None + + +class BedMetadata(BaseModel): + sample_name: str + genome: str + organism: str = "" + species_id: str = "" + cell_type: str = "" + cell_line: str = "" + exp_protocol: str = Field("", description="Experimental protocol (e.g. ChIP-seq)") + library_source: str = Field( + "", description="Library source (e.g. genomic, transcriptomic)" + ) + genotype: str = Field("", description="Genotype of the sample") + target: str = Field("", description="Target of the assay (e.g. H3K4me3)") + antibody: str = Field("", description="Antibody used in the assay") + treatment: str = Field( + "", description="Treatment of the sample (e.g. drug treatment)" + ) + tissue: str = Field("", description="Tissue type") + global_sample_id: str = Field("", description="Global sample identifier") + global_experiment_id: str = Field("", description="Global experiment identifier") + description: str = Field("", description="Description of the sample") + + # THIS IS NOW PART OF THE BedBase model in bbconf + # bed_format: FILE_TYPE = FILE_TYPE.BED + # bed_type: str = Field( + # default="bed3", pattern="^bed(?:[3-9]|1[0-5])(?:\+|$)[0-9]?+$" + # ) diff --git a/bbconf/modules/objects.py b/bbconf/modules/objects.py index 7ae28598..b3a65733 100644 --- a/bbconf/modules/objects.py +++ b/bbconf/modules/objects.py @@ -2,8 +2,7 @@ class BBObjects: - """ - """ + """ """ def __init__(self, db_engine: BaseEngine): """ diff --git a/tests/conftest.py b/tests/conftest.py index c6e04d6d..b811c485 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,4 +1 @@ - - - -DNS = "postgresql+psycopg://postgres:docker@localhost:5432/bedbase" \ No newline at end of file +DNS = "postgresql+psycopg://postgres:docker@localhost:5432/bedbase" diff --git a/tests/test_bbagent.py b/tests/test_bbagent.py index 1c920fee..00553e69 100644 --- a/tests/test_bbagent.py +++ b/tests/test_bbagent.py @@ -9,6 +9,7 @@ config = "/home/bnt4me/virginia/repos/bbuploader/config_db_local.yaml" + def db_setup(): # Check if the database is setup try: @@ -24,4 +25,4 @@ def db_setup(): def test_pepdbagent(): - assert db_setup() \ No newline at end of file + assert db_setup() From 089c3a6098f3b549ea4ddf49fc622916217e545f Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Tue, 19 Mar 2024 14:57:02 +0100 Subject: [PATCH 06/61] added get function --- bbconf/db_utils.py | 3 +- bbconf/modules/bedfiles.py | 81 ++++++++++++++++++++++++++++++++------ bbconf/modules/models.py | 29 ++++++++------ tests/test_bbagent.py | 8 +++- 4 files changed, 93 insertions(+), 28 deletions(-) diff --git a/bbconf/db_utils.py b/bbconf/db_utils.py index 96150a21..70214263 100644 --- a/bbconf/db_utils.py +++ b/bbconf/db_utils.py @@ -82,9 +82,10 @@ class Bed(Base): id: Mapped[str] = mapped_column( primary_key=True, ) - name: Mapped[str] = Mapped[Optional[str]] + name: Mapped[Optional[str]] genome_alias: Mapped[Optional[str]] genome_digest: Mapped[Optional[str]] + description: Mapped[Optional[str]] bed_type: Mapped[str] = mapped_column(default="bed3") bed_format: Mapped[str] = mapped_column(default="bed") indexed: Mapped[bool] = mapped_column( diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index 5b6d014b..d0305df6 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -17,16 +17,17 @@ from bbconf.modules.models import ( BedMetadata, BedFiles, - Files, + FileModel, BedPlots, BedClassification, BedStats, - Plot, + PlotModel, + BedPEPHub, ) from bbconf.exceptions import ( BedBaseConfError, ) -from bbconf.db_utils import BaseEngine, Bed +from bbconf.db_utils import BaseEngine, Bed, Plots, Files from bbconf.config_parser.bedbaseconfig import BedBaseConfig _LOGGER = getLogger(PKG_NAME) @@ -63,9 +64,42 @@ def get(self, identifier: str) -> BedMetadata: """ statement = select(Bed).where(Bed.id == identifier) + bed_plots = BedPlots() + bed_files = BedFiles() + with Session(self._sa_engine) as session: bed_object = session.scalar(statement) + for result in bed_object.plots: + setattr(bed_plots, result.name, PlotModel( + name=result.name, + path=result.path, + path_thumbnail=result.path_thumbnail, + description=result.description + )) + + for result in bed_object.files: + setattr(bed_files, result.name, FileModel( + name=result.name, + path=result.path, + description=result.description + )) + + bed_stats = BedStats(**bed_object.__dict__) + bed_classification = BedClassification(**bed_object.__dict__) + + return BedMetadata( + id=bed_object.id, + name=bed_object.name, + stats=bed_stats, + classification=bed_classification, + plots=bed_plots, + files=bed_files, + description="", + submission_date=bed_object.submission_date, + last_update_date=bed_object.last_update_date + ) + def get_stats(self, identifier: str) -> dict: """ Get file statistics by identifier. @@ -143,10 +177,12 @@ def add( """ _LOGGER.info(f"Adding bed file to database. bed_id: {identifier}") + stats = BedStats(**stats) + # TODO: we should not check for specific keys, of the plots! plots = BedPlots(**plots) files = BedFiles(**files) - metadata = BedMetadata(**metadata) + metadata = BedPEPHub(**metadata) classification = BedClassification(**classification) if upload_pephub: @@ -169,18 +205,37 @@ def add( identifier, output_path=local_path, plots=plots ) - new_bed = Bed( - id=identifier, - **stats.model_dump(), - **classification.model_dump(), - ) - - # TODO: add plots to the file with Session(self._sa_engine) as session: + new_bed = Bed( + id=identifier, + **stats.model_dump(), + **classification.model_dump(), + ) session.add(new_bed) + if upload_s3: + for k, v in files: + if v: + new_file = Files( + name=k, + path=v.path, + description=v.description, + bedfile_id=identifier, + ) + session.add(new_file) + for k, v in plots: + if v: + new_plot = Plots( + name=k, + path=v.path, + path_thumbnail=v.path_thumbnail, + description=v.description, + bedfile_id=identifier, + ) + session.add(new_plot) + session.commit() - print(new_bed) + return None def delete(self, identifier: str) -> None: """ @@ -269,7 +324,7 @@ def upload_plots_s3( setattr( plots_output, key, - Plot( + PlotModel( name=value.name, path=file_s3_path, path_thumbnail=file_s3_path_thumbnail, diff --git a/bbconf/modules/models.py b/bbconf/modules/models.py index 78c43587..5b2f847b 100644 --- a/bbconf/modules/models.py +++ b/bbconf/modules/models.py @@ -14,7 +14,7 @@ ) -class Plot(BaseModel): +class PlotModel(BaseModel): name: str = Field(alias="title") path: str path_thumbnail: Optional[Union[str, None]] = Field(None, alias="thumbnail_path") @@ -24,17 +24,17 @@ class Plot(BaseModel): class BedPlots(BaseModel): - chrombins: Plot = None - gccontent: Plot = None - partitions: Plot = None - expected_partitions: Plot = None - cumulative_partitions: Plot = None - widths_histogram: Plot = None - neighbor_distances: Plot = None - open_chromatin: Plot = None + chrombins: PlotModel = None + gccontent: PlotModel = None + partitions: PlotModel = None + expected_partitions: PlotModel = None + cumulative_partitions: PlotModel = None + widths_histogram: PlotModel = None + neighbor_distances: PlotModel = None + open_chromatin: PlotModel = None -class Files(BaseModel): +class FileModel(BaseModel): name: str = Field(alias="title") path: str description: Optional[str] = None @@ -44,8 +44,8 @@ class Files(BaseModel): class BedFiles(BaseModel): - bed_file: Files = Field(None, alias="bedfile") - bigbed_file: Files = Field(None, alias="bigbedfile") + bed_file: FileModel = Field(None, alias="bedfile") + bigbed_file: FileModel = Field(None, alias="bigbedfile") model_config = ConfigDict( populate_by_name=True, @@ -62,6 +62,7 @@ class BedClassification(BaseModel): ) bed_format: str = None + model_config = ConfigDict(extra="ignore") class BedStats(BaseModel): number_of_regions: Optional[float] = None @@ -83,6 +84,8 @@ class BedStats(BaseModel): intergenic_percentage: Optional[float] = None promotercore_percentage: Optional[float] = None + model_config = ConfigDict(extra="ignore") + class BedMetadata(BaseModel): id: str @@ -96,7 +99,7 @@ class BedMetadata(BaseModel): files: BedFiles = None -class BedMetadata(BaseModel): +class BedPEPHub(BaseModel): sample_name: str genome: str organism: str = "" diff --git a/tests/test_bbagent.py b/tests/test_bbagent.py index 00553e69..cde4ef50 100644 --- a/tests/test_bbagent.py +++ b/tests/test_bbagent.py @@ -24,5 +24,11 @@ def db_setup(): return True -def test_pepdbagent(): +def test_bb_database(): assert db_setup() + +def test_get(): + agent = BedBaseAgent(config=config) + ff = agent.bed.get("91b2754c8ff01769bacfc80e6923c46e") + print(ff) + assert ff != None \ No newline at end of file From bbf25bbc8945356740e8802640b50a6d6c13f8e2 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Tue, 19 Mar 2024 17:10:37 +0100 Subject: [PATCH 07/61] added get subfunctions --- bbconf/bbagent.py | 151 +-------------- bbconf/bbconf.py | 104 +++++----- bbconf/models/__init__.py | 2 + .../models.py => models/bed_models.py} | 41 ++-- bbconf/models/drs_models.py | 29 +++ bbconf/modules/bedfiles.py | 103 +++++++--- bbconf/modules/objects.py | 177 +++++++++++++++++- tests/test_bbagent.py | 57 +++++- 8 files changed, 389 insertions(+), 275 deletions(-) create mode 100644 bbconf/models/__init__.py rename bbconf/{modules/models.py => models/bed_models.py} (89%) create mode 100644 bbconf/models/drs_models.py diff --git a/bbconf/bbagent.py b/bbconf/bbagent.py index f87e9bc3..f4fde5f1 100644 --- a/bbconf/bbagent.py +++ b/bbconf/bbagent.py @@ -38,157 +38,8 @@ def bed(self) -> BedAgentBedFile: # @property # def bedset(self): # return self.__bedset - # + # # # @property # def objects(self): # return self.__objects - # def get_prefixed_uri(self, postfix: str, access_id: str) -> str: - # """ - # Return uri with correct prefix (schema) - # - # :param postfix: postfix of the uri (or everything after uri schema) - # :param access_id: access method name - # :return: full uri path - # """ - # - # try: - # prefix = self.config[CFG_ACCESS_METHOD_KEY][access_id]["prefix"] - # return os.path.join(prefix, postfix) - # except KeyError: - # _LOGGER.error(f"Access method {access_id} is not defined.") - # raise BadAccessMethodError(f"Access method {access_id} is not defined.") - # - # def get_thumbnail_uri( - # self, - # record_type: Literal["bed", "bedset"], - # record_id: str, - # result_id: str, - # access_id: str = "http", - # ) -> str: - # """ - # Create URL to access a bed- or bedset-associated thumbnail - # - # :param record_type: table_name ["bed", "bedset"] - # :param record_id: record identifier - # :param result_id: column name (result name) - # :param access_id: access id (e.g. http, s3, etc.) - # :return: string with thumbnail - # """ - # - # try: - # result = self.get_result(record_type, record_id, result_id) - # return self.get_prefixed_uri(result["thumbnail_path"], access_id) - # except KeyError: - # _LOGGER.error( - # f"Thumbnail for {record_type} {record_id} {result_id} is not defined." - # ) - # raise MissingThumbnailError( - # f"Thumbnail for {record_type} {record_id} {result_id} is not defined." - # ) - # - # def get_object_uri( - # self, - # record_type: Literal["bed", "bedset"], - # record_id: str, - # result_id: str, - # access_id: str, - # ) -> str: - # """ - # Create URL to access a bed- or bedset-associated file - # - # :param record_type: table_name ["bed", "bedset"] - # :param record_id: record identifier - # :param result_id: column name (result name) - # :param access_id: access id (e.g. http, s3, etc.) - # :return: - # """ - # result = self.get_result(record_type, record_id, result_id) - # return self.get_prefixed_uri(result["path"], access_id) - # - # def get_result( - # self, - # record_type: Literal["bed", "bedset"], - # record_id: str, - # result_id: Union[str, List[str]], - # ) -> dict: - # """ - # Generic getter that can return a result from either bed or bedset - # - # :param record_type: table_name ["bed", "bedset"] - # :param record_id: record identifier - # :param result_id: column name (result name) - # :return: pipestat result - # """ - # if record_type == "bed": - # result = self.bed.retrieve_one(record_id, result_id) - # elif record_type == "bedset": - # result = self.bedset.retrieve_one(record_id, result_id) - # else: - # raise BedBaseConfError( - # f"Record type {record_type} is not supported. Only bed and bedset are supported." - # ) - # - # _LOGGER.info(f"Getting uri for {record_type} {record_id} {result_id}") - # _LOGGER.info(f"Result: {result}") - # return result - # - # def get_drs_metadata( - # self, - # record_type: Literal["bed", "bedset"], - # record_id: str, - # result_id: str, - # base_uri: str, - # ) -> DRSModel: - # """ - # Get DRS metadata for a bed- or bedset-associated file - # - # :param record_type: bed or bedset - # :param record_id: record identifier - # :param result_id: name of the result file to get metadata for - # :param base_uri: base uri to use for the self_uri field (server hostname of DRS broker) - # :return: DRS metadata - # """ - # - # access_methods = [] - # object_id = f"{record_type}.{record_id}.{result_id}" - # result_ids = [result_id, "pipestat_created_time", "pipestat_modified_time"] - # record_metadata = self.get_result( - # record_type, record_id, result_ids - # ) # only get result once - # if not record_metadata: - # raise RecordNotFoundError("This record does not exist") - # - # if not record_metadata[result_id] or not record_metadata[result_id]["path"]: - # raise MissingObjectError("This object does not exist") - # - # path = record_metadata[result_id]["path"] - # for access_id in self.config[CFG_ACCESS_METHOD_KEY].keys(): - # access_dict = AccessMethod( - # type=access_id, - # access_id=access_id, - # access_url=AccessURL(url=self.get_prefixed_uri(path, access_id)), - # region=self.config[CFG_ACCESS_METHOD_KEY][access_id].get( - # "region", None - # ), - # ) - # access_methods.append(access_dict) - # drs_dict = DRSModel( - # id=object_id, - # self_uri=f"drs://{base_uri}/{object_id}", - # size=record_metadata[result_id].get("size", "unknown"), - # created_time=record_metadata.get("pipestat_created_time", "unknown"), - # updated_time=record_metadata.get("pipestat_modified_time", "unknown"), - # checksums=object_id, - # access_methods=access_methods, - # ) - # - # return drs_dict - # - # def _read_config_file(self, config_path: str) -> dict: - # """ - # Read configuration file - # - # :param config_path: path to the configuration file - # :return: configuration dictionary - # """ diff --git a/bbconf/bbconf.py b/bbconf/bbconf.py index 5a4d9c08..02dd3f56 100644 --- a/bbconf/bbconf.py +++ b/bbconf/bbconf.py @@ -50,7 +50,7 @@ BadAccessMethodError, ) from bbconf.helpers import raise_missing_key, get_bedbase_cfg -from bbconf.models import DRSModel, AccessMethod, AccessURL +# from bbconf.models import DRSModel, AccessMethod, AccessURL from geniml.text2bednn import text2bednn from geniml.search import QdrantBackend @@ -667,54 +667,54 @@ def get_result( _LOGGER.info(f"Result: {result}") return result - def get_drs_metadata( - self, - record_type: Literal["bed", "bedset"], - record_id: str, - result_id: str, - base_uri: str, - ) -> DRSModel: - """ - Get DRS metadata for a bed- or bedset-associated file - - :param record_type: bed or bedset - :param record_id: record identifier - :param result_id: name of the result file to get metadata for - :param base_uri: base uri to use for the self_uri field (server hostname of DRS broker) - :return: DRS metadata - """ - - access_methods = [] - object_id = f"{record_type}.{record_id}.{result_id}" - result_ids = [result_id, "pipestat_created_time", "pipestat_modified_time"] - record_metadata = self.get_result( - record_type, record_id, result_ids - ) # only get result once - if not record_metadata: - raise RecordNotFoundError("This record does not exist") - - if not record_metadata[result_id] or not record_metadata[result_id]["path"]: - raise MissingObjectError("This object does not exist") - - path = record_metadata[result_id]["path"] - for access_id in self.config[CFG_ACCESS_METHOD_KEY].keys(): - access_dict = AccessMethod( - type=access_id, - access_id=access_id, - access_url=AccessURL(url=self.get_prefixed_uri(path, access_id)), - region=self.config[CFG_ACCESS_METHOD_KEY][access_id].get( - "region", None - ), - ) - access_methods.append(access_dict) - drs_dict = DRSModel( - id=object_id, - self_uri=f"drs://{base_uri}/{object_id}", - size=record_metadata[result_id].get("size", "unknown"), - created_time=record_metadata.get("pipestat_created_time", "unknown"), - updated_time=record_metadata.get("pipestat_modified_time", "unknown"), - checksums=object_id, - access_methods=access_methods, - ) - - return drs_dict + # def get_drs_metadata( + # self, + # record_type: Literal["bed", "bedset"], + # record_id: str, + # result_id: str, + # base_uri: str, + # ) -> DRSModel: + # """ + # Get DRS metadata for a bed- or bedset-associated file + # + # :param record_type: bed or bedset + # :param record_id: record identifier + # :param result_id: name of the result file to get metadata for + # :param base_uri: base uri to use for the self_uri field (server hostname of DRS broker) + # :return: DRS metadata + # """ + # + # access_methods = [] + # object_id = f"{record_type}.{record_id}.{result_id}" + # result_ids = [result_id, "pipestat_created_time", "pipestat_modified_time"] + # record_metadata = self.get_result( + # record_type, record_id, result_ids + # ) # only get result once + # if not record_metadata: + # raise RecordNotFoundError("This record does not exist") + # + # if not record_metadata[result_id] or not record_metadata[result_id]["path"]: + # raise MissingObjectError("This object does not exist") + # + # path = record_metadata[result_id]["path"] + # for access_id in self.config[CFG_ACCESS_METHOD_KEY].keys(): + # access_dict = AccessMethod( + # type=access_id, + # access_id=access_id, + # access_url=AccessURL(url=self.get_prefixed_uri(path, access_id)), + # region=self.config[CFG_ACCESS_METHOD_KEY][access_id].get( + # "region", None + # ), + # ) + # access_methods.append(access_dict) + # drs_dict = DRSModel( + # id=object_id, + # self_uri=f"drs://{base_uri}/{object_id}", + # size=record_metadata[result_id].get("size", "unknown"), + # created_time=record_metadata.get("pipestat_created_time", "unknown"), + # updated_time=record_metadata.get("pipestat_modified_time", "unknown"), + # checksums=object_id, + # access_methods=access_methods, + # ) + # + # return drs_dict diff --git a/bbconf/models/__init__.py b/bbconf/models/__init__.py new file mode 100644 index 00000000..935a5e3f --- /dev/null +++ b/bbconf/models/__init__.py @@ -0,0 +1,2 @@ +# from bedfiles import BedAgentBedFile +# from bedsets import BedAgentBedSet diff --git a/bbconf/modules/models.py b/bbconf/models/bed_models.py similarity index 89% rename from bbconf/modules/models.py rename to bbconf/models/bed_models.py index 5b2f847b..b935b906 100644 --- a/bbconf/modules/models.py +++ b/bbconf/models/bed_models.py @@ -1,18 +1,8 @@ import datetime -from typing import Optional, List, Union -import os -import pathlib +from typing import Optional, Union from pydantic import BaseModel, ConfigDict, Field -from bbconf.model_parser import yaml_to_pydantic - -from bbconf.const_new import ( - DEFAULT_VEC2VEC_MODEL, - DEFAULT_TEXT2VEC_MODEL, - DEFAULT_REGION2_VEC_MODEL, -) - class PlotModel(BaseModel): name: str = Field(alias="title") @@ -87,18 +77,6 @@ class BedStats(BaseModel): model_config = ConfigDict(extra="ignore") -class BedMetadata(BaseModel): - id: str - name: str - description: Optional[str] = None - submission_date: datetime.datetime = None - last_update_date: Optional[datetime.datetime] = None - stats: BedStats = None - classification: BedClassification = None - plots: BedPlots = None - files: BedFiles = None - - class BedPEPHub(BaseModel): sample_name: str genome: str @@ -121,8 +99,15 @@ class BedPEPHub(BaseModel): global_experiment_id: str = Field("", description="Global experiment identifier") description: str = Field("", description="Description of the sample") - # THIS IS NOW PART OF THE BedBase model in bbconf - # bed_format: FILE_TYPE = FILE_TYPE.BED - # bed_type: str = Field( - # default="bed3", pattern="^bed(?:[3-9]|1[0-5])(?:\+|$)[0-9]?+$" - # ) + +class BedMetadata(BaseModel): + id: str + name: str + description: Optional[str] = None + submission_date: datetime.datetime = None + last_update_date: Optional[datetime.datetime] = None + stats: BedStats = None + classification: BedClassification = None + plots: BedPlots = None + files: BedFiles = None + raw_metadata: Optional[BedPEPHub] = None diff --git a/bbconf/models/drs_models.py b/bbconf/models/drs_models.py new file mode 100644 index 00000000..5b38a152 --- /dev/null +++ b/bbconf/models/drs_models.py @@ -0,0 +1,29 @@ +import datetime +from typing import Optional, List, Union +from pydantic import BaseModel, ConfigDict + + +# DRS Models +class AccessURL(BaseModel): + url: str + headers: Optional[dict] = None + + +class AccessMethod(BaseModel): + type: str + access_url: Optional[AccessURL] = None + access_id: Optional[str] = None + region: Optional[str] = None + + +class DRSModel(BaseModel): + id: str + name: Optional[str] = None + self_uri: str + size: str + created_time: Optional[datetime.datetime] = None + updated_time: Optional[datetime.datetime] = None + checksums: str + access_methods: List[AccessMethod] + description: Optional[str] = None + diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index d0305df6..a830d126 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -14,7 +14,7 @@ from bbconf.const import ( PKG_NAME, ) -from bbconf.modules.models import ( +from bbconf.models.bed_models import ( BedMetadata, BedFiles, FileModel, @@ -88,6 +88,17 @@ def get(self, identifier: str) -> BedMetadata: bed_stats = BedStats(**bed_object.__dict__) bed_classification = BedClassification(**bed_object.__dict__) + try: + bed_metadata = self._config.phc.sample.get( + namespace=self._config.config.phc.namespace, + name=self._config.config.phc.name, + tag=self._config.config.phc.tag, + sample_name=identifier, + ) + except Exception as e: + _LOGGER.warning(f"Could not retrieve metadata from pephub. Error: {e}") + bed_metadata = {} + return BedMetadata( id=bed_object.id, name=bed_object.name, @@ -95,55 +106,102 @@ def get(self, identifier: str) -> BedMetadata: classification=bed_classification, plots=bed_plots, files=bed_files, - description="", + description=bed_object.description, submission_date=bed_object.submission_date, - last_update_date=bed_object.last_update_date + last_update_date=bed_object.last_update_date, + raw_metadata=BedPEPHub(**bed_metadata), ) - def get_stats(self, identifier: str) -> dict: + def get_stats(self, identifier: str) -> BedStats: """ Get file statistics by identifier. :param identifier: bed file identifier - :return: project statistics + + :return: project statistics as BedStats object """ - ... + statement = select(Bed).where(Bed.id == identifier) + + with Session(self._sa_engine) as session: + bed_object = session.scalar(statement) + bed_stats = BedStats(**bed_object.__dict__) - def get_plots(self, identifier: str) -> dict: + return bed_stats + + def get_plots(self, identifier: str) -> BedPlots: """ Get file plots by identifier. :param identifier: bed file identifier :return: project plots """ - ... + statement = select(Bed).where(Bed.id == identifier) - def get_files(self, identifier: str) -> dict: + with Session(self._sa_engine) as session: + bed_object = session.scalar(statement) + bed_plots = BedPlots() + for result in bed_object.plots: + setattr(bed_plots, result.name, PlotModel( + name=result.name, + path=result.path, + path_thumbnail=result.path_thumbnail, + description=result.description + )) + return bed_plots + + def get_files(self, identifier: str) -> BedFiles: """ Get file files by identifier. :param identifier: bed file identifier :return: project files """ - ... + statement = select(Bed).where(Bed.id == identifier) + + with Session(self._sa_engine) as session: + bed_object = session.scalar(statement) + bed_files = BedFiles() + for result in bed_object.files: + setattr(bed_files, result.name, FileModel( + name=result.name, + path=result.path, + description=result.description + )) + return bed_files - def get_metadata(self, identifier: str) -> dict: + def get_raw_metadata(self, identifier: str) -> BedPEPHub: """ Get file metadata by identifier. :param identifier: bed file identifier :return: project metadata """ - ... + try: + bed_metadata = self._config.phc.sample.get( + namespace=self._config.config.phc.namespace, + name=self._config.config.phc.name, + tag=self._config.config.phc.tag, + sample_name=identifier, + ) + except Exception as e: + _LOGGER.warning(f"Could not retrieve metadata from pephub. Error: {e}") + bed_metadata = {} + return BedPEPHub(**bed_metadata) - def get_classification(self, identifier: str) -> dict: + def get_classification(self, identifier: str) -> BedClassification: """ Get file classification by identifier. :param identifier: bed file identifier :return: project classification """ - ... + statement = select(Bed).where(Bed.id == identifier) + + with Session(self._sa_engine) as session: + bed_object = session.scalar(statement) + bed_classification = BedClassification(**bed_object.__dict__) + + return bed_classification def add( self, @@ -424,20 +482,3 @@ def text_to_bed_search(self, query: str, limit: int = 10, offset: int = 0): f"Couldn't find qdrant result in bedbase for id: {result['id']}" ) return results - - def _verify_results(self, results: dict) -> tuple: - """ - Verify if results are in the correct format - - :param results: results to verify - :return: True if results are correct, False if not - """ - table_annotations = Bed.__annotations__.keys() - correct_results = {} - unknown_results = {} - for key, value in results.items(): - if key in table_annotations: - correct_results[key] = value - else: - unknown_results[key] = value - return correct_results, unknown_results diff --git a/bbconf/modules/objects.py b/bbconf/modules/objects.py index b3a65733..6367bbb3 100644 --- a/bbconf/modules/objects.py +++ b/bbconf/modules/objects.py @@ -1,21 +1,180 @@ -from bbconf.db_utils import BaseEngine +import logging +import os +from typing import List, Union, Literal + +from bbconf.modules.bedfiles import BedAgentBedFile +from bbconf.config_parser.bedbaseconfig import BedBaseConfig +from bbconf.const import PKG_NAME +from bbconf.exceptions import ( + BadAccessMethodError, + MissingThumbnailError, + MissingObjectError, + BedBaseConfError, +) + +from bbconf.models.drs_models import AccessMethod, AccessURL, DRSModel + + +_LOGGER = logging.getLogger(PKG_NAME) class BBObjects: """ """ - def __init__(self, db_engine: BaseEngine): + def __init__(self, config: BedBaseConfig): """ :param db_engine: pepdbengine object with sa engine """ - self._sa_engine = db_engine.engine - self._db_engine = db_engine + self.config = config + self.bed = BedAgentBedFile(self.config) + + def get_prefixed_uri(self, postfix: str, access_id: str) -> str: + """ + Return uri with correct prefix (schema) + + :param postfix: postfix of the uri (or everything after uri schema) + :param access_id: access method name, e.g. http, s3, etc. + :return: full uri path + """ + + try: + prefix = getattr(self.config.config.access_methods, access_id).prefix + return os.path.join(prefix, postfix) + except KeyError: + _LOGGER.error(f"Access method {access_id} is not defined.") + raise BadAccessMethodError(f"Access method {access_id} is not defined.") + + def get_thumbnail_uri( + self, + record_type: Literal["bed", "bedset"], + record_id: str, + result_id: str, + access_id: str = "http", + ) -> str: + """ + Create URL to access a bed- or bedset-associated thumbnail + + :param record_type: table_name ["bed", "bedset"] + :param record_id: record identifier + :param result_id: column name (result name) + :param access_id: access id (e.g. http, s3, etc.) + :return: string with thumbnail + """ + if record_type == "bed": + ... + elif record_type == "bedset": + ... + else: + raise BedBaseConfError( + f"Record type {record_type} is not supported. Only bed and bedset are supported." + ) + try: + self.bed.get_plots(identifier=record_id) + + result = self.get_result(record_type, record_id, result_id) + return self.get_prefixed_uri(result["thumbnail_path"], access_id) + except KeyError: + _LOGGER.error( + f"Thumbnail for {record_type} {record_id} {result_id} is not defined." + ) + raise MissingThumbnailError( + f"Thumbnail for {record_type} {record_id} {result_id} is not defined." + ) - def get(self, identifier: str) -> dict: + def get_object_uri( + self, + record_type: Literal["bed", "bedset"], + record_id: str, + result_id: str, + access_id: str, + ) -> str: """ - Get file metadata by identifier. + Create URL to access a bed- or bedset-associated file - :param identifier: bed file identifier - :return: project metadata + :param record_type: table_name ["bed", "bedset"] + :param record_id: record identifier + :param result_id: column name (result name) + :param access_id: access id (e.g. http, s3, etc.) + :return: """ - ... + result = self.get_result(record_type, record_id, result_id) + return self.get_prefixed_uri(result["path"], access_id) + + def get_result( + self, + record_type: Literal["bed", "bedset"], + record_id: str, + result_id: Union[str, List[str]], + ) -> dict: + """ + Generic getter that can return a result from either bed or bedset + + :param record_type: table_name ["bed", "bedset"] + :param record_id: record identifier + :param result_id: column name (result name). e.g. "bigbedfile", "bed_file", "open_chromatin" + :return: pipestat result + """ + if record_type == "bed": + result = self.bed.retrieve_one(record_id, result_id) + elif record_type == "bedset": + result = self.bedset.retrieve_one(record_id, result_id) + else: + raise BedBaseConfError( + f"Record type {record_type} is not supported. Only bed and bedset are supported." + ) + + _LOGGER.info(f"Getting uri for {record_type} {record_id} {result_id}") + _LOGGER.info(f"Result: {result}") + return result + + def get_drs_metadata( + self, + record_type: Literal["bed", "bedset"], + record_id: str, + result_id: str, + base_uri: str, + ) -> DRSModel: + """ + Get DRS metadata for a bed- or bedset-associated file + + :param record_type: bed or bedset + :param record_id: record identifier + :param result_id: name of the result file to get metadata for + :param base_uri: base uri to use for the self_uri field (server hostname of DRS broker) + :return: DRS metadata + """ + + access_methods = [] + object_id = f"{record_type}.{record_id}.{result_id}" + result_ids = [result_id, "pipestat_created_time", "pipestat_modified_time"] + record_metadata = self.get_result( + record_type, record_id, result_ids + ) # only get result once + if not record_metadata: + raise RecordNotFoundError("This record does not exist") + + if not record_metadata[result_id] or not record_metadata[result_id]["path"]: + raise MissingObjectError("This object does not exist") + + path = record_metadata[result_id]["path"] + for access_id in self.config[CFG_ACCESS_METHOD_KEY].keys(): + access_dict = AccessMethod( + type=access_id, + access_id=access_id, + access_url=AccessURL(url=self.get_prefixed_uri(path, access_id)), + region=self.config[CFG_ACCESS_METHOD_KEY][access_id].get( + "region", None + ), + ) + access_methods.append(access_dict) + drs_dict = DRSModel( + id=object_id, + self_uri=f"drs://{base_uri}/{object_id}", + size=record_metadata[result_id].get("size", "unknown"), + created_time=record_metadata.get("pipestat_created_time", "unknown"), + updated_time=record_metadata.get("pipestat_modified_time", "unknown"), + checksums=object_id, + access_methods=access_methods, + ) + + return drs_dict \ No newline at end of file diff --git a/tests/test_bbagent.py b/tests/test_bbagent.py index cde4ef50..43bea48d 100644 --- a/tests/test_bbagent.py +++ b/tests/test_bbagent.py @@ -27,8 +27,55 @@ def db_setup(): def test_bb_database(): assert db_setup() -def test_get(): - agent = BedBaseAgent(config=config) - ff = agent.bed.get("91b2754c8ff01769bacfc80e6923c46e") - print(ff) - assert ff != None \ No newline at end of file + +class Test_BedFile_Agent: + + def test_upload(self): + agent = BedBaseAgent(config=config) + agent.bed.add( + + ) + + def test_get_all(self): + agent = BedBaseAgent(config=config) + ff = agent.bed.get("91b2754c8ff01769bacfc80e6923c46e") + print(ff) + assert ff != None + + def test_get_raw_metadata(self): + agent = BedBaseAgent(config=config) + ff = agent.bed.get_raw_metadata("91b2754c8ff01769bacfc80e6923c46e") + print(ff) + assert ff != None + + def test_get_stats(self): + agent = BedBaseAgent(config=config) + ff = agent.bed.get_stats("91b2754c8ff01769bacfc80e6923c46e") + print(ff) + assert ff != None + + def test_get_files(self): + agent = BedBaseAgent(config=config) + ff = agent.bed.get_files("91b2754c8ff01769bacfc80e6923c46e") + print(ff) + assert ff != None + + def test_get_plots(self): + agent = BedBaseAgent(config=config) + ff = agent.bed.get_plots("91b2754c8ff01769bacfc80e6923c46e") + print(ff) + assert ff != None + + def test_bed_delete(self): + # agent = BedBaseAgent(config=config) + # ff = agent.bed.delete("91b2754c8ff01769bacfc80e6923c46e") + # print(ff) + # assert ff != None + pass + + def test_bed_update(self): + # agent = BedBaseAgent(config=config) + # ff = agent.bed.update("91b2754c8ff01769bacfc80e6923c46e", {"number_of_regions": 44}) + # print(ff) + # assert ff != None + pass From f54961fc2d906eab75d5af724d8a23a7a345ba66 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Tue, 19 Mar 2024 20:08:21 +0100 Subject: [PATCH 08/61] added objects --- MANIFEST.in | 1 + bbconf/bbagent.py | 8 +-- bbconf/db_utils.py | 46 ++++++++------- bbconf/models/bed_models.py | 42 +++++++------- bbconf/{models.py => models_old.py} | 0 bbconf/modules/bedfiles.py | 88 +++++++++++++++++++---------- bbconf/modules/objects.py | 61 +++++++++----------- tests/test_bbagent.py | 29 ++++++++++ 8 files changed, 167 insertions(+), 108 deletions(-) rename bbconf/{models.py => models_old.py} (100%) diff --git a/MANIFEST.in b/MANIFEST.in index e95406d7..0126442a 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -4,3 +4,4 @@ include requirements/* include bbconf/schemas/* include bbconf/modules/* include bbconf/config_parser/* +include bbconf/models/* diff --git a/bbconf/bbagent.py b/bbconf/bbagent.py index f4fde5f1..4be16e5a 100644 --- a/bbconf/bbagent.py +++ b/bbconf/bbagent.py @@ -29,7 +29,7 @@ def __init__( # ff # self.__bedset = BedAgentBedSet(self.config) - # self.__objects = BBObjects(self.config) + self.__objects = BBObjects(self.config) @property def bed(self) -> BedAgentBedFile: @@ -39,7 +39,7 @@ def bed(self) -> BedAgentBedFile: # def bedset(self): # return self.__bedset # # - # @property - # def objects(self): - # return self.__objects + @property + def objects(self): + return self.__objects diff --git a/bbconf/db_utils.py b/bbconf/db_utils.py index 70214263..398d7631 100644 --- a/bbconf/db_utils.py +++ b/bbconf/db_utils.py @@ -125,7 +125,7 @@ class Bed(Base): tssdist: Mapped[Optional[int]] # relations: - plots: Mapped[List["Plots"]] = relationship("Plots", back_populates="bedfile") + # plots: Mapped[List["Plots"]] = relationship("Plots", back_populates="bedfile") files: Mapped[List["Files"]] = relationship("Files", back_populates="bedfile") bedsets: Mapped[List["BedFileBedSetRelation"]] = relationship( @@ -140,7 +140,13 @@ class Files(Base): name: Mapped[str] = mapped_column( nullable=False, comment="Name of the file, e.g. bed, bigBed" ) + type: Mapped[str] = mapped_column( + default="file", comment="Type of the object, e.g. file, plot, ..." + ) path: Mapped[str] + path_thumbnail: Mapped[str] = mapped_column( + nullable=True, comment="Thumbnail path of the file" + ) description: Mapped[Optional[str]] size: Mapped[Optional[str]] = mapped_column(comment="Size of the file") @@ -151,24 +157,24 @@ class Files(Base): bedset: Mapped["BedSets"] = relationship("BedSets", back_populates="files") -class Plots(Base): - __tablename__ = "plots" - - id: Mapped[int] = mapped_column(primary_key=True) - name: Mapped[str] = mapped_column(nullable=False, comment="Name of the plot") - description: Mapped[Optional[str]] = mapped_column( - comment="Description of the plot" - ) - path: Mapped[str] = mapped_column(comment="Path to the plot file") - path_thumbnail: Mapped[str] = mapped_column( - nullable=True, comment="Path to the thumbnail of the plot file" - ) - - bedfile_id: Mapped[int] = mapped_column(ForeignKey("bed.id"), nullable=True) - bedset_id: Mapped[int] = mapped_column(ForeignKey("bedsets.id"), nullable=True) - - bedfile: Mapped["Bed"] = relationship("Bed", back_populates="plots") - bedset: Mapped["BedSets"] = relationship("BedSets", back_populates="plots") +# class Plots(Base): +# __tablename__ = "plots" +# +# id: Mapped[int] = mapped_column(primary_key=True) +# name: Mapped[str] = mapped_column(nullable=False, comment="Name of the plot") +# description: Mapped[Optional[str]] = mapped_column( +# comment="Description of the plot" +# ) +# path: Mapped[str] = mapped_column(comment="Path to the plot file") +# path_thumbnail: Mapped[str] = mapped_column( +# nullable=True, comment="Path to the thumbnail of the plot file" +# ) +# +# bedfile_id: Mapped[int] = mapped_column(ForeignKey("bed.id"), nullable=True) +# bedset_id: Mapped[int] = mapped_column(ForeignKey("bedsets.id"), nullable=True) +# +# bedfile: Mapped["Bed"] = relationship("Bed", back_populates="plots") +# bedset: Mapped["BedSets"] = relationship("BedSets", back_populates="plots") class BedFileBedSetRelation(Base): @@ -207,7 +213,7 @@ class BedSets(Base): bedfiles: Mapped[List["BedFileBedSetRelation"]] = relationship( "BedFileBedSetRelation", back_populates="bedset" ) - plots: Mapped[List["Plots"]] = relationship("Plots", back_populates="bedset") + # plots: Mapped[List["Plots"]] = relationship("Plots", back_populates="bedset") files: Mapped[List["Files"]] = relationship("Files", back_populates="bedset") diff --git a/bbconf/models/bed_models.py b/bbconf/models/bed_models.py index b935b906..6ca3b61d 100644 --- a/bbconf/models/bed_models.py +++ b/bbconf/models/bed_models.py @@ -4,33 +4,35 @@ from pydantic import BaseModel, ConfigDict, Field -class PlotModel(BaseModel): +# class PlotModel(BaseModel): +# name: str = Field(alias="title") +# path: str +# path_thumbnail: Optional[Union[str, None]] = Field(None, alias="thumbnail_path") +# description: Optional[Union[str, None]] = None +# +# model_config = ConfigDict(populate_by_name=True) + +class FileModel(BaseModel): name: str = Field(alias="title") path: str path_thumbnail: Optional[Union[str, None]] = Field(None, alias="thumbnail_path") - description: Optional[Union[str, None]] = None + description: Optional[str] = None + size: Optional[str] = None model_config = ConfigDict(populate_by_name=True) class BedPlots(BaseModel): - chrombins: PlotModel = None - gccontent: PlotModel = None - partitions: PlotModel = None - expected_partitions: PlotModel = None - cumulative_partitions: PlotModel = None - widths_histogram: PlotModel = None - neighbor_distances: PlotModel = None - open_chromatin: PlotModel = None + chrombins: FileModel = None + gccontent: FileModel = None + partitions: FileModel = None + expected_partitions: FileModel = None + cumulative_partitions: FileModel = None + widths_histogram: FileModel = None + neighbor_distances: FileModel = None + open_chromatin: FileModel = None - -class FileModel(BaseModel): - name: str = Field(alias="title") - path: str - description: Optional[str] = None - size: Optional[str] = None - - model_config = ConfigDict(populate_by_name=True) + model_config = ConfigDict(extra="ignore") class BedFiles(BaseModel): @@ -39,7 +41,7 @@ class BedFiles(BaseModel): model_config = ConfigDict( populate_by_name=True, - extra="allow", + extra="ignore", ) @@ -54,6 +56,7 @@ class BedClassification(BaseModel): model_config = ConfigDict(extra="ignore") + class BedStats(BaseModel): number_of_regions: Optional[float] = None gc_content: Optional[float] = None @@ -111,3 +114,4 @@ class BedMetadata(BaseModel): plots: BedPlots = None files: BedFiles = None raw_metadata: Optional[BedPEPHub] = None + diff --git a/bbconf/models.py b/bbconf/models_old.py similarity index 100% rename from bbconf/models.py rename to bbconf/models_old.py diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index a830d126..84c685de 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -7,7 +7,7 @@ from geniml.io import RegionSet from sqlalchemy.orm import Session -from sqlalchemy import select +from sqlalchemy import select, and_, or_ import os @@ -21,13 +21,12 @@ BedPlots, BedClassification, BedStats, - PlotModel, BedPEPHub, ) from bbconf.exceptions import ( BedBaseConfError, ) -from bbconf.db_utils import BaseEngine, Bed, Plots, Files +from bbconf.db_utils import BaseEngine, Bed, Files from bbconf.config_parser.bedbaseconfig import BedBaseConfig _LOGGER = getLogger(PKG_NAME) @@ -70,20 +69,26 @@ def get(self, identifier: str) -> BedMetadata: with Session(self._sa_engine) as session: bed_object = session.scalar(statement) - for result in bed_object.plots: - setattr(bed_plots, result.name, PlotModel( - name=result.name, - path=result.path, - path_thumbnail=result.path_thumbnail, - description=result.description - )) - for result in bed_object.files: - setattr(bed_files, result.name, FileModel( - name=result.name, - path=result.path, - description=result.description - )) + # PLOTS + if result.name in BedPlots.model_fields: + setattr(bed_plots, result.name, FileModel( + name=result.name, + path=result.path, + size=result.size, + path_thumbnail=result.path_thumbnail, + description=result.description + )) + # FILES + elif result.name in BedFiles.model_fields: + setattr(bed_files, result.name, FileModel( + name=result.name, + path=result.path, + size=result.size, + description=result.description + )) + else: + _LOGGER.error(f"Unknown file type: {result.name}. And is not in the model fields. Skipping..") bed_stats = BedStats(**bed_object.__dict__) bed_classification = BedClassification(**bed_object.__dict__) @@ -140,13 +145,14 @@ def get_plots(self, identifier: str) -> BedPlots: with Session(self._sa_engine) as session: bed_object = session.scalar(statement) bed_plots = BedPlots() - for result in bed_object.plots: - setattr(bed_plots, result.name, PlotModel( - name=result.name, - path=result.path, - path_thumbnail=result.path_thumbnail, - description=result.description - )) + for result in bed_object.files: + if result.name in BedPlots.model_fields: + setattr(bed_plots, result.name, FileModel( + name=result.name, + path=result.path, + path_thumbnail=result.path_thumbnail, + description=result.description + )) return bed_plots def get_files(self, identifier: str) -> BedFiles: @@ -162,11 +168,12 @@ def get_files(self, identifier: str) -> BedFiles: bed_object = session.scalar(statement) bed_files = BedFiles() for result in bed_object.files: - setattr(bed_files, result.name, FileModel( - name=result.name, - path=result.path, - description=result.description - )) + if result.name in BedFiles.model_fields: + setattr(bed_files, result.name, FileModel( + name=result.name, + path=result.path, + description=result.description + )) return bed_files def get_raw_metadata(self, identifier: str) -> BedPEPHub: @@ -203,6 +210,24 @@ def get_classification(self, identifier: str) -> BedClassification: return bed_classification + def get_objects(self, identifier: str) -> Dict[str, FileModel]: + """ + Get all object related to bedfile + + :param identifier: bed file identifier + :return: project objects dict + """ + statement = select(Bed).where(Bed.id == identifier) + return_dict = {} + + with Session(self._sa_engine) as session: + bed_object = session.scalar(statement) + for result in bed_object.files: + return_dict[result.name] = FileModel(**result.__dict__) + + return return_dict + + def add( self, identifier: str, @@ -278,16 +303,19 @@ def add( path=v.path, description=v.description, bedfile_id=identifier, + type="file", + size=v.size, ) session.add(new_file) for k, v in plots: if v: - new_plot = Plots( + new_plot = Files( name=k, path=v.path, path_thumbnail=v.path_thumbnail, description=v.description, bedfile_id=identifier, + type="plot" ) session.add(new_plot) @@ -382,7 +410,7 @@ def upload_plots_s3( setattr( plots_output, key, - PlotModel( + FileModel( name=value.name, path=file_s3_path, path_thumbnail=file_s3_path_thumbnail, diff --git a/bbconf/modules/objects.py b/bbconf/modules/objects.py index 6367bbb3..f45bfc3c 100644 --- a/bbconf/modules/objects.py +++ b/bbconf/modules/objects.py @@ -13,6 +13,7 @@ ) from bbconf.models.drs_models import AccessMethod, AccessURL, DRSModel +from bbconf.models.bed_models import FileModel _LOGGER = logging.getLogger(PKG_NAME) @@ -28,7 +29,7 @@ def __init__(self, config: BedBaseConfig): self.config = config self.bed = BedAgentBedFile(self.config) - def get_prefixed_uri(self, postfix: str, access_id: str) -> str: + def _get_prefixed_uri(self, postfix: str, access_id: str) -> str: """ Return uri with correct prefix (schema) @@ -60,20 +61,11 @@ def get_thumbnail_uri( :param access_id: access id (e.g. http, s3, etc.) :return: string with thumbnail """ - if record_type == "bed": - ... - elif record_type == "bedset": - ... - else: - raise BedBaseConfError( - f"Record type {record_type} is not supported. Only bed and bedset are supported." - ) - try: - self.bed.get_plots(identifier=record_id) + result = self._get_result(record_type, record_id, result_id) + if result.path_thumbnail: + return self._get_prefixed_uri(result.path_thumbnail, access_id) - result = self.get_result(record_type, record_id, result_id) - return self.get_prefixed_uri(result["thumbnail_path"], access_id) - except KeyError: + else: _LOGGER.error( f"Thumbnail for {record_type} {record_id} {result_id} is not defined." ) @@ -97,15 +89,15 @@ def get_object_uri( :param access_id: access id (e.g. http, s3, etc.) :return: """ - result = self.get_result(record_type, record_id, result_id) - return self.get_prefixed_uri(result["path"], access_id) + result = self._get_result(record_type, record_id, result_id) + return self._get_prefixed_uri(result.path, access_id) - def get_result( + def _get_result( self, record_type: Literal["bed", "bedset"], record_id: str, result_id: Union[str, List[str]], - ) -> dict: + ) -> FileModel: """ Generic getter that can return a result from either bed or bedset @@ -115,9 +107,12 @@ def get_result( :return: pipestat result """ if record_type == "bed": - result = self.bed.retrieve_one(record_id, result_id) + result = self.bed.get_objects(identifier=record_id)[result_id] elif record_type == "bedset": - result = self.bedset.retrieve_one(record_id, result_id) + # result = self.bedset.retrieve_one(record_id, result_id) + _LOGGER.error("Not implemented") + return {} + else: raise BedBaseConfError( f"Record type {record_type} is not supported. Only bed and bedset are supported." @@ -146,23 +141,19 @@ def get_drs_metadata( access_methods = [] object_id = f"{record_type}.{record_id}.{result_id}" - result_ids = [result_id, "pipestat_created_time", "pipestat_modified_time"] - record_metadata = self.get_result( - record_type, record_id, result_ids - ) # only get result once + bed_result = self.bed.get(record_id) + created_time = bed_result.submission_date + modified_time = bed_result.last_update_date + record_metadata = self._get_result(record_type, record_id, result_id) # only get result once if not record_metadata: - raise RecordNotFoundError("This record does not exist") - - if not record_metadata[result_id] or not record_metadata[result_id]["path"]: - raise MissingObjectError("This object does not exist") + raise BedBaseConfError(f"Record not found") - path = record_metadata[result_id]["path"] - for access_id in self.config[CFG_ACCESS_METHOD_KEY].keys(): + for access_id in self.config.config.access_methods.model_dump().keys(): access_dict = AccessMethod( type=access_id, access_id=access_id, - access_url=AccessURL(url=self.get_prefixed_uri(path, access_id)), - region=self.config[CFG_ACCESS_METHOD_KEY][access_id].get( + access_url=AccessURL(url=self._get_prefixed_uri(record_metadata.path, access_id)), + region=self.config.config.access_methods.model_dump()[access_id].get( "region", None ), ) @@ -170,9 +161,9 @@ def get_drs_metadata( drs_dict = DRSModel( id=object_id, self_uri=f"drs://{base_uri}/{object_id}", - size=record_metadata[result_id].get("size", "unknown"), - created_time=record_metadata.get("pipestat_created_time", "unknown"), - updated_time=record_metadata.get("pipestat_modified_time", "unknown"), + size=record_metadata.size or "unknown", + created_time=created_time, + updated_time=modified_time, checksums=object_id, access_methods=access_methods, ) diff --git a/tests/test_bbagent.py b/tests/test_bbagent.py index 43bea48d..704582f4 100644 --- a/tests/test_bbagent.py +++ b/tests/test_bbagent.py @@ -66,6 +66,11 @@ def test_get_plots(self): print(ff) assert ff != None + def test_get_objects(self): + agent = BedBaseAgent(config=config) + ff = agent.bed.get_objects("91b2754c8ff01769bacfc80e6923c46e") + print(ff) + def test_bed_delete(self): # agent = BedBaseAgent(config=config) # ff = agent.bed.delete("91b2754c8ff01769bacfc80e6923c46e") @@ -79,3 +84,27 @@ def test_bed_update(self): # print(ff) # assert ff != None pass + + +class TestObjects(): + def test_object_path(self): + agent = BedBaseAgent(config=config) + ff = agent.objects.get_object_uri("bed", "91b2754c8ff01769bacfc80e6923c46e", "bed_file", "http") + ff + + def test_object_path_thumbnail_error(self): + agent = BedBaseAgent(config=config) + # TODO: it should raise issue: + ff = agent.objects.get_thumbnail_uri("bed", "91b2754c8ff01769bacfc80e6923c46e", "bed_file", "http") + ff + + def test_object_path_thumbnail(self): + agent = BedBaseAgent(config=config) + # TODO: it should raise issue: + ff = agent.objects.get_thumbnail_uri("bed", "91b2754c8ff01769bacfc80e6923c46e", "widths_histogram", "http") + ff + + def test_object_metadata(self): + agent = BedBaseAgent(config=config) + ff = agent.objects.get_drs_metadata("bed", "91b2754c8ff01769bacfc80e6923c46e", "widths_histogram", "localhost") + ff From 42455da804421739e412aff4e7945443557f7b56 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Tue, 19 Mar 2024 22:39:30 +0100 Subject: [PATCH 09/61] cleaning --- bbconf/__init__.py | 4 +- bbconf/_version.py | 2 +- bbconf/bbagent.py | 2 - bbconf/bbconf.py | 720 -------------------------- bbconf/config_parser/bedbaseconfig.py | 4 +- bbconf/config_parser/const.py | 23 +- bbconf/config_parser/models.py | 40 +- bbconf/const.py | 98 ---- bbconf/const_new.py | 70 --- bbconf/exceptions.py | 10 - bbconf/helpers.py | 17 +- bbconf/model_parser.py | 125 ----- bbconf/models/bed_models.py | 2 +- bbconf/models/drs_models.py | 1 - bbconf/models_old.py | 53 -- bbconf/modules/bedfiles.py | 72 ++- bbconf/modules/objects.py | 52 +- bbconf/schemas/bedfiles_schema.yaml | 149 ------ bbconf/schemas/bedsets_schema.yaml | 54 -- tests/test_bbagent.py | 22 +- 20 files changed, 144 insertions(+), 1376 deletions(-) delete mode 100644 bbconf/bbconf.py delete mode 100644 bbconf/const_new.py delete mode 100644 bbconf/model_parser.py delete mode 100644 bbconf/models_old.py delete mode 100644 bbconf/schemas/bedfiles_schema.yaml delete mode 100644 bbconf/schemas/bedsets_schema.yaml diff --git a/bbconf/__init__.py b/bbconf/__init__.py index 2b5105dc..f5de3d37 100644 --- a/bbconf/__init__.py +++ b/bbconf/__init__.py @@ -1,11 +1,11 @@ import logging import coloredlogs -from bbconf.bbconf import BedBaseConf, get_bedbase_cfg from ._version import __version__ from .const import PKG_NAME +from bbconf.bbagent import BedBaseAgent -__all__ = ["BedBaseConf", "get_bedbase_cfg", "__version__"] +__all__ = ["BedBaseAgent", "__version__"] _LOGGER = logging.getLogger(PKG_NAME) coloredlogs.install( diff --git a/bbconf/_version.py b/bbconf/_version.py index 36370558..c6422df7 100644 --- a/bbconf/_version.py +++ b/bbconf/_version.py @@ -1 +1 @@ -__version__ = "0.5.0a1" +__version__ = "0.6.0a1" diff --git a/bbconf/bbagent.py b/bbconf/bbagent.py index 4be16e5a..5e95a33c 100644 --- a/bbconf/bbagent.py +++ b/bbconf/bbagent.py @@ -3,7 +3,6 @@ from bbconf.config_parser.bedbaseconfig import BedBaseConfig -from bbconf.db_utils import POSTGRES_DIALECT, BaseEngine from bbconf.modules.bedfiles import BedAgentBedFile from bbconf.modules.bedsets import BedAgentBedSet from bbconf.modules.objects import BBObjects @@ -42,4 +41,3 @@ def bed(self) -> BedAgentBedFile: @property def objects(self): return self.__objects - diff --git a/bbconf/bbconf.py b/bbconf/bbconf.py deleted file mode 100644 index 02dd3f56..00000000 --- a/bbconf/bbconf.py +++ /dev/null @@ -1,720 +0,0 @@ -import os -from logging import getLogger -from typing import List, Optional, Dict, Union, Literal -from textwrap import indent - -import yacman -from pipestat import PipestatManager -from pipestat.exceptions import RecordNotFoundError, SchemaError - -from sqlmodel import SQLModel, Field, select -import qdrant_client - -from sqlalchemy.orm import relationship -from sqlalchemy import inspect -import numpy as np - -from bbconf.const import ( - CFG_PATH_KEY, - CFG_PATH_PIPELINE_OUTPUT_KEY, - CFG_PATH_BEDSTAT_DIR_KEY, - CFG_PATH_TEXT2VEC_KEY, - DEFAULT_SECTION_VALUES, - CFG_PATH_BEDBUNCHER_DIR_KEY, - BED_TABLE, - BED_TABLE_SCHEMA, - BEDSET_TABLE, - BEDSET_TABLE_SCHEMA, - BEDFILE_BEDSET_ASSOCIATION_TABLE_KEY, - CFG_REMOTE_KEY, - BEDSETS_REL_KEY, - BEDFILES_REL_KEY, - CFG_PATH_REGION2VEC_KEY, - CFG_PATH_VEC2VEC_KEY, - CFG_QDRANT_KEY, - CFG_QDRANT_PORT_KEY, - CFG_QDRANT_API_KEY, - CFG_QDRANT_HOST_KEY, - CFG_QDRANT_COLLECTION_NAME_KEY, - DEFAULT_TEXT2VEC_MODEL, - DEFAULT_VEC2VEC_MODEL, - DEFAULT_REGION2_VEC_MODEL, - CFG_ACCESS_METHOD_KEY, - PKG_NAME, -) -from bbconf.exceptions import ( - BedBaseConfError, - MissingConfigDataError, - MissingThumbnailError, - MissingObjectError, - BadAccessMethodError, -) -from bbconf.helpers import raise_missing_key, get_bedbase_cfg -# from bbconf.models import DRSModel, AccessMethod, AccessURL - -from geniml.text2bednn import text2bednn -from geniml.search import QdrantBackend -from fastembed.embedding import FlagEmbedding -from geniml.region2vec import Region2VecExModel -from geniml.io import RegionSet - -_LOGGER = getLogger(PKG_NAME) - - -class BedBaseConf: - """ - This class standardizes reporting of bedstat and bedbuncher results. - It formalizes a way for these pipelines and downstream tools - to communicate -- the produced results can easily and reliably become an - input for the server. The object exposes API for interacting with the - results and is backed by a [PostgreSQL](https://www.postgresql.org/) - database. - """ - - def __init__(self, config_path: str = None, database_only: bool = False): - """ - Initialize the object - - :param str config_path: path to the bedbase configuration file - :param bool database_only: whether the database managers should not - keep an in-memory copy of the data in the database - """ - - cfg_path = get_bedbase_cfg(config_path) - - self._config = self._read_config_file(cfg_path) - - # Create Pipestat objects and tables if they do not exist - _LOGGER.debug("Creating pipestat objects...") - self.__pipestats = { - BED_TABLE: PipestatManager( - config_file=cfg_path, - schema_path=BED_TABLE_SCHEMA, - database_only=database_only, - ), - BEDSET_TABLE: PipestatManager( - config_file=cfg_path, - schema_path=BEDSET_TABLE_SCHEMA, - database_only=database_only, - ), - } - - self._create_bedset_bedfiles_table() - - # setup t2bsi object - self._t2bsi = None - try: - self._senta2vec_hg_model_name = self.config[CFG_PATH_KEY].get( - CFG_PATH_TEXT2VEC_KEY, DEFAULT_TEXT2VEC_MODEL - ) - _LOGGER.debug("Setting up qdrant database connection...") - self._qdrant_backend = self._init_qdrant_backend() - - if self.config[CFG_PATH_KEY].get(CFG_PATH_REGION2VEC_KEY) and self.config[ - CFG_PATH_KEY - ].get(CFG_PATH_VEC2VEC_KEY): - self.region2vec_model = self.config[CFG_PATH_KEY].get( - CFG_PATH_REGION2VEC_KEY - ) - self._t2bsi = self._create_t2bsi_object() - else: - if not self.config[CFG_PATH_KEY].get(CFG_PATH_REGION2VEC_KEY): - _LOGGER.debug( - f"{CFG_PATH_REGION2VEC_KEY} was not provided in config file! Using default.." - ) - self.region2vec_model = DEFAULT_REGION2_VEC_MODEL - else: - self.region2vec_model = self.config[CFG_PATH_KEY].get( - CFG_PATH_REGION2VEC_KEY - ) - - if not self.config[CFG_PATH_KEY].get(CFG_PATH_VEC2VEC_KEY): - self.config[CFG_PATH_KEY][ - CFG_PATH_VEC2VEC_KEY - ] = DEFAULT_VEC2VEC_MODEL - - except qdrant_client.http.exceptions.ResponseHandlingException as err: - _LOGGER.error(f"error in Connection to qdrant! skipping... Error: {err}") - - def _read_config_file(self, config_path: str) -> dict: - """ - Read configuration file and insert default values if not set - - :param config_path: configuration file path - :return: None - :raises: raise_missing_key (if config key is missing) - """ - _config = yacman.YAMLConfigManager(filepath=config_path).exp - - if CFG_PATH_KEY not in _config: - raise_missing_key(CFG_PATH_KEY) - - if not _config[CFG_PATH_KEY]: - _config[CFG_PATH_KEY] = {} - - if CFG_PATH_PIPELINE_OUTPUT_KEY not in _config[CFG_PATH_KEY]: - raise_missing_key(CFG_PATH_PIPELINE_OUTPUT_KEY) - - if CFG_PATH_BEDSTAT_DIR_KEY not in _config[CFG_PATH_KEY]: - raise_missing_key(CFG_PATH_BEDSTAT_DIR_KEY) - - if CFG_PATH_BEDBUNCHER_DIR_KEY not in _config[CFG_PATH_KEY]: - raise_missing_key(CFG_PATH_BEDBUNCHER_DIR_KEY) - - # Setting default values if doesn't exist in config file - for section, mapping in DEFAULT_SECTION_VALUES.items(): - if section not in _config: - _config[section] = {} - for key, default in mapping.items(): - if key not in _config[section]: - _LOGGER.debug( - f"Config lacks '{section}.{key}' key. Setting to: {default}" - ) - _config[section][key] = default - - if CFG_PATH_REGION2VEC_KEY not in _config[CFG_PATH_KEY]: - _LOGGER.warning("Region2vec config key is missing in configuration file") - _config[CFG_PATH_KEY][CFG_PATH_REGION2VEC_KEY] = None - - return _config - - def search_bed_by_text( - self, query: str - ) -> List[Dict[str, Union[int, float, Dict[str, str], List[float]]]]: - """ - Search for bed files by text query in the qdrant database - - :param query: strign query provided by user - :return: a list of dictionary that contains the search results in this format: - { - "id": - "score": - "payload": { - - } - "vector": [] - } - """ - if self._t2bsi is None: - raise BedBaseConfError( - "Can't perform search, ensure qdrant_db credentials in config file" - ) - return self._t2bsi.nl_vec_search(query) - - def __str__(self): - """ - Generate string representation of the object - - :return str: string representation of the object - """ - - res = f"{self.__class__.__name__}\n" - res += f"{BED_TABLE}:\n" - res += f"{indent(str(self.bed), ' ')}" - res += f"\n{BEDSET_TABLE}:\n" - res += f"{indent(str(self.bedset), ' ')}" - res += "\nconfig:\n" - res += f"{indent(str(self.config), ' ')}" - return res - - @property - def config(self) -> dict: - """ - Config used to initialize the object - - :return dict: bedbase configuration file contents - """ - return self._config - - @property - def bed(self) -> PipestatManager: - """ - PipestatManager of the bedfiles table - - :return pipestat.PipestatManager: manager of the bedfiles table - """ - return self.__pipestats[BED_TABLE] - - @property - def bedset(self) -> PipestatManager: - """ - PipestatManager of the bedsets table - - :return pipestat.PipestatManager: manager of the bedsets table - """ - return self.__pipestats[BEDSET_TABLE] - - def _check_table_exists(self, table_name: str) -> bool: - """ - Check if the specified table exists on the 'bed' pipestatmanager object - - :param str table_name: table name to be checked - :return bool: whether the specified table exists - """ - with self.bed.backend.session as s: - return inspect(s.bind).has_table(table_name=table_name) - - def _get_output_path( - self, table_name: str, remote_key: str, remote: bool = False - ) -> str: - """ - Get path to the output of the selected pipeline - - :param str table_name: name of the table that is populated by the - pipeline to return the output path for - :param str remote_key: - :param bool remote: whether to use remote url base - :return str: path to the selected pipeline output - """ - dir_key = ( - CFG_PATH_BEDBUNCHER_DIR_KEY - if table_name == BEDSET_TABLE - else CFG_PATH_BEDSTAT_DIR_KEY - ) - base = ( - self.config[CFG_REMOTE_KEY][remote_key]["prefix"] - if remote - else self.config[CFG_PATH_KEY][CFG_PATH_PIPELINE_OUTPUT_KEY] - ) - if remote and not base: - raise MissingConfigDataError( - f"{CFG_REMOTE_KEY} key value is invalid: {base}" - ) - return os.path.join(base, self.config[CFG_PATH_KEY][dir_key]) - - def get_bedbuncher_output_path(self, remote_key, remote=False) -> str: - """ - Get path to the output of the bedbuncher pipeline - - :param bool remote: whether to use remote url base - :return str: path to the bedbuncher pipeline output - """ - return self._get_output_path( - table_name=BEDSET_TABLE, remote_key=remote_key, remote=remote - ) - - def get_bedstat_output_path(self, remote_key, remote=False) -> str: - """ - Get path to the output of the bedstat pipeline - - :param bool remote: whether to use remote url base - :return str: path to the bedstat pipeline output - """ - return self._get_output_path( - table_name=BED_TABLE, remote_key=remote_key, remote=remote - ) - - def _create_bedset_bedfiles_table(self): - """ - Create a relationship table - """ - - class BedFileBedSetAssociation(SQLModel, table=True): - __tablename__ = BEDFILE_BEDSET_ASSOCIATION_TABLE_KEY - bedfile_id: Optional[int] = Field( - default=None, - foreign_key=f"{self.bed.cfg['pipeline_name']}__sample.id", - primary_key=True, - ) - bedset_id: Optional[int] = Field( - default=None, - foreign_key=f"{self.bedset.cfg['pipeline_name']}__sample.id", - primary_key=True, - ) - - __table_args__ = {"extend_existing": True} - - self.rel_table = BedFileBedSetAssociation - returned_model = BedFileBedSetAssociation.__table__ - - # this will create a relationship between bedfiles and bedsets, and will have mapping in both tables (bedfiles, bedsets) - self.BedfileORM.__mapper__.add_property( - BEDSETS_REL_KEY, - relationship( - self.BedsetORM, - secondary=returned_model, - backref=BEDFILES_REL_KEY, - ), - ) - - SQLModel.metadata.create_all(bind=self.bed.backend.db_engine_key) - - def report_relationship( - self, bedset_record_id: str, bedfile_record_id: str - ) -> None: - """ - Report a bedfile for bedset. - - Inserts the ID pair into the relationship table, which allows to - manage many to many bedfile bedset relationships - - :param int bedset_record_id: record identifier of the bedset to report bedfile for - :param int bedfile_record_id: record identifier of the bedfile to report - """ - - if not self._check_table_exists( - table_name=BEDFILE_BEDSET_ASSOCIATION_TABLE_KEY - ): - self._create_bedset_bedfiles_table() - - with self.bed.backend.session as s: - bedset_statement = select(self.BedsetORM).where( - self.BedsetORM.record_identifier == bedset_record_id - ) - bedset = s.exec(bedset_statement).one() - - bedfile_statement = select(self.BedfileORM).where( - self.BedfileORM.record_identifier == bedfile_record_id - ) - bedfile = s.exec(bedfile_statement).one() - - if not bedfile: - raise BedBaseConfError( - f"Bedfile with if: {bedfile_record_id} doesn't exists. Can't add bedfile to bedset" - ) - - # add relationship - bedset.bedfiles.append(bedfile) - s.add(bedfile) - s.commit() - - return None - - def remove_relationship( - self, bedset_record_id: str, bedfile_record_id: Union[str, List[str]] = None - ) -> None: - """ - Remove entries from the relationships table - - :param str bedset_record_id: id of the bedset to remove - :param list[str] bedfile_record_id: ids of the bedfiles to remove for the - selected bedset. If none provided, all the relationsips for the - selected bedset will be removed. - """ - - if not self._check_table_exists( - table_name=BEDFILE_BEDSET_ASSOCIATION_TABLE_KEY - ): - raise BedBaseConfError( - f"Can't remove a relationship, '{BEDFILE_BEDSET_ASSOCIATION_TABLE_KEY}' does not exist" - ) - - with self.bedset.backend.session as s: - bedset_statement = select(self.BedsetORM).where( - self.BedsetORM.record_identifier == bedset_record_id - ) - bedset = s.exec(bedset_statement).one() - - if bedfile_record_id is None: - list_of_bed = [bed for bed in bedset.bedfiles] - - for bed in list_of_bed: - bedset.bedfiles.remove(bed) - else: - if isinstance(bedfile_record_id, str): - bedfile_record_id = [bedset_record_id] - - for bedfile_id in bedfile_record_id: - bedfile_statement = select(self.BedfileORM).where( - self.BedfileORM.record_identifier == bedfile_id - ) - bedfile = s.exec(bedfile_statement).one() - - bedset.bedfiles.remove(bedfile) - s.add(bedset) - s.commit() - - def select_bedfiles_from_bedset( - self, - bedset_record_id: str, - metadata: bool = False, - ) -> List[dict]: - """ - Select bedfiles that are part of a bedset that matches the query - - :param: bedset_record_id: record identifier of the bedset to query - :param: metadata: whether to include metadata in the result - :return: matched bedfiles table contents - """ - if metadata: - with self.bed.backend.session as session: - statement = select(self.BedsetORM).where( - self.BedsetORM.record_identifier == bedset_record_id - ) - results = session.exec(statement).one().bedfiles - bedfile_list = [bedfile.model_dump() for bedfile in results] - else: - # Probably we can do it in more simple way - with self.bed.backend.session as session: - statement = select(self.BedfileORM.record_identifier).where( - self.BedfileORM.id.in_( - select(self.rel_table.bedfile_id).where( - self.rel_table.bedset_id - == select(self.BedsetORM.id) - .where(self.BedsetORM.record_identifier == bedset_record_id) - .scalar_subquery() - ) - ) - ) - bedfile_list = session.exec(statement).all() - bedfile_list = [ - {"record_identifier": bedset_id} for bedset_id in bedfile_list - ] - return bedfile_list - - def select_unique(self, table_name: str, column: str = None) -> List[dict]: - """ - Select unique value in given column and table - - :param str table_name: table to query in - :param str column: column to include in the result - :return list[dict]: unique entries in the column - """ - - if table_name == "bedfile__sample": - with self.bed.backend.session: - values = self.bed.backend.select_records(columns=column)["records"] - elif table_name == "bedsets__sample": - with self.bedset.backend.session: - values = self.bedset.backend.select_records(columns=column)["records"] - else: - raise SchemaError(f"Incorrect table name provided {table_name}") - - return [i for n, i in enumerate(values) if i not in values[n + 1 :]] - - @property - def BedfileORM(self) -> SQLModel: - """ - return: ORM of bedfile table (SQLModelMetaclass) - """ - return self.bed.backend.get_model("bedfile__sample") - - @property - def BedsetORM(self) -> SQLModel: - """ - return: ORM of bedset table (SQLModelMetaclass) - """ - return self.bedset.backend.get_model("bedsets__sample") - - @property - def t2bsi(self) -> text2bednn.Text2BEDSearchInterface: - """ - :return: object with search functions - """ - return self._t2bsi - - @property - def qdrant_backend(self) -> QdrantBackend: - return self._qdrant_backend - - def _init_qdrant_backend(self) -> QdrantBackend: - """ - Create qdrant client object using credentials provided in config file - :return: QdrantClient - """ - return QdrantBackend( - collection=self._config[CFG_QDRANT_KEY][CFG_QDRANT_COLLECTION_NAME_KEY], - qdrant_host=self._config[CFG_QDRANT_KEY][CFG_QDRANT_HOST_KEY], - qdrant_port=self._config[CFG_QDRANT_KEY][CFG_QDRANT_PORT_KEY], - qdrant_api_key=self._config[CFG_QDRANT_KEY][CFG_QDRANT_API_KEY], - ) - - def _create_t2bsi_object(self) -> Union[text2bednn.Text2BEDSearchInterface, None]: - """ - Create Text 2 BED search interface and return this object - :return: Text2BEDSearchInterface object - """ - - try: - return text2bednn.Text2BEDSearchInterface( - nl2vec_model=FlagEmbedding(model_name=self._senta2vec_hg_model_name), - vec2vec_model=self._config[CFG_PATH_KEY][CFG_PATH_VEC2VEC_KEY], - search_backend=self.qdrant_backend, - ) - except Exception as e: - _LOGGER.error("Error in creating Text2BEDSearchInterface object: " + str(e)) - return None - - def add_bed_to_qdrant( - self, - bed_id: str, - bed_file: Union[str, RegionSet], - payload: dict = None, - region_to_vec: Region2VecExModel = None, - ) -> None: - """ - Convert bed file to vector and add it to qdrant database - - :param bed_id: bed file id - :param bed_file: path to the bed file, or RegionSet object - :param payload: additional metadata to store alongside vectors - :param region_to_vec: initiated region to vector model. If None, new object will be created. - :return: None - """ - - _LOGGER.info(f"Adding bed file to qdrant. bed_id: {bed_id}") - # Convert bedfile to vector - if isinstance(bed_file, str): - bed_region_set = RegionSet(bed_file) - elif isinstance(bed_file, RegionSet): - bed_region_set = bed_file - else: - raise BedBaseConfError( - "Could not add add region to qdrant. Invalid type, or path. " - ) - if not region_to_vec or isinstance(self.region2vec_model, str): - reg_2_vec_obj = Region2VecExModel(self.region2vec_model) - else: - reg_2_vec_obj = region_to_vec - bed_embedding = np.mean(reg_2_vec_obj.encode(bed_region_set), axis=0) - - # Upload bed file vector to the database - vec_dim = bed_embedding.shape[0] - self.qdrant_backend.load( - ids=[bed_id], - vectors=bed_embedding.reshape(1, vec_dim), - payloads=[{**payload}], - ) - return None - - def get_prefixed_uri(self, postfix: str, access_id: str) -> str: - """ - Return uri with correct prefix (schema) - - :param postfix: postfix of the uri (or everything after uri schema) - :param access_id: access method name - :return: full uri path - """ - - try: - prefix = self.config[CFG_ACCESS_METHOD_KEY][access_id]["prefix"] - return os.path.join(prefix, postfix) - except KeyError: - _LOGGER.error(f"Access method {access_id} is not defined.") - raise BadAccessMethodError(f"Access method {access_id} is not defined.") - - def get_thumbnail_uri( - self, - record_type: Literal["bed", "bedset"], - record_id: str, - result_id: str, - access_id: str = "http", - ) -> str: - """ - Create URL to access a bed- or bedset-associated thumbnail - - :param record_type: table_name ["bed", "bedset"] - :param record_id: record identifier - :param result_id: column name (result name) - :param access_id: access id (e.g. http, s3, etc.) - :return: string with thumbnail - """ - - try: - result = self.get_result(record_type, record_id, result_id) - return self.get_prefixed_uri(result["thumbnail_path"], access_id) - except KeyError: - _LOGGER.error( - f"Thumbnail for {record_type} {record_id} {result_id} is not defined." - ) - raise MissingThumbnailError( - f"Thumbnail for {record_type} {record_id} {result_id} is not defined." - ) - - def get_object_uri( - self, - record_type: Literal["bed", "bedset"], - record_id: str, - result_id: str, - access_id: str, - ) -> str: - """ - Create URL to access a bed- or bedset-associated file - - :param record_type: table_name ["bed", "bedset"] - :param record_id: record identifier - :param result_id: column name (result name) - :param access_id: access id (e.g. http, s3, etc.) - :return: - """ - result = self.get_result(record_type, record_id, result_id) - return self.get_prefixed_uri(result["path"], access_id) - - def get_result( - self, - record_type: Literal["bed", "bedset"], - record_id: str, - result_id: Union[str, List[str]], - ) -> dict: - """ - Generic getter that can return a result from either bed or bedset - - :param record_type: table_name ["bed", "bedset"] - :param record_id: record identifier - :param result_id: column name (result name) - :return: pipestat result - """ - if record_type == "bed": - result = self.bed.retrieve_one(record_id, result_id) - elif record_type == "bedset": - result = self.bedset.retrieve_one(record_id, result_id) - else: - raise BedBaseConfError( - f"Record type {record_type} is not supported. Only bed and bedset are supported." - ) - - _LOGGER.info(f"Getting uri for {record_type} {record_id} {result_id}") - _LOGGER.info(f"Result: {result}") - return result - - # def get_drs_metadata( - # self, - # record_type: Literal["bed", "bedset"], - # record_id: str, - # result_id: str, - # base_uri: str, - # ) -> DRSModel: - # """ - # Get DRS metadata for a bed- or bedset-associated file - # - # :param record_type: bed or bedset - # :param record_id: record identifier - # :param result_id: name of the result file to get metadata for - # :param base_uri: base uri to use for the self_uri field (server hostname of DRS broker) - # :return: DRS metadata - # """ - # - # access_methods = [] - # object_id = f"{record_type}.{record_id}.{result_id}" - # result_ids = [result_id, "pipestat_created_time", "pipestat_modified_time"] - # record_metadata = self.get_result( - # record_type, record_id, result_ids - # ) # only get result once - # if not record_metadata: - # raise RecordNotFoundError("This record does not exist") - # - # if not record_metadata[result_id] or not record_metadata[result_id]["path"]: - # raise MissingObjectError("This object does not exist") - # - # path = record_metadata[result_id]["path"] - # for access_id in self.config[CFG_ACCESS_METHOD_KEY].keys(): - # access_dict = AccessMethod( - # type=access_id, - # access_id=access_id, - # access_url=AccessURL(url=self.get_prefixed_uri(path, access_id)), - # region=self.config[CFG_ACCESS_METHOD_KEY][access_id].get( - # "region", None - # ), - # ) - # access_methods.append(access_dict) - # drs_dict = DRSModel( - # id=object_id, - # self_uri=f"drs://{base_uri}/{object_id}", - # size=record_metadata[result_id].get("size", "unknown"), - # created_time=record_metadata.get("pipestat_created_time", "unknown"), - # updated_time=record_metadata.get("pipestat_modified_time", "unknown"), - # checksums=object_id, - # access_methods=access_methods, - # ) - # - # return drs_dict diff --git a/bbconf/config_parser/bedbaseconfig.py b/bbconf/config_parser/bedbaseconfig.py index 7c557458..c533cb56 100644 --- a/bbconf/config_parser/bedbaseconfig.py +++ b/bbconf/config_parser/bedbaseconfig.py @@ -10,13 +10,11 @@ from geniml.io import RegionSet from pephubclient import PEPHubClient -from bbconf import BedBaseConf import boto3 from bbconf.db_utils import BaseEngine -from bbconf.const_new import ( - CFG_PATH_KEY, +from bbconf.const import ( PKG_NAME, ) from bbconf.helpers import get_bedbase_cfg diff --git a/bbconf/config_parser/const.py b/bbconf/config_parser/const.py index d4a02324..b2d21e9e 100644 --- a/bbconf/config_parser/const.py +++ b/bbconf/config_parser/const.py @@ -1 +1,22 @@ -# TODO: add defaults here +DEFAULT_DB_NAME = "bedbase" +DEFAULT_DB_PORT = 5432 +DEFAULT_DB_DIALECT = "postgresql" +DEFAULT_DB_DRIVER = "psycopg" + +DEFAULT_QDRANT_HOST = "localhost" +DEFAULT_QDRANT_PORT = 6333 +DEFAULT_QDRANT_COLLECTION_NAME = "bedbase" +DEFAULT_QDRANT_API_KEY = None + +DEFAULT_SERVER_PORT = 80 +DEFAULT_SERVER_HOST = "0.0.0.0" + +DEFAULT_TEXT2VEC_MODEL = "sentence-transformers/all-MiniLM-L6-v2" +DEFAULT_VEC2VEC_MODEL = "databio/v2v-MiniLM-v2-ATAC-hg38" +DEFAULT_REGION2_VEC_MODEL = "databio/r2v-ChIP-atlas-hg38" + +DEFAULT_PEPHUB_NAMESPACE = "databio" +DEFAULT_PEPHUB_NAME = "allbeds" +DEFAULT_PEPHUB_TAG = "bedbase" + +DEFAULT_S3_BUCKET = "bedbase" diff --git a/bbconf/config_parser/models.py b/bbconf/config_parser/models.py index b1347d6b..dca6c4cc 100644 --- a/bbconf/config_parser/models.py +++ b/bbconf/config_parser/models.py @@ -1,33 +1,45 @@ from typing import Optional, List, Union from pydantic import BaseModel, ConfigDict -from bbconf.const_new import ( +from bbconf.config_parser.const import ( DEFAULT_VEC2VEC_MODEL, DEFAULT_TEXT2VEC_MODEL, DEFAULT_REGION2_VEC_MODEL, + DEFAULT_DB_DIALECT, + DEFAULT_DB_NAME, + DEFAULT_DB_DRIVER, + DEFAULT_QDRANT_COLLECTION_NAME, + DEFAULT_DB_PORT, + DEFAULT_QDRANT_PORT, + DEFAULT_SERVER_HOST, + DEFAULT_SERVER_PORT, + DEFAULT_PEPHUB_NAMESPACE, + DEFAULT_PEPHUB_NAME, + DEFAULT_PEPHUB_TAG, + DEFAULT_S3_BUCKET, ) class ConfigDB(BaseModel): host: str - port: int = 5432 + port: int = DEFAULT_DB_PORT user: str password: str - database: str = "bedbase" - dialect: str = "postgresql" - driver: Optional[str] = "psycopg" + database: str = DEFAULT_DB_NAME + dialect: str = DEFAULT_DB_DIALECT + driver: Optional[str] = DEFAULT_DB_DRIVER class ConfigQdrant(BaseModel): host: str - port: int = 6333 + port: int = DEFAULT_QDRANT_PORT api_key: Optional[str] = None - collection: str = "bedbase" + collection: str = DEFAULT_QDRANT_COLLECTION_NAME class ConfigServer(BaseModel): - host: str = "0.0.0.0" - port: int = 8000 + host: str = DEFAULT_SERVER_HOST + port: int = DEFAULT_SERVER_PORT class ConfigPath(BaseModel): @@ -52,18 +64,18 @@ class ConfigS3(BaseModel): endpoint_url: Union[str, None] = None aws_access_key_id: Union[str, None] = None aws_secret_access_key: Union[str, None] = None - bucket: Union[str, None] = "bedbase" + bucket: Union[str, None] = DEFAULT_S3_BUCKET class ConfigPepHubClient(BaseModel): - namespace: Union[str, None] = "databio" - name: Union[str, None] = "allbeds" - tag: Union[str, None] = "bedbase" + namespace: Union[str, None] = DEFAULT_PEPHUB_NAMESPACE + name: Union[str, None] = DEFAULT_PEPHUB_NAME + tag: Union[str, None] = DEFAULT_PEPHUB_TAG class ConfigFile(BaseModel): database: ConfigDB - qdrant: ConfigQdrant + qdrant: ConfigQdrant = None server: ConfigServer path: ConfigPath access_methods: AccessMethods = None diff --git a/bbconf/const.py b/bbconf/const.py index 68f5cbff..b41ddfb8 100644 --- a/bbconf/const.py +++ b/bbconf/const.py @@ -1,102 +1,4 @@ -""" -Constant variables shared among packages that constitute bedbase project -""" - -import os - -SCHEMA_DIRNAME = "schemas" -SCHEMAS_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), SCHEMA_DIRNAME) -BED_TABLE_SCHEMA = os.path.join(SCHEMAS_PATH, "bedfiles_schema.yaml") -BEDSET_TABLE_SCHEMA = os.path.join(SCHEMAS_PATH, "bedsets_schema.yaml") -DIST_TABLE_SCHEMA = os.path.join(SCHEMAS_PATH, "distance_schema.yaml") - PKG_NAME = "bbconf" -DOC_URL = "TBA" # TODO: add documentation URL once it's established - -BED_TABLE = "bedfile__sample" -BEDSET_TABLE = "bedsets__sample" - -BEDFILES_REL_KEY = "bedfiles" -BEDSETS_REL_KEY = "bedsets" - -BEDFILE_BEDSET_ASSOCIATION_TABLE_KEY = "bedset_bedfiles_new" - -CFG_ENV_VARS = ["BEDBASE"] - -PIPESTATS_KEY = "__pipestats" -COMMON_DECL_BASE_KEY = "__common_declarative_base" - -HIDDEN_ATTR_KEYS = [PIPESTATS_KEY, COMMON_DECL_BASE_KEY] - -# config file constants -CFG_PATH_KEY = "path" -CFG_PATH_BEDSTAT_DIR_KEY = "bedstat_dir" -CFG_PATH_BEDBUNCHER_DIR_KEY = "bedbuncher_dir" -CFG_PATH_PIPELINE_OUTPUT_KEY = "pipeline_output_path" -CFG_PATH_REGION2VEC_KEY = "region2vec" -CFG_PATH_VEC2VEC_KEY = "vec2vec" -CFG_PATH_TEXT2VEC_KEY = "text2vec" - - -CFG_DATABASE_KEY = "database" -CFG_DATABASE_NAME_KEY = "name" -CFG_DATABASE_HOST_KEY = "host" -CFG_DATABASE_PORT_KEY = "port" -CFG_DATABASE_PASSWORD_KEY = "password" -CFG_DATABASE_USER_KEY = "user" - -CFG_QDRANT_KEY = "qdrant" - -CFG_QDRANT_HOST_KEY = "host" -CFG_QDRANT_PORT_KEY = "port" -CFG_QDRANT_API_KEY = "api_key" -CFG_QDRANT_COLLECTION_NAME_KEY = "collection" - -CFG_SERVER_KEY = "server" -CFG_SERVER_HOST_KEY = "host" -CFG_SERVER_PORT_KEY = "port" - -CFG_REMOTE_KEY = "remotes" - -DB_DEFAULT_HOST = "localhost" -DB_DEFAULT_USER = "postgres" -DB_DEFAULT_PASSWORD = "bedbasepassword" -DB_DEFAULT_NAME = "postgres" -DB_DEFAULT_PORT = 5432 -DB_DEFAULT_DIALECT = "postgresql" - -CFG_ACCESS_METHOD_KEY = "access_methods" - -DEFAULT_QDRANT_HOST = "localhost" -DEFAULT_QDRANT_PORT = 6333 -DEFAULT_QDRANT_COLLECTION_NAME = "bedbase" -DEFAULT_QDRANT_API_KEY = None - -SERVER_DEFAULT_PORT = 80 -SERVER_DEFAULT_HOST = "0.0.0.0" - -DEFAULT_SECTION_VALUES = { - CFG_DATABASE_KEY: { - CFG_DATABASE_USER_KEY: DB_DEFAULT_USER, - CFG_DATABASE_PASSWORD_KEY: DB_DEFAULT_PASSWORD, - CFG_DATABASE_NAME_KEY: DB_DEFAULT_NAME, - CFG_DATABASE_PORT_KEY: DB_DEFAULT_PORT, - CFG_DATABASE_HOST_KEY: DB_DEFAULT_HOST, - }, - CFG_SERVER_KEY: { - CFG_SERVER_HOST_KEY: SERVER_DEFAULT_HOST, - CFG_SERVER_PORT_KEY: SERVER_DEFAULT_PORT, - }, - CFG_QDRANT_KEY: { - CFG_QDRANT_HOST_KEY: DEFAULT_QDRANT_HOST, - CFG_QDRANT_PORT_KEY: DEFAULT_QDRANT_PORT, - CFG_QDRANT_COLLECTION_NAME_KEY: DEFAULT_QDRANT_COLLECTION_NAME, - CFG_QDRANT_API_KEY: DEFAULT_QDRANT_API_KEY, - }, -} -DEFAULT_TEXT2VEC_MODEL = "sentence-transformers/all-MiniLM-L6-v2" -DEFAULT_VEC2VEC_MODEL = "databio/v2v-MiniLM-v2-ATAC-hg38" -DEFAULT_REGION2_VEC_MODEL = "databio/r2v-ChIP-atlas-hg38" DRS_ACCESS_URL = "{server_url}/objects/{object_id}/access/{access_id}" diff --git a/bbconf/const_new.py b/bbconf/const_new.py deleted file mode 100644 index b15acdac..00000000 --- a/bbconf/const_new.py +++ /dev/null @@ -1,70 +0,0 @@ -PKG_NAME = "bbconf" - - -# config file constants -CFG_PATH_KEY = "path" -CFG_PATH_REGION2VEC_KEY = "region2vec" -CFG_PATH_VEC2VEC_KEY = "vec2vec" -CFG_PATH_TEXT2VEC_KEY = "text2vec" - -CFG_DATABASE_KEY = "database" -CFG_DATABASE_NAME_KEY = "name" -CFG_DATABASE_HOST_KEY = "host" -CFG_DATABASE_PORT_KEY = "port" -CFG_DATABASE_PASSWORD_KEY = "password" -CFG_DATABASE_USER_KEY = "user" - -CFG_QDRANT_KEY = "qdrant" - -CFG_QDRANT_HOST_KEY = "host" -CFG_QDRANT_PORT_KEY = "port" -CFG_QDRANT_API_KEY = "api_key" -CFG_QDRANT_COLLECTION_NAME_KEY = "collection" - -CFG_SERVER_KEY = "server" -CFG_SERVER_HOST_KEY = "host" -CFG_SERVER_PORT_KEY = "port" - -CFG_REMOTE_KEY = "remotes" - -DB_DEFAULT_HOST = "localhost" -DB_DEFAULT_USER = "postgres" -DB_DEFAULT_PASSWORD = "bedbasepassword" -DB_DEFAULT_NAME = "postgres" -DB_DEFAULT_PORT = 5432 -DB_DEFAULT_DIALECT = "postgresql" - -CFG_ACCESS_METHOD_KEY = "access_methods" - -DEFAULT_QDRANT_HOST = "localhost" -DEFAULT_QDRANT_PORT = 6333 -DEFAULT_QDRANT_COLLECTION_NAME = "bedbase" -DEFAULT_QDRANT_API_KEY = None - -SERVER_DEFAULT_PORT = 80 -SERVER_DEFAULT_HOST = "0.0.0.0" - -DEFAULT_SECTION_VALUES = { - CFG_DATABASE_KEY: { - CFG_DATABASE_USER_KEY: DB_DEFAULT_USER, - CFG_DATABASE_PASSWORD_KEY: DB_DEFAULT_PASSWORD, - CFG_DATABASE_NAME_KEY: DB_DEFAULT_NAME, - CFG_DATABASE_PORT_KEY: DB_DEFAULT_PORT, - CFG_DATABASE_HOST_KEY: DB_DEFAULT_HOST, - }, - CFG_SERVER_KEY: { - CFG_SERVER_HOST_KEY: SERVER_DEFAULT_HOST, - CFG_SERVER_PORT_KEY: SERVER_DEFAULT_PORT, - }, - CFG_QDRANT_KEY: { - CFG_QDRANT_HOST_KEY: DEFAULT_QDRANT_HOST, - CFG_QDRANT_PORT_KEY: DEFAULT_QDRANT_PORT, - CFG_QDRANT_COLLECTION_NAME_KEY: DEFAULT_QDRANT_COLLECTION_NAME, - CFG_QDRANT_API_KEY: DEFAULT_QDRANT_API_KEY, - }, -} - - -DEFAULT_TEXT2VEC_MODEL = "sentence-transformers/all-MiniLM-L6-v2" -DEFAULT_VEC2VEC_MODEL = "databio/v2v-MiniLM-v2-ATAC-hg38" -DEFAULT_REGION2_VEC_MODEL = "databio/r2v-ChIP-atlas-hg38" diff --git a/bbconf/exceptions.py b/bbconf/exceptions.py index c9a910ce..a4a456c7 100644 --- a/bbconf/exceptions.py +++ b/bbconf/exceptions.py @@ -1,5 +1,4 @@ import abc -from .const import DOC_URL class BedBaseConfError(Exception): @@ -14,15 +13,6 @@ class BadAccessMethodError(BedBaseConfError): pass -class MissingConfigDataError(BedBaseConfError): - """Exception for invalid config file.""" - - def __init__(self, msg): - spacing = " " if msg[-1] in ["?", ".", "\n"] else "; " - suggest = "For config format documentation please see: " + DOC_URL - super(MissingConfigDataError, self).__init__(msg + spacing + suggest) - - class BedBaseConnectionError(BedBaseConfError): """Error type for DB connection problems""" diff --git a/bbconf/helpers.py b/bbconf/helpers.py index 09ed54bf..77a83e5e 100644 --- a/bbconf/helpers.py +++ b/bbconf/helpers.py @@ -1,14 +1,15 @@ import logging - +from typing import NoReturn from yacman import select_config -from .const import CFG_ENV_VARS -from .exceptions import MissingConfigDataError, BedBaseConnectionError -from typing import NoReturn +from bbconf.exceptions import BedBaseConnectionError _LOGGER = logging.getLogger(__name__) +CFG_ENV_VARS = ["BEDBASE"] + + def get_bedbase_cfg(cfg: str = None) -> str: """ Determine path to the bedbase configuration file @@ -27,11 +28,3 @@ def get_bedbase_cfg(cfg: str = None) -> str: f"{'or '.join(CFG_ENV_VARS)} environment variable" ) return selected_cfg - - -def raise_missing_key(key: str) -> NoReturn: - """ - Raise missing key with message - """ - - raise MissingConfigDataError(f"BedBaseConfig lacks '{key}' key") diff --git a/bbconf/model_parser.py b/bbconf/model_parser.py deleted file mode 100644 index 3cb69ba6..00000000 --- a/bbconf/model_parser.py +++ /dev/null @@ -1,125 +0,0 @@ -from pydantic import create_model, Field, ConfigDict -import logging -from typing import Union, Tuple, Dict, Any, List -from pathlib import Path -import os -from ubiquerg import expandpath -from oyaml import safe_load -import datetime - - -# TODO: This should be moved to pipestat or bedhost - -_LOGGER = logging.getLogger("bedhost") - -CLASSES_BY_TYPE = { - "object": dict, - "number": float, - "integer": int, - "string": str, - "path": Path, - "boolean": bool, - "file": str, - "image": str, - "link": str, - "array": List[Dict], -} - - -def _get_data_type(type_name): - t = CLASSES_BY_TYPE[type_name] - return t - - -def _add_dates_to_schema(schema: dict) -> dict: - """ - Add date fields to the schema - - :param schema: schema dictionary - :return: schema dictionary with date fields - """ - - schema["pipestat_created_time"] = ( - Union[datetime.datetime, str, None], - Field( - default=None, - nullable=True, - ), - ) - schema["pipestat_modified_time"] = ( - Union[datetime.datetime, str, None], - Field( - default=None, - nullable=True, - ), - ) - return schema - - -def read_yaml_data(path: Union[str, Path], what: str) -> Tuple[str, Dict[str, Any]]: - """ - Safely read YAML file and log message - - :param str path: YAML file to read - :param str what: context - :return (str, dict): absolute path to the read file and the read data - """ - if isinstance(path, Path): - test = lambda p: p.is_file() - elif isinstance(path, str): - path = expandpath(path) - test = os.path.isfile - else: - raise TypeError( - f"Alleged path to YAML file to read is neither path nor string: {path}" - ) - assert test(path), FileNotFoundError(f"File not found: {path}") - _LOGGER.debug(f"Reading {what} from '{path}'") - with open(path, "r") as f: - return path, safe_load(f) - - -def get_fields_dict(schema: dict) -> Dict[str, Field]: - """ - Get the field dictionary from the schema - - :param schema: schema dictionary - - :return: field dictionary - """ - defs = {} - samples = schema["properties"].get("samples") - for name, value in samples["properties"].items(): - - defs[name] = ( - Union[_get_data_type(value["type"]), None], - Field( - default=value.get("default"), - nullable=True, - description=value.get("description"), - ), - ) - return defs - - -def yaml_to_pydantic(name: str, data: Union[str, dict]): - """ - Convert yaml to pydantic model - - :param data: path to yaml file - :param name: name of the model - - :return: pydantic model - """ - if not isinstance(data, dict): - _, data = read_yaml_data(data, "schema") - from pipestat.parsed_schema import replace_JSON_refs - - data = replace_JSON_refs(data, data) - fields_dict = get_fields_dict(data) - - # This step is necessary because the pipestat schema does not include the dates and adds additional fields - fields_dict = _add_dates_to_schema(fields_dict) - config = ConfigDict(extra="ignore") - - return create_model(name, __config__=config, **fields_dict) diff --git a/bbconf/models/bed_models.py b/bbconf/models/bed_models.py index 6ca3b61d..9d1e6df7 100644 --- a/bbconf/models/bed_models.py +++ b/bbconf/models/bed_models.py @@ -12,6 +12,7 @@ # # model_config = ConfigDict(populate_by_name=True) + class FileModel(BaseModel): name: str = Field(alias="title") path: str @@ -114,4 +115,3 @@ class BedMetadata(BaseModel): plots: BedPlots = None files: BedFiles = None raw_metadata: Optional[BedPEPHub] = None - diff --git a/bbconf/models/drs_models.py b/bbconf/models/drs_models.py index 5b38a152..d496184c 100644 --- a/bbconf/models/drs_models.py +++ b/bbconf/models/drs_models.py @@ -26,4 +26,3 @@ class DRSModel(BaseModel): checksums: str access_methods: List[AccessMethod] description: Optional[str] = None - diff --git a/bbconf/models_old.py b/bbconf/models_old.py deleted file mode 100644 index e449b338..00000000 --- a/bbconf/models_old.py +++ /dev/null @@ -1,53 +0,0 @@ -import datetime -from typing import Optional, List, Union -import os -import pathlib - -from pydantic import BaseModel, ConfigDict - -from bbconf.model_parser import yaml_to_pydantic - -from bbconf.const_new import ( - DEFAULT_VEC2VEC_MODEL, - DEFAULT_TEXT2VEC_MODEL, - DEFAULT_REGION2_VEC_MODEL, -) - - -# DRS Models -class AccessURL(BaseModel): - url: str - headers: Optional[dict] = None - - -class AccessMethod(BaseModel): - type: str - access_url: Optional[AccessURL] = None - access_id: Optional[str] = None - region: Optional[str] = None - - -class DRSModel(BaseModel): - id: str - name: Optional[str] = None - self_uri: str - size: str - created_time: Optional[datetime.datetime] = None - updated_time: Optional[datetime.datetime] = None - checksums: str - access_methods: List[AccessMethod] - description: Optional[str] = None - - -BedFileTableModel = yaml_to_pydantic( - "BedFile", - os.path.join( - pathlib.Path(__file__).parent.resolve(), "schemas", "bedfiles_schema.yaml" - ), -) -BedSetTableModel = yaml_to_pydantic( - "BedSet", - os.path.join( - pathlib.Path(__file__).parent.resolve(), "schemas", "bedsets_schema.yaml" - ), -) diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index 84c685de..e4277171 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -72,23 +72,33 @@ def get(self, identifier: str) -> BedMetadata: for result in bed_object.files: # PLOTS if result.name in BedPlots.model_fields: - setattr(bed_plots, result.name, FileModel( - name=result.name, - path=result.path, - size=result.size, - path_thumbnail=result.path_thumbnail, - description=result.description - )) + setattr( + bed_plots, + result.name, + FileModel( + name=result.name, + path=result.path, + size=result.size, + path_thumbnail=result.path_thumbnail, + description=result.description, + ), + ) # FILES elif result.name in BedFiles.model_fields: - setattr(bed_files, result.name, FileModel( - name=result.name, - path=result.path, - size=result.size, - description=result.description - )) + setattr( + bed_files, + result.name, + FileModel( + name=result.name, + path=result.path, + size=result.size, + description=result.description, + ), + ) else: - _LOGGER.error(f"Unknown file type: {result.name}. And is not in the model fields. Skipping..") + _LOGGER.error( + f"Unknown file type: {result.name}. And is not in the model fields. Skipping.." + ) bed_stats = BedStats(**bed_object.__dict__) bed_classification = BedClassification(**bed_object.__dict__) @@ -147,12 +157,16 @@ def get_plots(self, identifier: str) -> BedPlots: bed_plots = BedPlots() for result in bed_object.files: if result.name in BedPlots.model_fields: - setattr(bed_plots, result.name, FileModel( - name=result.name, - path=result.path, - path_thumbnail=result.path_thumbnail, - description=result.description - )) + setattr( + bed_plots, + result.name, + FileModel( + name=result.name, + path=result.path, + path_thumbnail=result.path_thumbnail, + description=result.description, + ), + ) return bed_plots def get_files(self, identifier: str) -> BedFiles: @@ -169,11 +183,15 @@ def get_files(self, identifier: str) -> BedFiles: bed_files = BedFiles() for result in bed_object.files: if result.name in BedFiles.model_fields: - setattr(bed_files, result.name, FileModel( - name=result.name, - path=result.path, - description=result.description - )) + setattr( + bed_files, + result.name, + FileModel( + name=result.name, + path=result.path, + description=result.description, + ), + ) return bed_files def get_raw_metadata(self, identifier: str) -> BedPEPHub: @@ -227,7 +245,6 @@ def get_objects(self, identifier: str) -> Dict[str, FileModel]: return return_dict - def add( self, identifier: str, @@ -260,7 +277,6 @@ def add( """ _LOGGER.info(f"Adding bed file to database. bed_id: {identifier}") - stats = BedStats(**stats) # TODO: we should not check for specific keys, of the plots! plots = BedPlots(**plots) @@ -315,7 +331,7 @@ def add( path_thumbnail=v.path_thumbnail, description=v.description, bedfile_id=identifier, - type="plot" + type="plot", ) session.add(new_plot) diff --git a/bbconf/modules/objects.py b/bbconf/modules/objects.py index f45bfc3c..8d36c1d1 100644 --- a/bbconf/modules/objects.py +++ b/bbconf/modules/objects.py @@ -24,7 +24,7 @@ class BBObjects: def __init__(self, config: BedBaseConfig): """ - :param db_engine: pepdbengine object with sa engine + :param config: config object """ self.config = config self.bed = BedAgentBedFile(self.config) @@ -46,11 +46,11 @@ def _get_prefixed_uri(self, postfix: str, access_id: str) -> str: raise BadAccessMethodError(f"Access method {access_id} is not defined.") def get_thumbnail_uri( - self, - record_type: Literal["bed", "bedset"], - record_id: str, - result_id: str, - access_id: str = "http", + self, + record_type: Literal["bed", "bedset"], + record_id: str, + result_id: str, + access_id: str = "http", ) -> str: """ Create URL to access a bed- or bedset-associated thumbnail @@ -74,11 +74,11 @@ def get_thumbnail_uri( ) def get_object_uri( - self, - record_type: Literal["bed", "bedset"], - record_id: str, - result_id: str, - access_id: str, + self, + record_type: Literal["bed", "bedset"], + record_id: str, + result_id: str, + access_id: str, ) -> str: """ Create URL to access a bed- or bedset-associated file @@ -93,10 +93,10 @@ def get_object_uri( return self._get_prefixed_uri(result.path, access_id) def _get_result( - self, - record_type: Literal["bed", "bedset"], - record_id: str, - result_id: Union[str, List[str]], + self, + record_type: Literal["bed", "bedset"], + record_id: str, + result_id: Union[str, List[str]], ) -> FileModel: """ Generic getter that can return a result from either bed or bedset @@ -111,7 +111,7 @@ def _get_result( elif record_type == "bedset": # result = self.bedset.retrieve_one(record_id, result_id) _LOGGER.error("Not implemented") - return {} + raise BedBaseConfError("ERROR NOT IMPLEMENTED YET") else: raise BedBaseConfError( @@ -123,11 +123,11 @@ def _get_result( return result def get_drs_metadata( - self, - record_type: Literal["bed", "bedset"], - record_id: str, - result_id: str, - base_uri: str, + self, + record_type: Literal["bed", "bedset"], + record_id: str, + result_id: str, + base_uri: str, ) -> DRSModel: """ Get DRS metadata for a bed- or bedset-associated file @@ -144,7 +144,9 @@ def get_drs_metadata( bed_result = self.bed.get(record_id) created_time = bed_result.submission_date modified_time = bed_result.last_update_date - record_metadata = self._get_result(record_type, record_id, result_id) # only get result once + record_metadata = self._get_result( + record_type, record_id, result_id + ) # only get result once if not record_metadata: raise BedBaseConfError(f"Record not found") @@ -152,7 +154,9 @@ def get_drs_metadata( access_dict = AccessMethod( type=access_id, access_id=access_id, - access_url=AccessURL(url=self._get_prefixed_uri(record_metadata.path, access_id)), + access_url=AccessURL( + url=self._get_prefixed_uri(record_metadata.path, access_id) + ), region=self.config.config.access_methods.model_dump()[access_id].get( "region", None ), @@ -168,4 +172,4 @@ def get_drs_metadata( access_methods=access_methods, ) - return drs_dict \ No newline at end of file + return drs_dict diff --git a/bbconf/schemas/bedfiles_schema.yaml b/bbconf/schemas/bedfiles_schema.yaml deleted file mode 100644 index 2b9f4563..00000000 --- a/bbconf/schemas/bedfiles_schema.yaml +++ /dev/null @@ -1,149 +0,0 @@ -title: BED files schema -description: An output schema for bedfile results. -type: object -properties: - pipeline_name: bedfile - samples: - type: object - properties: - name: - type: string - description: BED file name - genome: - type: object - description: genome assembly of the BED files - bed_type: - type: string - description: type of BED file, eg. "bed3", "bed6+4" - bed_format: - type: string - description: format type of BED file, narrowpeak, broadpeak, or bed - bedfile: - $ref: "#/$defs/file" - label: bedfile - description: BED file - bigbedfile: - $ref: "#/$defs/file" - label: bigBed - description: bigBed file - regions_no: - type: integer - description: Number of regions - gc_content: - type: number - description: GC content - median_tss_dist: - type: number - description: Median TSS distance - mean_region_width: - type: number - description: Mean region width - exon_frequency: - type: number - description: Exon frequency - intron_frequency: - type: number - description: Intron frequency - promoterprox_frequency: - type: number - description: Promoter frequency - intergenic_frequency: - type: number - description: Intergenic frequency - promotercore_frequency: - type: number - description: Promoter core frequency - fiveutr_frequency: - type: number - description: 5' UTR frequency - threeutr_frequency: - type: number - description: 3' UTR frequency - fiveutr_percentage: - type: number - description: 5' UTR percentage - threeutr_percentage: - type: number - description: 3' UTR percentage - promoterprox_percentage: - type: number - description: Promoter proc percentage - exon_percentage: - type: number - description: Exon percentage - intron_percentage: - type: number - description: Intron percentage - intergenic_percentage: - type: number - description: Intergenic percentage - promotercore_percentage: - type: number - description: Promoter core percentage - tssdist: - $ref: "#/$defs/image" - label: TSS_distance - description: Region-TSS distance plot - chrombins: - $ref: "#/$defs/image" - label: Chromosome_bins - description: Regions distribution over chromosomes plot - gccontent: - $ref: "#/$defs/image" - label: GC_content - description: GC content plot - partitions: - $ref: "#/$defs/image" - label: Regions_dist_partitions - description: Regions distribution over genomic partitions plot - expected_partitions: - $ref: "#/$defs/image" - label: Expected_partitions - description: Expected distribution over genomic partitions plot - cumulative_partitions: - $ref: "#/$defs/image" - label: Cumulative_partitions - description: Cumulative distribution over genomic partitions plot - widths_histogram: - $ref: "#/$defs/image" - label: Widths_histogram - description: Quantile-trimmed histogram of widths - neighbor_distances: - $ref: "#/$defs/image" - label: Neighbor_distance - description: Distance between neighbor regions - open_chromatin: - $ref: "#/$defs/image" - label: Open_chromatin - description: Cell specific enrichment for open chromatin plot - upload_status: - type: object - description: "Status of the upload to the databases: Dict[s3, qdrant, pephub]" - - -$defs: - image: - type: object - object_type: image - properties: - path: - type: string - thumbnail_path: - type: string - title: - type: string - required: - - path - - thumbnail_path - - title - file: - type: object - object_type: file - properties: - path: - type: string - title: - type: string - required: - - path - - title \ No newline at end of file diff --git a/bbconf/schemas/bedsets_schema.yaml b/bbconf/schemas/bedsets_schema.yaml deleted file mode 100644 index e492a0e7..00000000 --- a/bbconf/schemas/bedsets_schema.yaml +++ /dev/null @@ -1,54 +0,0 @@ -title: bedset_output_schema -description: An output schema for bedset results. -type: object -properties: - pipeline_name: bedsets - samples: - type: object - properties: - name: - type: string - description: BED set name - description: - type: string - description: description of the BED set - md5sum: - type: string - description: digest of the BED set - genome: - type: object - description: genome assembly of the BED sets - bedset_means: - type: object - description: Mean statistics of the BED files in this BED set - bedset_standard_deviation: - type: object - description: Standard deviations of statistics of the BED files in this BED set - region_commonality: - $ref: "#/$defs/image" - label: Region_commonality - description: Region commonality plot - processed: - type: boolean - label: BED_set_status - description: whether the BED set stats/plot are completed - pephub_path: - type: string - description: PEPhub registry path - - -$defs: - image: - type: object - object_type: image - properties: - path: - type: string - thumbnail_path: - type: string - title: - type: string - required: - - path - - thumbnail_path - - title \ No newline at end of file diff --git a/tests/test_bbagent.py b/tests/test_bbagent.py index 704582f4..7993a568 100644 --- a/tests/test_bbagent.py +++ b/tests/test_bbagent.py @@ -32,9 +32,7 @@ class Test_BedFile_Agent: def test_upload(self): agent = BedBaseAgent(config=config) - agent.bed.add( - - ) + agent.bed.add() def test_get_all(self): agent = BedBaseAgent(config=config) @@ -86,25 +84,33 @@ def test_bed_update(self): pass -class TestObjects(): +class TestObjects: def test_object_path(self): agent = BedBaseAgent(config=config) - ff = agent.objects.get_object_uri("bed", "91b2754c8ff01769bacfc80e6923c46e", "bed_file", "http") + ff = agent.objects.get_object_uri( + "bed", "91b2754c8ff01769bacfc80e6923c46e", "bed_file", "http" + ) ff def test_object_path_thumbnail_error(self): agent = BedBaseAgent(config=config) # TODO: it should raise issue: - ff = agent.objects.get_thumbnail_uri("bed", "91b2754c8ff01769bacfc80e6923c46e", "bed_file", "http") + ff = agent.objects.get_thumbnail_uri( + "bed", "91b2754c8ff01769bacfc80e6923c46e", "bed_file", "http" + ) ff def test_object_path_thumbnail(self): agent = BedBaseAgent(config=config) # TODO: it should raise issue: - ff = agent.objects.get_thumbnail_uri("bed", "91b2754c8ff01769bacfc80e6923c46e", "widths_histogram", "http") + ff = agent.objects.get_thumbnail_uri( + "bed", "91b2754c8ff01769bacfc80e6923c46e", "widths_histogram", "http" + ) ff def test_object_metadata(self): agent = BedBaseAgent(config=config) - ff = agent.objects.get_drs_metadata("bed", "91b2754c8ff01769bacfc80e6923c46e", "widths_histogram", "localhost") + ff = agent.objects.get_drs_metadata( + "bed", "91b2754c8ff01769bacfc80e6923c46e", "widths_histogram", "localhost" + ) ff From 3091721ef307edcf21bf6c7e2f8a37e9ebd218ab Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Wed, 20 Mar 2024 21:02:11 +0100 Subject: [PATCH 10/61] added and fixed qdrant --- bbconf/config_parser/__init__.py | 3 + bbconf/config_parser/bedbaseconfig.py | 16 +++ bbconf/db_utils.py | 18 ++-- bbconf/exceptions.py | 6 ++ bbconf/models/bed_models.py | 34 +++++-- bbconf/modules/bedfiles.py | 141 ++++++++++++++++++++++---- bbconf/modules/bedsets.py | 104 +++++++++++++++++-- tests/test_bbagent.py | 24 +++++ 8 files changed, 298 insertions(+), 48 deletions(-) diff --git a/bbconf/config_parser/__init__.py b/bbconf/config_parser/__init__.py index e69de29b..3d089de4 100644 --- a/bbconf/config_parser/__init__.py +++ b/bbconf/config_parser/__init__.py @@ -0,0 +1,3 @@ +from .bedbaseconfig import BedBaseConfig + +__all__ = ["BedBaseConfig"] diff --git a/bbconf/config_parser/bedbaseconfig.py b/bbconf/config_parser/bedbaseconfig.py index c533cb56..54c64473 100644 --- a/bbconf/config_parser/bedbaseconfig.py +++ b/bbconf/config_parser/bedbaseconfig.py @@ -32,6 +32,7 @@ def __init__(self, config: Union[Path, str]): self._db_engine = self._init_db_engine() self._qdrant_engine = self._init_qdrant_backend() self._t2bsi = self._init_t2bsi_object() + self._r2v = self._init_r2v_object() self._phc = self._init_pephubclient() self._boto3_client = self._init_boto3_client() @@ -86,6 +87,15 @@ def t2bsi(self) -> Union[text2bednn.Text2BEDSearchInterface, None]: """ return self._t2bsi + @property + def r2v(self) -> Region2VecExModel: + """ + Get region2vec object + + :return: region2vec object + """ + return self._r2v + @property def qdrant_engine(self) -> QdrantBackend: """ @@ -189,3 +199,9 @@ def _init_boto3_client( except Exception as e: _LOGGER.error(f"Error in creating boto3 client object: {e}") return None + + def _init_r2v_object(self) -> Region2VecExModel: + """ + Create Region2VecExModel object using credentials provided in config file + """ + return Region2VecExModel(self.config.path.region2vec) diff --git a/bbconf/db_utils.py b/bbconf/db_utils.py index 398d7631..50c5568c 100644 --- a/bbconf/db_utils.py +++ b/bbconf/db_utils.py @@ -79,9 +79,7 @@ class Bed(Base): __tablename__ = "bed" - id: Mapped[str] = mapped_column( - primary_key=True, - ) + id: Mapped[str] = mapped_column(primary_key=True, index=True) name: Mapped[Optional[str]] genome_alias: Mapped[Optional[str]] genome_digest: Mapped[Optional[str]] @@ -136,7 +134,7 @@ class Bed(Base): class Files(Base): __tablename__ = "files" - id: Mapped[int] = mapped_column(primary_key=True) + id: Mapped[int] = mapped_column(primary_key=True, index=True) name: Mapped[str] = mapped_column( nullable=False, comment="Name of the file, e.g. bed, bigBed" ) @@ -148,10 +146,14 @@ class Files(Base): nullable=True, comment="Thumbnail path of the file" ) description: Mapped[Optional[str]] - size: Mapped[Optional[str]] = mapped_column(comment="Size of the file") + size: Mapped[Optional[int]] = mapped_column(default=0, comment="Size of the file") - bedfile_id: Mapped[int] = mapped_column(ForeignKey("bed.id"), nullable=True) - bedset_id: Mapped[int] = mapped_column(ForeignKey("bedsets.id"), nullable=True) + bedfile_id: Mapped[int] = mapped_column( + ForeignKey("bed.id"), nullable=True, index=True + ) + bedset_id: Mapped[int] = mapped_column( + ForeignKey("bedsets.id"), nullable=True, index=True + ) bedfile: Mapped["Bed"] = relationship("Bed", back_populates="files") bedset: Mapped["BedSets"] = relationship("BedSets", back_populates="files") @@ -189,7 +191,7 @@ class BedFileBedSetRelation(Base): class BedSets(Base): __tablename__ = "bedsets" - id: Mapped[str] = mapped_column(primary_key=True) + id: Mapped[str] = mapped_column(primary_key=True, index=True) name: Mapped[str] = mapped_column(nullable=False, comment="Name of the bedset") description: Mapped[Optional[str]] = mapped_column( comment="Description of the bedset" diff --git a/bbconf/exceptions.py b/bbconf/exceptions.py index a4a456c7..efe390a1 100644 --- a/bbconf/exceptions.py +++ b/bbconf/exceptions.py @@ -29,3 +29,9 @@ class MissingObjectError(BedBaseConfError): """Error type for missing object""" pass + + +class BEDFileNotFoundError(BedBaseConfError): + """Error type for missing object""" + + pass diff --git a/bbconf/models/bed_models.py b/bbconf/models/bed_models.py index 9d1e6df7..113554ae 100644 --- a/bbconf/models/bed_models.py +++ b/bbconf/models/bed_models.py @@ -1,24 +1,15 @@ import datetime -from typing import Optional, Union +from typing import Optional, Union, List from pydantic import BaseModel, ConfigDict, Field -# class PlotModel(BaseModel): -# name: str = Field(alias="title") -# path: str -# path_thumbnail: Optional[Union[str, None]] = Field(None, alias="thumbnail_path") -# description: Optional[Union[str, None]] = None -# -# model_config = ConfigDict(populate_by_name=True) - - class FileModel(BaseModel): name: str = Field(alias="title") path: str path_thumbnail: Optional[Union[str, None]] = Field(None, alias="thumbnail_path") description: Optional[str] = None - size: Optional[str] = None + size: Optional[int] = None model_config = ConfigDict(populate_by_name=True) @@ -115,3 +106,24 @@ class BedMetadata(BaseModel): plots: BedPlots = None files: BedFiles = None raw_metadata: Optional[BedPEPHub] = None + + +class BedListResult(BaseModel): + count: int + limit: int + offset: int + results: List[str] + + +class QdrantSearchResult(BaseModel): + id: str + payload: dict + score: float + metadata: Union[BedMetadata, None] = None + + +class BedListSearchResult(BaseModel): + count: int + limit: int + offset: int + results: List[QdrantSearchResult] = None diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index e4277171..a70f3cf7 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -5,6 +5,9 @@ from geniml.region2vec import Region2VecExModel from geniml.io import RegionSet +from geniml.bbclient import BBClient + +from qdrant_client.models import PointIdsList, VectorParams, Distance from sqlalchemy.orm import Session from sqlalchemy import select, and_, or_ @@ -22,11 +25,15 @@ BedClassification, BedStats, BedPEPHub, + BedListResult, + BedListSearchResult, + QdrantSearchResult, ) from bbconf.exceptions import ( BedBaseConfError, + BEDFileNotFoundError, ) -from bbconf.db_utils import BaseEngine, Bed, Files +from bbconf.db_utils import Bed, Files from bbconf.config_parser.bedbaseconfig import BedBaseConfig _LOGGER = getLogger(PKG_NAME) @@ -35,6 +42,7 @@ BIGBED_PATH_FOLDER = "bigbed_files" BED_PATH_FOLDER = "bed_files" PLOTS_PATH_FOLDER = "stats" +QDRANT_GENOME = "hg38" class BedAgentBedFile: @@ -68,7 +76,8 @@ def get(self, identifier: str) -> BedMetadata: with Session(self._sa_engine) as session: bed_object = session.scalar(statement) - + if not bed_object: + raise BEDFileNotFoundError(f"Bed file with id: {identifier} not found.") for result in bed_object.files: # PLOTS if result.name in BedPlots.model_fields: @@ -245,6 +254,28 @@ def get_objects(self, identifier: str) -> Dict[str, FileModel]: return return_dict + def get_ids_list(self, limit: int = 100, offset: int = 0) -> BedListResult: + """ + Get list of bed file identifiers. + + :param limit: number of results to return + :param offset: offset to start from + :return: list of bed file identifiers + """ + # TODO: add filter (e.g. bed_type, genome...), search by description + # TODO: question: Return Annotation? + statement = select(Bed.id).limit(limit).offset(offset) + + with Session(self._sa_engine) as session: + bed_ids = session.execute(statement).all() + + return BedListResult( + count=len(bed_ids), + limit=limit, + offset=offset, + results=[result[0] for result in bed_ids], + ) + def add( self, identifier: str, @@ -290,7 +321,9 @@ def add( _LOGGER.info("upload_pephub set to false. Skipping pephub..") if add_to_qdrant: - self.upload_qdrant(identifier, files.bed_file.path, metadata.model_dump()) + self.upload_file_qdrant( + identifier, files.bed_file.path, {"bed_id": identifier} + ) else: _LOGGER.info("add_to_qdrant set to false. Skipping qdrant..") @@ -332,6 +365,7 @@ def add( description=v.description, bedfile_id=identifier, type="plot", + size=v.size, ) session.add(new_plot) @@ -346,7 +380,7 @@ def delete(self, identifier: str) -> None: :param identifier: bed file identifier :return: None """ - ... + raise NotImplemented def upload_files_s3(self, files: BedFiles) -> BedFiles: """ @@ -369,20 +403,22 @@ def upload_files_s3(self, files: BedFiles) -> BedFiles: self._upload_s3(bed_file_path, bed_s3_path) files.bed_file.path = bed_s3_path + files.bed_file.size = os.path.getsize(bed_file_path) if files.bigbed_file: file_base_name = os.path.basename(files.bigbed_file.path) - bed_file = files.bigbed_file.path + bigbed_file_local = files.bigbed_file.path bigbed_s3_path = os.path.join( BIGBED_PATH_FOLDER, file_base_name[0], file_base_name[1], - os.path.basename(bed_file), + os.path.basename(bigbed_file_local), ) - self._upload_s3(bed_file, bigbed_s3_path) + self._upload_s3(bigbed_file_local, bigbed_s3_path) files.bigbed_file.path = bigbed_s3_path + files.bigbed_file.size = os.path.getsize(bigbed_file_local) return files @@ -412,6 +448,7 @@ def upload_plots_s3( self._upload_s3(local_path, file_s3_path) else: file_s3_path = None + local_path = None if value.path_thumbnail: file_s3_path_thumbnail = os.path.join( output_folder, os.path.basename(value.path_thumbnail) @@ -431,6 +468,7 @@ def upload_plots_s3( path=file_s3_path, path_thumbnail=file_s3_path_thumbnail, description=value.description, + size=os.path.getsize(local_path) if local_path else None, ), ) @@ -461,16 +499,17 @@ def upload_pephub(self, identifier: str, metadata: dict, overwrite: bool = False overwrite=overwrite, ) - def upload_qdrant( + def upload_file_qdrant( self, bed_id: str, bed_file: Union[str, RegionSet], payload: dict = None, - region_to_vec: Region2VecExModel = None, ) -> None: """ Convert bed file to vector and add it to qdrant database + !Warning: only hg38 genome can be added to qdrant! + :param bed_id: bed file id :param bed_file: path to the bed file, or RegionSet object :param payload: additional metadata to store alongside vectors @@ -487,11 +526,7 @@ def upload_qdrant( raise BedBaseConfError( "Could not add add region to qdrant. Invalid type, or path. " ) - if not region_to_vec and isinstance(self._config.config.path.region2vec, str): - reg_2_vec_obj = Region2VecExModel(self._config.config.path.region2vec) - else: - reg_2_vec_obj = region_to_vec - bed_embedding = np.mean(reg_2_vec_obj.encode(bed_region_set), axis=0) + bed_embedding = np.mean(self._config.r2v.encode(bed_region_set), axis=0) # Upload bed file vector to the database vec_dim = bed_embedding.shape[0] @@ -502,7 +537,9 @@ def upload_qdrant( ) return None - def text_to_bed_search(self, query: str, limit: int = 10, offset: int = 0): + def text_to_bed_search( + self, query: str, limit: int = 10, offset: int = 0 + ) -> BedListSearchResult: """ Search for bed files by text query in qdrant database @@ -515,14 +552,74 @@ def text_to_bed_search(self, query: str, limit: int = 10, offset: int = 0): _LOGGER.info(f"Looking for: {query}") _LOGGER.info(f"Using backend: {self._config.t2bsi}") - # TODO: FIX it! results = self._config.t2bsi.nl_vec_search(query, limit=limit, offset=offset) + results_list = [] for result in results: + result_id = result["id"].replace("-", "") try: - # qdrant automatically adds hypens to the ids. remove them. - result["metadata"] = bbc.bed.retrieve_one(result["id"].replace("-", "")) - except RecordNotFoundError: - _LOGGER.info( - f"Couldn't find qdrant result in bedbase for id: {result['id']}" + result_meta = self.get(result_id) + except BEDFileNotFoundError as e: + _LOGGER.warning( + f"Could not retrieve metadata for bed file: {result_id}. Error: {e}" ) - return results + continue + if result_meta: + results_list.append(QdrantSearchResult(**result, metadata=result_meta)) + return BedListSearchResult( + count=len(results), limit=limit, offset=offset, results=results_list + ) + + def reindex_qdrant(self) -> None: + """ + Re-upload all files to quadrant. + !Warning: only hg38 genome can be added to qdrant! + + If you want want to fully reindex/reupload to qdrant, first delete collection and create new one. + + Upload all files to qdrant. + """ + bb_client = BBClient() + + statement = select(Bed.id).where(Bed.genome_alias == QDRANT_GENOME) + + with Session(self._db_engine.engine) as session: + bed_ids = session.execute(statement).all() + + bed_ids = [bed_result[0] for bed_result in bed_ids] + + for record_id in bed_ids: + bed_region_set_obj = bb_client.load_bed(record_id) + + self.upload_file_qdrant( + bed_id=record_id, + bed_file=bed_region_set_obj, + payload={"bed_id": record_id}, + ) + + return None + + def delete_qdrant_point(self, identifier: str) -> None: + """ + Delete bed file from qdrant. + + :param identifier: bed file identifier + :return: None + """ + + result = self._config.qdrant_engine.qd_client.delete( + collection_name=self._config.config.qdrant.collection, + points_selector=PointIdsList( + points=[identifier], + ), + ) + return result + + def create_qdrant_collection(self) -> None: + """ + Create qdrant collection for bed files. + """ + result = self._config.qdrant_engine.qd_client.create_collection( + collection_name="test_collection", + vectors_config=VectorParams(size=100, distance=Distance.DOT), + ) + return None diff --git a/bbconf/modules/bedsets.py b/bbconf/modules/bedsets.py index a0978bcb..63506411 100644 --- a/bbconf/modules/bedsets.py +++ b/bbconf/modules/bedsets.py @@ -1,4 +1,17 @@ -from bbconf.db_utils import BaseEngine +from typing import List +import logging + +from sqlalchemy.orm import Session + +from bbconf.config_parser import BedBaseConfig +from bbconf.db_utils import BedFileBedSetRelation +from bbconf.db_utils import Bed +from bbconf.db_utils import BedSets + +from bbconf.const import PKG_NAME + + +_LOGGER = logging.getLogger(PKG_NAME) class BedAgentBedSet: @@ -8,12 +21,12 @@ class BedAgentBedSet: This class has method to add, delete, get files and metadata from the database. """ - def __init__(self, db_engine: BaseEngine): + def __init__(self, config: BedBaseConfig): """ - :param db_engine: pepdbengine object with sa engine + :param config: config object """ - self._sa_engine = db_engine.engine - self._db_engine = db_engine + self.config = config + self._db_engine = self.config.db_engine def get(self, identifier: str) -> dict: """ @@ -24,9 +37,86 @@ def get(self, identifier: str) -> dict: """ ... - def create(self): ... + def create( + self, + identifier: str, + name: str, + description: str = None, + bedid_list: List[str] = None, + statistics: bool = False, + plots: dict = None, + upload_pephub: bool = False, + no_fail: bool = False, + ) -> None: + """ + Create bedset in the database. + + :param identifier: bedset identifier + :param description: bedset description + :param bedid_list: list of bed file identifiers + :param statistics: calculate statistics for bedset + :param plots: dictionary with plots + :param upload_pephub: upload bedset to pephub (create view in pephub) + :param no_fail: do not raise an error if bedset already exists + :return: None + """ + _LOGGER.info(f"Creating bedset '{identifier}'") + + new_bedset = BedSets( + id=identifier, + description=description, + name=identifier, + statistics=statistics, + ) + + # TODO: upload plots! We don't have them now + + # TODO: upload to pephub + + with Session(self._db_engine.engine) as session: + session.add(new_bedset) + + for bedfile in bedid_list: + session.add(BedFileBedSetRelation(bedset_id=identifier, bed_id=bedfile)) + + session.commit() + + def _calculate_statistics(self, bed_ids: List[str]) -> dict: + """ + Calculate statistics for bedset. + + :param bed_ids: list of bed file identifiers + :return: statistics + """ + numeric_columns = [ + column + for column, value in bbc.bed.result_schemas.items() + if value["type"] == "number" + ] + + results_dict = {"mean": {}, "sd": {}} + + for column_name in numeric_columns: + with bbc.bed.backend.session as s: + mean_bedset_statement = select( + func.round( + func.avg(getattr(bbc.BedfileORM, column_name)).cast(Numeric), 4 + ).cast(Float) + ).where(bbc.BedfileORM.record_identifier.in_(bedset)) + sd_bedset_statement = select( + func.round( + func.stddev(getattr(bbc.BedfileORM, column_name)).cast(Numeric), + 4, + ).cast(Float) + ).where(bbc.BedfileORM.record_identifier.in_(bedset)) + + results_dict["mean"][column_name] = s.exec(mean_bedset_statement).one() + results_dict["sd"][column_name] = s.exec(sd_bedset_statement).one() + + _LOGGER.info("Bedset statistics were calculated successfully") + return results_dict - def delete(self, identifier: str) -> None: + def delete(self) -> None: """ Delete bed file from the database. diff --git a/tests/test_bbagent.py b/tests/test_bbagent.py index 7993a568..b3cf2206 100644 --- a/tests/test_bbagent.py +++ b/tests/test_bbagent.py @@ -69,6 +69,30 @@ def test_get_objects(self): ff = agent.bed.get_objects("91b2754c8ff01769bacfc80e6923c46e") print(ff) + def test_get_list(self): + agent = BedBaseAgent(config=config) + ff = agent.bed.get_ids_list() + print(ff) + assert ff != None + + def test_qdrant_search(self): + agent = BedBaseAgent(config=config) + ff = agent.bed.text_to_bed_search("asf") + print(ff) + assert ff != None + + def test_qdrant_reindex(self): + agent = BedBaseAgent(config=config) + ff = agent.bed.reindex_qdrant() + ff + assert True + + def test_delete_qdrant_point(self): + agent = BedBaseAgent(config=config) + ff = agent.bed.delete_qdrant_point("91b2754c8ff01769bacfc80e6923c46e") + ff + assert True + def test_bed_delete(self): # agent = BedBaseAgent(config=config) # ff = agent.bed.delete("91b2754c8ff01769bacfc80e6923c46e") From 199047768c09cdc78f30ac1f51f91185ce100d5f Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Wed, 20 Mar 2024 21:13:01 +0100 Subject: [PATCH 11/61] added upload status of pephub and qdrant to db --- bbconf/modules/bedfiles.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index a70f3cf7..250bcecb 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -342,6 +342,8 @@ def add( id=identifier, **stats.model_dump(), **classification.model_dump(), + indexed=add_to_qdrant, + pephub=upload_pephub, ) session.add(new_bed) if upload_s3: From fdcc258b04989e7015e79b354ed3637618a7c8a3 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Wed, 20 Mar 2024 21:31:57 +0100 Subject: [PATCH 12/61] updated database column --- bbconf/db_utils.py | 38 ++++++++++++++++++------------------- bbconf/models/bed_models.py | 23 ++++++++++++++-------- bbconf/modules/bedfiles.py | 3 +-- 3 files changed, 35 insertions(+), 29 deletions(-) diff --git a/bbconf/db_utils.py b/bbconf/db_utils.py index 50c5568c..c04678be 100644 --- a/bbconf/db_utils.py +++ b/bbconf/db_utils.py @@ -102,25 +102,25 @@ class Bed(Base): ) # statistics: - number_of_regions: Mapped[Optional[int]] - gc_content: Mapped[Optional[int]] - median_tss_dist: Mapped[Optional[int]] - mean_region_width: Mapped[Optional[int]] - exon_frequency: Mapped[Optional[int]] - intron_frequency: Mapped[Optional[int]] - promoterprox_frequency: Mapped[Optional[int]] - intergenic_frequency: Mapped[Optional[int]] - promotercore_frequency: Mapped[Optional[int]] - fiveutr_frequency: Mapped[Optional[int]] - threeutr_frequency: Mapped[Optional[int]] - fiveutr_percentage: Mapped[Optional[int]] - threeutr_percentage: Mapped[Optional[int]] - promoterprox_percentage: Mapped[Optional[int]] - exon_percentage: Mapped[Optional[int]] - intron_percentage: Mapped[Optional[int]] - intergenic_percentage: Mapped[Optional[int]] - promotercore_percentage: Mapped[Optional[int]] - tssdist: Mapped[Optional[int]] + number_of_regions: Mapped[Optional[float]] + gc_content: Mapped[Optional[float]] + median_tss_dist: Mapped[Optional[float]] + mean_region_width: Mapped[Optional[float]] + exon_frequency: Mapped[Optional[float]] + intron_frequency: Mapped[Optional[float]] + promoterprox_frequency: Mapped[Optional[float]] + intergenic_frequency: Mapped[Optional[float]] + promotercore_frequency: Mapped[Optional[float]] + fiveutr_frequency: Mapped[Optional[float]] + threeutr_frequency: Mapped[Optional[float]] + fiveutr_percentage: Mapped[Optional[float]] + threeutr_percentage: Mapped[Optional[float]] + promoterprox_percentage: Mapped[Optional[float]] + exon_percentage: Mapped[Optional[float]] + intron_percentage: Mapped[Optional[float]] + intergenic_percentage: Mapped[Optional[float]] + promotercore_percentage: Mapped[Optional[float]] + tssdist: Mapped[Optional[float]] # relations: # plots: Mapped[List["Plots"]] = relationship("Plots", back_populates="bedfile") diff --git a/bbconf/models/bed_models.py b/bbconf/models/bed_models.py index 113554ae..a30c4dba 100644 --- a/bbconf/models/bed_models.py +++ b/bbconf/models/bed_models.py @@ -50,26 +50,33 @@ class BedClassification(BaseModel): class BedStats(BaseModel): - number_of_regions: Optional[float] = None + number_of_regions: Optional[float] = Field(None, alias="regions_no") gc_content: Optional[float] = None median_tss_dist: Optional[float] = None mean_region_width: Optional[float] = None + exon_frequency: Optional[float] = None + exon_percentage: Optional[float] = None + intron_frequency: Optional[float] = None - promoterprox_frequency: Optional[float] = None + intron_percentage: Optional[float] = None + + intergenic_percentage: Optional[float] = None intergenic_frequency: Optional[float] = None + promotercore_frequency: Optional[float] = None + promotercore_percentage: Optional[float] = None + fiveutr_frequency: Optional[float] = None - threeutr_frequency: Optional[float] = None fiveutr_percentage: Optional[float] = None + + threeutr_frequency: Optional[float] = None threeutr_percentage: Optional[float] = None + + promoterprox_frequency: Optional[float] = None promoterprox_percentage: Optional[float] = None - exon_percentage: Optional[float] = None - intron_percentage: Optional[float] = None - intergenic_percentage: Optional[float] = None - promotercore_percentage: Optional[float] = None - model_config = ConfigDict(extra="ignore") + model_config = ConfigDict(extra="ignore", populate_by_name=True) class BedPEPHub(BaseModel): diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index 250bcecb..cdfb2d05 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -1,9 +1,8 @@ import warnings from logging import getLogger -from typing import List, Optional, Dict, Union, Literal +from typing import Dict, Union import numpy as np -from geniml.region2vec import Region2VecExModel from geniml.io import RegionSet from geniml.bbclient import BBClient From 5daed722ba193afc7f55b02bad7abfc36193ed94 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Thu, 21 Mar 2024 03:19:13 +0100 Subject: [PATCH 13/61] added bedbase stats function --- bbconf/bbagent.py | 28 +++++++++++++++++++++++++++- bbconf/models/base_models.py | 7 +++++++ bbconf/modules/bedsets.py | 8 +++----- tests/test_bbagent.py | 7 +++++++ 4 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 bbconf/models/base_models.py diff --git a/bbconf/bbagent.py b/bbconf/bbagent.py index 5e95a33c..8dcfb9be 100644 --- a/bbconf/bbagent.py +++ b/bbconf/bbagent.py @@ -1,11 +1,16 @@ from pathlib import Path from typing import Union, List +from sqlalchemy.orm import Session +from sqlalchemy.sql import select, func, distinct + from bbconf.config_parser.bedbaseconfig import BedBaseConfig +from bbconf.db_utils import Bed, BedSets from bbconf.modules.bedfiles import BedAgentBedFile from bbconf.modules.bedsets import BedAgentBedSet from bbconf.modules.objects import BBObjects +from bbconf.models.base_models import StatsReturn class BedBaseAgent(object): @@ -37,7 +42,28 @@ def bed(self) -> BedAgentBedFile: # @property # def bedset(self): # return self.__bedset - # # + @property def objects(self): return self.__objects + + def get_stats(self, bedfile: str) -> StatsReturn: + """ + Get statistics for a bed file + + :param bedfile: bed file name + :return: statistics + """ + with Session(self.config.db_engine.engine) as session: + number_of_bed = session.execute(select(func.count(Bed.id))).one()[0] + number_of_bedset = session.execute(select(func.count(BedSets.id))).one()[0] + + number_of_genomes = session.execute( + select(func.count(distinct(Bed.genome_alias))) + ).one()[0] + + return StatsReturn( + number_of_bed=number_of_bed, + number_of_bedset=number_of_bedset, + number_of_genomes=number_of_genomes, + ) diff --git a/bbconf/models/base_models.py b/bbconf/models/base_models.py new file mode 100644 index 00000000..59bdd7e5 --- /dev/null +++ b/bbconf/models/base_models.py @@ -0,0 +1,7 @@ +from pydantic import BaseModel, ConfigDict, Field + + +class StatsReturn(BaseModel): + number_of_bedfiles: int = 0 + number_of_bedsets: int = 0 + number_of_genomes: int = 0 diff --git a/bbconf/modules/bedsets.py b/bbconf/modules/bedsets.py index 63506411..e7fef872 100644 --- a/bbconf/modules/bedsets.py +++ b/bbconf/modules/bedsets.py @@ -8,6 +8,8 @@ from bbconf.db_utils import Bed from bbconf.db_utils import BedSets +from bbconf.models.bed_models import BedStats + from bbconf.const import PKG_NAME @@ -88,11 +90,7 @@ def _calculate_statistics(self, bed_ids: List[str]) -> dict: :param bed_ids: list of bed file identifiers :return: statistics """ - numeric_columns = [ - column - for column, value in bbc.bed.result_schemas.items() - if value["type"] == "number" - ] + numeric_columns = BedStats.model_fields results_dict = {"mean": {}, "sd": {}} diff --git a/tests/test_bbagent.py b/tests/test_bbagent.py index b3cf2206..2a5fdc73 100644 --- a/tests/test_bbagent.py +++ b/tests/test_bbagent.py @@ -108,6 +108,13 @@ def test_bed_update(self): pass +def test_get_stats(): + agent = BedBaseAgent(config=config) + ff = agent.get_stats("91b2754c8ff01769bacfc80e6923c46e") + print(ff) + assert ff != None + + class TestObjects: def test_object_path(self): agent = BedBaseAgent(config=config) From f210575a7decc1708c8c7a06db35ba16ede335fd Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Thu, 21 Mar 2024 14:31:26 +0100 Subject: [PATCH 14/61] added bedset functions --- bbconf/bbagent.py | 16 ++-- bbconf/exceptions.py | 8 +- bbconf/models/base_models.py | 11 +++ bbconf/models/bed_models.py | 9 +- bbconf/models/bedset_models.py | 25 ++++++ bbconf/modules/bedsets.py | 159 +++++++++++++++++++++++++++------ tests/test_bbagent.py | 35 ++++++++ 7 files changed, 217 insertions(+), 46 deletions(-) create mode 100644 bbconf/models/bedset_models.py diff --git a/bbconf/bbagent.py b/bbconf/bbagent.py index 8dcfb9be..ac673786 100644 --- a/bbconf/bbagent.py +++ b/bbconf/bbagent.py @@ -27,31 +27,25 @@ def __init__( self.config = BedBaseConfig(config) self.__bed = BedAgentBedFile(self.config) - - # ff = self.__bed.add("test", {"number_of_regions": 44}) - - # ff - - # self.__bedset = BedAgentBedSet(self.config) + self.__bedset = BedAgentBedSet(self.config) self.__objects = BBObjects(self.config) @property def bed(self) -> BedAgentBedFile: return self.__bed - # @property - # def bedset(self): - # return self.__bedset + @property + def bedset(self): + return self.__bedset @property def objects(self): return self.__objects - def get_stats(self, bedfile: str) -> StatsReturn: + def get_stats(self) -> StatsReturn: """ Get statistics for a bed file - :param bedfile: bed file name :return: statistics """ with Session(self.config.db_engine.engine) as session: diff --git a/bbconf/exceptions.py b/bbconf/exceptions.py index efe390a1..88a26cef 100644 --- a/bbconf/exceptions.py +++ b/bbconf/exceptions.py @@ -32,6 +32,12 @@ class MissingObjectError(BedBaseConfError): class BEDFileNotFoundError(BedBaseConfError): - """Error type for missing object""" + """Error type for missing bedfile""" + + pass + + +class BedSetNotFoundError(BedBaseConfError): + """Error type for missing bedset""" pass diff --git a/bbconf/models/base_models.py b/bbconf/models/base_models.py index 59bdd7e5..c5423d53 100644 --- a/bbconf/models/base_models.py +++ b/bbconf/models/base_models.py @@ -1,4 +1,15 @@ from pydantic import BaseModel, ConfigDict, Field +from typing import Optional, Union + + +class FileModel(BaseModel): + name: str = Field(alias="title") + path: str + path_thumbnail: Optional[Union[str, None]] = Field(None, alias="thumbnail_path") + description: Optional[str] = None + size: Optional[int] = None + + model_config = ConfigDict(populate_by_name=True) class StatsReturn(BaseModel): diff --git a/bbconf/models/bed_models.py b/bbconf/models/bed_models.py index a30c4dba..2fa14ef6 100644 --- a/bbconf/models/bed_models.py +++ b/bbconf/models/bed_models.py @@ -4,14 +4,7 @@ from pydantic import BaseModel, ConfigDict, Field -class FileModel(BaseModel): - name: str = Field(alias="title") - path: str - path_thumbnail: Optional[Union[str, None]] = Field(None, alias="thumbnail_path") - description: Optional[str] = None - size: Optional[int] = None - - model_config = ConfigDict(populate_by_name=True) +from .base_models import FileModel class BedPlots(BaseModel): diff --git a/bbconf/models/bedset_models.py b/bbconf/models/bedset_models.py new file mode 100644 index 00000000..2131af0b --- /dev/null +++ b/bbconf/models/bedset_models.py @@ -0,0 +1,25 @@ +from pydantic import BaseModel +from typing import List + +from .bed_models import BedStats + + +class BedSetStats(BaseModel): + mean: BedStats = None + sd: BedStats = None + + +class BedSetMetadata(BaseModel): + id: str + name: str + md5sum: str + statistics: BedSetStats = None + desciption: str = None + bed_ids: List[str] = None + + +class BedSetListResult(BaseModel): + count: int + limit: int + offset: int + results: List[str] diff --git a/bbconf/modules/bedsets.py b/bbconf/modules/bedsets.py index e7fef872..971a79db 100644 --- a/bbconf/modules/bedsets.py +++ b/bbconf/modules/bedsets.py @@ -1,16 +1,17 @@ from typing import List import logging +from hashlib import md5 +from sqlalchemy import select, func, Numeric, Float from sqlalchemy.orm import Session from bbconf.config_parser import BedBaseConfig -from bbconf.db_utils import BedFileBedSetRelation -from bbconf.db_utils import Bed -from bbconf.db_utils import BedSets +from bbconf.db_utils import BedFileBedSetRelation, Bed, BedSets from bbconf.models.bed_models import BedStats - +from bbconf.models.bedset_models import BedSetStats, BedSetMetadata, BedSetListResult from bbconf.const import PKG_NAME +from bbconf.exceptions import BedSetNotFoundError _LOGGER = logging.getLogger(PKG_NAME) @@ -30,14 +31,39 @@ def __init__(self, config: BedBaseConfig): self.config = config self._db_engine = self.config.db_engine - def get(self, identifier: str) -> dict: + def get(self, identifier: str) -> BedSetMetadata: """ Get file metadata by identifier. :param identifier: bed file identifier :return: project metadata """ - ... + + statement = select(BedSets).where(BedSets.id == identifier) + + with Session(self._db_engine.engine) as session: + bedset_obj = session.execute(statement).one() + if not bedset_obj: + raise BedSetNotFoundError(identifier) + else: + bedset_obj = bedset_obj[0] + list_of_bedfiles = [ + bedset_obj.bedfile_id for bedset_obj in bedset_obj.bedfiles + ] + + bedset_metadata = BedSetMetadata( + id=bedset_obj.id, + name=bedset_obj.name, + description=bedset_obj.description, + md5sum=bedset_obj.md5sum, + statistics=BedSetStats( + mean=BedStats(**bedset_obj.bedset_means), + sd=BedStats(**bedset_obj.bedset_standard_deviation), + ).model_dump(), + bed_ids=list_of_bedfiles, + ) + + return bedset_metadata def create( self, @@ -64,55 +90,134 @@ def create( """ _LOGGER.info(f"Creating bedset '{identifier}'") + if statistics: + stats = self._calculate_statistics(bedid_list) + else: + stats = None + + if upload_pephub: + try: + self._create_pephub_view(identifier, description, bedid_list, no_fail) + except Exception as e: + _LOGGER.error(f"Failed to create view in pephub: {e}") + if not no_fail: + raise e + new_bedset = BedSets( id=identifier, + name=name, description=description, - name=identifier, - statistics=statistics, + bedset_means=stats.mean.model_dump() if stats else None, + bedset_standard_deviation=stats.sd.model_dump() if stats else None, + md5sum=md5(";".join(sorted(bedid_list)).encode("utf-8")).hexdigest(), ) + # TODO: use md5sum from geniml.io # TODO: upload plots! We don't have them now - # TODO: upload to pephub - with Session(self._db_engine.engine) as session: session.add(new_bedset) for bedfile in bedid_list: - session.add(BedFileBedSetRelation(bedset_id=identifier, bed_id=bedfile)) + session.add( + BedFileBedSetRelation(bedset_id=identifier, bedfile_id=bedfile) + ) session.commit() - def _calculate_statistics(self, bed_ids: List[str]) -> dict: + _LOGGER.info(f"Bedset '{identifier}' was created successfully") + return None + + def _calculate_statistics(self, bed_ids: List[str]) -> BedSetStats: """ Calculate statistics for bedset. :param bed_ids: list of bed file identifiers :return: statistics """ - numeric_columns = BedStats.model_fields - results_dict = {"mean": {}, "sd": {}} + _LOGGER.info(f"Calculating bedset statistics") + numeric_columns = BedStats.model_fields - for column_name in numeric_columns: - with bbc.bed.backend.session as s: + bedset_sd = {} + bedset_mean = {} + with Session(self._db_engine.engine) as session: + for column_name in numeric_columns: mean_bedset_statement = select( func.round( - func.avg(getattr(bbc.BedfileORM, column_name)).cast(Numeric), 4 + func.avg(getattr(Bed, column_name)).cast(Numeric), 4 ).cast(Float) - ).where(bbc.BedfileORM.record_identifier.in_(bedset)) + ).where(Bed.id.in_(bed_ids)) + sd_bedset_statement = select( func.round( - func.stddev(getattr(bbc.BedfileORM, column_name)).cast(Numeric), + func.stddev(getattr(Bed, column_name)).cast(Numeric), 4, ).cast(Float) - ).where(bbc.BedfileORM.record_identifier.in_(bedset)) + ).where(Bed.id.in_(bed_ids)) - results_dict["mean"][column_name] = s.exec(mean_bedset_statement).one() - results_dict["sd"][column_name] = s.exec(sd_bedset_statement).one() + bedset_sd[column_name] = session.execute(mean_bedset_statement).one()[0] + bedset_mean[column_name] = session.execute(sd_bedset_statement).one()[0] + + bedset_stats = BedSetStats( + mean=bedset_mean, + sd=bedset_sd, + ) _LOGGER.info("Bedset statistics were calculated successfully") - return results_dict + return bedset_stats + + def _create_pephub_view( + self, + bedset_id: str, + description: str = None, + bed_ids: list = None, + nofail: bool = False, + ) -> None: + """ + Create view in pephub for bedset. + + :param bedset_id: bedset identifier + :param description: bedset description + :param bed_ids: list of bed file identifiers + :param nofail: do not raise an error if sample not found + + :return: None + """ + + _LOGGER.info(f"Creating view in pephub for bedset '{bedset_id}'") + self.config.phc.view.create( + namespace=self.config.config.phc.namespace, + name=self.config.config.phc.name, + tag=self.config.config.phc.tag, + view_name=bedset_id, + # description=description, + sample_list=bed_ids, + ) + return None + + def get_ids_list(self, limit: int = 10, offset: int = 0) -> BedSetListResult: + """ + Get list of bedsets from the database. + + :param limit: limit of results + :param offset: offset of results + :return: list of bedsets + """ + # TODO: add search and some metadata here + statement = select(BedSets).limit(limit).offset(offset) + + with Session(self._db_engine.engine) as session: + bedset_list = session.execute(statement).all() + + results = [bedset[0].id for bedset in bedset_list] + + return BedSetListResult( + count=len(results), + limit=limit, + offset=offset, + results=results, + ) def delete(self) -> None: """ @@ -121,8 +226,10 @@ def delete(self) -> None: :param identifier: bed file identifier :return: None """ - ... + raise NotImplementedError - def add_bedfile(self, identifier: str, bedfile: str) -> None: ... + def add_bedfile(self, identifier: str, bedfile: str) -> None: + raise NotImplementedError - def delete_bedfile(self, identifier: str, bedfile: str) -> None: ... + def delete_bedfile(self, identifier: str, bedfile: str) -> None: + raise NotImplementedError diff --git a/tests/test_bbagent.py b/tests/test_bbagent.py index 2a5fdc73..80095d27 100644 --- a/tests/test_bbagent.py +++ b/tests/test_bbagent.py @@ -145,3 +145,38 @@ def test_object_metadata(self): "bed", "91b2754c8ff01769bacfc80e6923c46e", "widths_histogram", "localhost" ) ff + + +class TestBedset: + + def test_clalculate_stats(self): + agent = BedBaseAgent(config=config) + ff = agent.bedset._calculate_statistics(["91b2754c8ff01769bacfc80e6923c46e"]) + ff + assert ff != None + + def test_upload_all(self): + agent = BedBaseAgent(config=config) + agent.bedset.create( + "test", + "test_name", + description="test", + bedid_list=["91b2754c8ff01769bacfc80e6923c46e"], + statistics=True, + # plots={"test": "test"}, + upload_pephub=True, + no_fail=True, + ) + assert True + + def test_get_idset(self): + agent = BedBaseAgent(config=config) + ff = agent.bedset.get("test") + print(ff) + assert ff != None + + def test_get_idset_list(self): + agent = BedBaseAgent(config=config) + ff = agent.bedset.get_ids_list() + print(ff) + assert ff != None From 39b5ce82dcf20ab3399d3cd2e00ad9905c5b79bc Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Thu, 21 Mar 2024 15:03:05 +0100 Subject: [PATCH 15/61] updated metadata in bedset and bedfile --- bbconf/models/bed_models.py | 18 ++++++--- bbconf/models/bedset_models.py | 2 +- bbconf/modules/bedfiles.py | 74 +++++++++++++++++++--------------- bbconf/modules/bedsets.py | 2 +- tests/test_bbagent.py | 2 +- 5 files changed, 58 insertions(+), 40 deletions(-) diff --git a/bbconf/models/bed_models.py b/bbconf/models/bed_models.py index 2fa14ef6..4739d947 100644 --- a/bbconf/models/bed_models.py +++ b/bbconf/models/bed_models.py @@ -101,18 +101,26 @@ class BedMetadata(BaseModel): description: Optional[str] = None submission_date: datetime.datetime = None last_update_date: Optional[datetime.datetime] = None - stats: BedStats = None - classification: BedClassification = None - plots: BedPlots = None - files: BedFiles = None + stats: Union[BedStats, None] = None + # classification: BedClassification = None + plots: Union[BedPlots, None] = None + files: Union[BedFiles, None] = None raw_metadata: Optional[BedPEPHub] = None + genome_alias: str = None + genome_digest: str = None + bed_type: str = Field( + default="bed3", pattern="^bed(?:[3-9]|1[0-5])(?:\+|$)[0-9]?+$" + ) + bed_format: str = None + full_response: bool = False + class BedListResult(BaseModel): count: int limit: int offset: int - results: List[str] + results: List[BedMetadata] class QdrantSearchResult(BaseModel): diff --git a/bbconf/models/bedset_models.py b/bbconf/models/bedset_models.py index 2131af0b..e5a80523 100644 --- a/bbconf/models/bedset_models.py +++ b/bbconf/models/bedset_models.py @@ -22,4 +22,4 @@ class BedSetListResult(BaseModel): count: int limit: int offset: int - results: List[str] + results: List[BedSetMetadata] diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index cdfb2d05..a8c8f211 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -61,11 +61,12 @@ def __init__(self, config: BedBaseConfig): self._boto3_client = config.boto3_client self._config = config - def get(self, identifier: str) -> BedMetadata: + def get(self, identifier: str, full: bool = False) -> BedMetadata: """ Get file metadata by identifier. :param identifier: bed file identifier + :param full: if True, return full metadata, including statistics, files, and raw metadata from pephub :return: project metadata """ statement = select(Bed).where(Bed.id == identifier) @@ -77,39 +78,44 @@ def get(self, identifier: str) -> BedMetadata: bed_object = session.scalar(statement) if not bed_object: raise BEDFileNotFoundError(f"Bed file with id: {identifier} not found.") - for result in bed_object.files: - # PLOTS - if result.name in BedPlots.model_fields: - setattr( - bed_plots, - result.name, - FileModel( - name=result.name, - path=result.path, - size=result.size, - path_thumbnail=result.path_thumbnail, - description=result.description, - ), - ) - # FILES - elif result.name in BedFiles.model_fields: - setattr( - bed_files, - result.name, - FileModel( - name=result.name, - path=result.path, - size=result.size, - description=result.description, - ), - ) + + if full: + for result in bed_object.files: + # PLOTS + if result.name in BedPlots.model_fields: + setattr( + bed_plots, + result.name, + FileModel( + name=result.name, + path=result.path, + size=result.size, + path_thumbnail=result.path_thumbnail, + description=result.description, + ), + ) + # FILES + elif result.name in BedFiles.model_fields: + setattr( + bed_files, + result.name, + FileModel( + name=result.name, + path=result.path, + size=result.size, + description=result.description, + ), + ) + else: _LOGGER.error( f"Unknown file type: {result.name}. And is not in the model fields. Skipping.." ) - - bed_stats = BedStats(**bed_object.__dict__) - bed_classification = BedClassification(**bed_object.__dict__) + bed_stats = BedStats(**bed_object.__dict__) + else: + bed_plots = None + bed_files = None + bed_stats = None try: bed_metadata = self._config.phc.sample.get( @@ -126,13 +132,17 @@ def get(self, identifier: str) -> BedMetadata: id=bed_object.id, name=bed_object.name, stats=bed_stats, - classification=bed_classification, plots=bed_plots, files=bed_files, description=bed_object.description, submission_date=bed_object.submission_date, last_update_date=bed_object.last_update_date, raw_metadata=BedPEPHub(**bed_metadata), + genome_alias=bed_object.genome_alias, + genome_digest=bed_object.genome_digest, + bed_type=bed_object.bed_type, + bed_format=bed_object.bed_format, + full_response=full, ) def get_stats(self, identifier: str) -> BedStats: @@ -272,7 +282,7 @@ def get_ids_list(self, limit: int = 100, offset: int = 0) -> BedListResult: count=len(bed_ids), limit=limit, offset=offset, - results=[result[0] for result in bed_ids], + results=[self.get(result[0]) for result in bed_ids], ) def add( diff --git a/bbconf/modules/bedsets.py b/bbconf/modules/bedsets.py index 971a79db..8d3f9dae 100644 --- a/bbconf/modules/bedsets.py +++ b/bbconf/modules/bedsets.py @@ -210,7 +210,7 @@ def get_ids_list(self, limit: int = 10, offset: int = 0) -> BedSetListResult: with Session(self._db_engine.engine) as session: bedset_list = session.execute(statement).all() - results = [bedset[0].id for bedset in bedset_list] + results = [self.get(bedset[0].id) for bedset in bedset_list] return BedSetListResult( count=len(results), diff --git a/tests/test_bbagent.py b/tests/test_bbagent.py index 80095d27..6daac1de 100644 --- a/tests/test_bbagent.py +++ b/tests/test_bbagent.py @@ -36,7 +36,7 @@ def test_upload(self): def test_get_all(self): agent = BedBaseAgent(config=config) - ff = agent.bed.get("91b2754c8ff01769bacfc80e6923c46e") + ff = agent.bed.get("91b2754c8ff01769bacfc80e6923c46e", full=True) print(ff) assert ff != None From 230e6fa4581b38fdf572c4870115abc9fddd4335 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Thu, 21 Mar 2024 15:10:25 +0100 Subject: [PATCH 16/61] added plots to bedset metadata --- bbconf/models/bedset_models.py | 2 ++ bbconf/modules/bedsets.py | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/bbconf/models/bedset_models.py b/bbconf/models/bedset_models.py index e5a80523..6c471555 100644 --- a/bbconf/models/bedset_models.py +++ b/bbconf/models/bedset_models.py @@ -2,6 +2,7 @@ from typing import List from .bed_models import BedStats +from .base_models import FileModel class BedSetStats(BaseModel): @@ -14,6 +15,7 @@ class BedSetMetadata(BaseModel): name: str md5sum: str statistics: BedSetStats = None + plots: List[FileModel] = None desciption: str = None bed_ids: List[str] = None diff --git a/bbconf/modules/bedsets.py b/bbconf/modules/bedsets.py index 8d3f9dae..4e2e5524 100644 --- a/bbconf/modules/bedsets.py +++ b/bbconf/modules/bedsets.py @@ -9,7 +9,7 @@ from bbconf.db_utils import BedFileBedSetRelation, Bed, BedSets from bbconf.models.bed_models import BedStats -from bbconf.models.bedset_models import BedSetStats, BedSetMetadata, BedSetListResult +from bbconf.models.bedset_models import BedSetStats, BedSetMetadata, BedSetListResult, FileModel from bbconf.const import PKG_NAME from bbconf.exceptions import BedSetNotFoundError @@ -60,6 +60,7 @@ def get(self, identifier: str) -> BedSetMetadata: mean=BedStats(**bedset_obj.bedset_means), sd=BedStats(**bedset_obj.bedset_standard_deviation), ).model_dump(), + plots=[FileModel(**plot.__dict__) for plot in bedset_obj.files], bed_ids=list_of_bedfiles, ) From 6a84f28a509c35534dcf6c21cda43e0a4f34e786 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Thu, 21 Mar 2024 15:20:16 +0100 Subject: [PATCH 17/61] added nofail --- bbconf/modules/bedfiles.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index a8c8f211..79c41103 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -298,6 +298,7 @@ def add( upload_s3: bool = False, local_path: str = None, overwrite: bool = False, + nofail: bool = False, ) -> None: """ Add bed file to the database. @@ -313,6 +314,7 @@ def add( :param upload_s3: upload files to s3 :param local_path: local path to the output files :param overwrite: overwrite bed file if it already exists + :param nofail: do not raise an error if sample not found :return: None """ _LOGGER.info(f"Adding bed file to database. bed_id: {identifier}") @@ -325,7 +327,14 @@ def add( classification = BedClassification(**classification) if upload_pephub: - self.upload_pephub(identifier, metadata.model_dump(), overwrite) + try: + self.upload_pephub(identifier, metadata.model_dump(), overwrite) + except Exception as e: + _LOGGER.warning( + f"Could not upload to pephub. Error: {e}. nofail: {nofail}" + ) + if not nofail: + raise e else: _LOGGER.info("upload_pephub set to false. Skipping pephub..") From d9c9c1845e5c5b19c5f341ded97471ca1f84d45b Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Thu, 21 Mar 2024 16:39:06 +0100 Subject: [PATCH 18/61] black --- bbconf/config_parser/models.py | 2 ++ bbconf/modules/bedfiles.py | 8 ++++++-- bbconf/modules/bedsets.py | 7 ++++++- tests/test_bbagent.py | 12 ++++++++---- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/bbconf/config_parser/models.py b/bbconf/config_parser/models.py index dca6c4cc..f8b16fac 100644 --- a/bbconf/config_parser/models.py +++ b/bbconf/config_parser/models.py @@ -29,6 +29,8 @@ class ConfigDB(BaseModel): dialect: str = DEFAULT_DB_DIALECT driver: Optional[str] = DEFAULT_DB_DRIVER + model_config = ConfigDict(extra="forbid") + class ConfigQdrant(BaseModel): host: str diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index 79c41103..9453e4df 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -263,12 +263,16 @@ def get_objects(self, identifier: str) -> Dict[str, FileModel]: return return_dict - def get_ids_list(self, limit: int = 100, offset: int = 0) -> BedListResult: + def get_ids_list( + self, limit: int = 100, offset: int = 0, full: bool = False + ) -> BedListResult: """ Get list of bed file identifiers. :param limit: number of results to return :param offset: offset to start from + :param full: if True, return full metadata, including statistics, files, and raw metadata from pephub + :return: list of bed file identifiers """ # TODO: add filter (e.g. bed_type, genome...), search by description @@ -282,7 +286,7 @@ def get_ids_list(self, limit: int = 100, offset: int = 0) -> BedListResult: count=len(bed_ids), limit=limit, offset=offset, - results=[self.get(result[0]) for result in bed_ids], + results=[self.get(result[0], full=full) for result in bed_ids], ) def add( diff --git a/bbconf/modules/bedsets.py b/bbconf/modules/bedsets.py index 4e2e5524..3418e357 100644 --- a/bbconf/modules/bedsets.py +++ b/bbconf/modules/bedsets.py @@ -9,7 +9,12 @@ from bbconf.db_utils import BedFileBedSetRelation, Bed, BedSets from bbconf.models.bed_models import BedStats -from bbconf.models.bedset_models import BedSetStats, BedSetMetadata, BedSetListResult, FileModel +from bbconf.models.bedset_models import ( + BedSetStats, + BedSetMetadata, + BedSetListResult, + FileModel, +) from bbconf.const import PKG_NAME from bbconf.exceptions import BedSetNotFoundError diff --git a/tests/test_bbagent.py b/tests/test_bbagent.py index 6daac1de..d3c2a1f5 100644 --- a/tests/test_bbagent.py +++ b/tests/test_bbagent.py @@ -155,13 +155,17 @@ def test_clalculate_stats(self): ff assert ff != None - def test_upload_all(self): + def test_crate_bedset_all(self): agent = BedBaseAgent(config=config) agent.bedset.create( - "test", + "testinoo", "test_name", - description="test", - bedid_list=["91b2754c8ff01769bacfc80e6923c46e"], + description="this is test description", + bedid_list=[ + "bbad85f21962bb8d972444f7f9a3a932", + "0dcdf8986a72a3d85805bbc9493a1302", + "db69691a3fee81a96c5dad57ca124fd8", + ], statistics=True, # plots={"test": "test"}, upload_pephub=True, From e30e141a0a6528d3daf7d1ce19aa09b535efd35b Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Thu, 21 Mar 2024 17:29:48 +0100 Subject: [PATCH 19/61] updated metadata and object models --- bbconf/models/bed_models.py | 2 +- bbconf/models/drs_models.py | 2 +- bbconf/modules/bedfiles.py | 21 +++++++++++++-------- tests/test_bbagent.py | 9 ++++----- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/bbconf/models/bed_models.py b/bbconf/models/bed_models.py index 4739d947..08b7c57a 100644 --- a/bbconf/models/bed_models.py +++ b/bbconf/models/bed_models.py @@ -105,7 +105,7 @@ class BedMetadata(BaseModel): # classification: BedClassification = None plots: Union[BedPlots, None] = None files: Union[BedFiles, None] = None - raw_metadata: Optional[BedPEPHub] = None + raw_metadata: Optional[Union[BedPEPHub, None]] = None genome_alias: str = None genome_digest: str = None diff --git a/bbconf/models/drs_models.py b/bbconf/models/drs_models.py index d496184c..9c129842 100644 --- a/bbconf/models/drs_models.py +++ b/bbconf/models/drs_models.py @@ -20,7 +20,7 @@ class DRSModel(BaseModel): id: str name: Optional[str] = None self_uri: str - size: str + size: int created_time: Optional[datetime.datetime] = None updated_time: Optional[datetime.datetime] = None checksums: str diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index 9453e4df..e77f4438 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -118,15 +118,20 @@ def get(self, identifier: str, full: bool = False) -> BedMetadata: bed_stats = None try: - bed_metadata = self._config.phc.sample.get( - namespace=self._config.config.phc.namespace, - name=self._config.config.phc.name, - tag=self._config.config.phc.tag, - sample_name=identifier, - ) + if full: + bed_metadata = BedPEPHub( + **self._config.phc.sample.get( + namespace=self._config.config.phc.namespace, + name=self._config.config.phc.name, + tag=self._config.config.phc.tag, + sample_name=identifier, + ) + ) + else: + bed_metadata = None except Exception as e: _LOGGER.warning(f"Could not retrieve metadata from pephub. Error: {e}") - bed_metadata = {} + bed_metadata = None return BedMetadata( id=bed_object.id, @@ -137,7 +142,7 @@ def get(self, identifier: str, full: bool = False) -> BedMetadata: description=bed_object.description, submission_date=bed_object.submission_date, last_update_date=bed_object.last_update_date, - raw_metadata=BedPEPHub(**bed_metadata), + raw_metadata=bed_metadata, genome_alias=bed_object.genome_alias, genome_digest=bed_object.genome_digest, bed_type=bed_object.bed_type, diff --git a/tests/test_bbagent.py b/tests/test_bbagent.py index d3c2a1f5..15f6e13b 100644 --- a/tests/test_bbagent.py +++ b/tests/test_bbagent.py @@ -119,7 +119,7 @@ class TestObjects: def test_object_path(self): agent = BedBaseAgent(config=config) ff = agent.objects.get_object_uri( - "bed", "91b2754c8ff01769bacfc80e6923c46e", "bed_file", "http" + "bed", "bbad85f21962bb8d972444f7f9a3a932", "bed_file", "http" ) ff @@ -127,22 +127,21 @@ def test_object_path_thumbnail_error(self): agent = BedBaseAgent(config=config) # TODO: it should raise issue: ff = agent.objects.get_thumbnail_uri( - "bed", "91b2754c8ff01769bacfc80e6923c46e", "bed_file", "http" + "bed", "bbad85f21962bb8d972444f7f9a3a932", "bed_file", "http" ) ff def test_object_path_thumbnail(self): agent = BedBaseAgent(config=config) - # TODO: it should raise issue: ff = agent.objects.get_thumbnail_uri( - "bed", "91b2754c8ff01769bacfc80e6923c46e", "widths_histogram", "http" + "bed", "bbad85f21962bb8d972444f7f9a3a932", "widths_histogram", "http" ) ff def test_object_metadata(self): agent = BedBaseAgent(config=config) ff = agent.objects.get_drs_metadata( - "bed", "91b2754c8ff01769bacfc80e6923c46e", "widths_histogram", "localhost" + "bed", "bbad85f21962bb8d972444f7f9a3a932", "widths_histogram", "localhost" ) ff From e77f8c471a59c648648ba53df05dd5c5ea9bd065 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Thu, 21 Mar 2024 18:37:48 +0100 Subject: [PATCH 20/61] added search to bedsets --- bbconf/models/bedset_models.py | 13 ++++-- bbconf/modules/bedsets.py | 75 +++++++++++++++++++++++++++++++++- 2 files changed, 83 insertions(+), 5 deletions(-) diff --git a/bbconf/models/bedset_models.py b/bbconf/models/bedset_models.py index 6c471555..4d8078f3 100644 --- a/bbconf/models/bedset_models.py +++ b/bbconf/models/bedset_models.py @@ -1,7 +1,7 @@ from pydantic import BaseModel -from typing import List +from typing import List, Union -from .bed_models import BedStats +from .bed_models import BedStats, BedMetadata from .base_models import FileModel @@ -16,7 +16,7 @@ class BedSetMetadata(BaseModel): md5sum: str statistics: BedSetStats = None plots: List[FileModel] = None - desciption: str = None + description: str = None bed_ids: List[str] = None @@ -25,3 +25,10 @@ class BedSetListResult(BaseModel): limit: int offset: int results: List[BedSetMetadata] + + +class BedSetBedFiles(BaseModel): + count: int + limit: int + offset: int + results: List[BedMetadata] diff --git a/bbconf/modules/bedsets.py b/bbconf/modules/bedsets.py index 3418e357..970e21d5 100644 --- a/bbconf/modules/bedsets.py +++ b/bbconf/modules/bedsets.py @@ -2,7 +2,7 @@ import logging from hashlib import md5 -from sqlalchemy import select, func, Numeric, Float +from sqlalchemy import select, func, Numeric, Float, or_ from sqlalchemy.orm import Session from bbconf.config_parser import BedBaseConfig @@ -14,9 +14,11 @@ BedSetMetadata, BedSetListResult, FileModel, + BedSetBedFiles, ) +from bbconf.modules.bedfiles import BedAgentBedFile from bbconf.const import PKG_NAME -from bbconf.exceptions import BedSetNotFoundError +from bbconf.exceptions import BedSetNotFoundError, BEDFileNotFoundError _LOGGER = logging.getLogger(PKG_NAME) @@ -225,6 +227,75 @@ def get_ids_list(self, limit: int = 10, offset: int = 0) -> BedSetListResult: results=results, ) + def get_bedset_bedfiles( + self, identifier: str, full: bool = False, limit: int = 100, offset: int = 0 + ) -> BedSetBedFiles: + """ + Get list of bedfiles in bedset. + + :param identifier: bedset identifier + :param full: return full records with stats, plots, files and metadata + :param limit: limit of results + :param offset: offset of results + + :return: list of bedfiles + """ + bed_object = BedAgentBedFile(self.config) + + statement = ( + select(BedFileBedSetRelation) + .where(BedFileBedSetRelation.bedset_id == identifier) + .limit(limit) + .offset(offset) + ) + + with Session(self._db_engine.engine) as session: + bedfiles = session.execute(statement).all() + results = [] + for bedfile in bedfiles: + try: + results.append(bed_object.get(bedfile[0].bedfile_id, full=full)) + except BEDFileNotFoundError as _: + _LOGGER.error(f"Bedfile {bedfile[0].bedfile_id} not found") + + return BedSetBedFiles( + count=len(results), + limit=limit, + offset=offset, + results=results, + ) + + def search(self, query: str, limit: int = 10, offset: int = 0) -> BedSetListResult: + """ + Search bedsets in the database. + + :param query: search query + :param limit: limit of results + :param offset: offset of results + :return: list of bedsets + """ + statement = select(BedSets.id) + if query: + sql_search_str = f"%{query}%" + statement = statement.where( + or_( + BedSets.name.ilike(sql_search_str), + BedSets.description.ilike(sql_search_str), + ) + ) + with Session(self._db_engine.engine) as session: + bedset_list = session.execute(statement.limit(limit).offset(offset)) + + result_list = [] + for bedset_id in bedset_list: + result_list.append(self.get(bedset_id[0])) + return BedSetListResult( + count=len(result_list), + limit=limit, + offset=offset, + results=result_list, + ) + def delete(self) -> None: """ Delete bed file from the database. From 3c115ca26dccadf6b5aa2503d6354d0c4aaa9f74 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Thu, 21 Mar 2024 18:39:54 +0100 Subject: [PATCH 21/61] updated requirements --- requirements/requirements-all.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/requirements/requirements-all.txt b/requirements/requirements-all.txt index b27670ad..f6fb14a5 100644 --- a/requirements/requirements-all.txt +++ b/requirements/requirements-all.txt @@ -1,5 +1,6 @@ yacman>=0.9.1 -pipestat[dbbackend]>=0.8.0 +sqlalchemy>=2.0.0 geniml>=0.2.0 psycopg>=3.1.15 -colorlogs \ No newline at end of file +colorlogs +pydantic>=2.6.4 From 32990ac124f105e60131c3cc711bc9ef706af6a7 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Thu, 21 Mar 2024 20:21:25 +0100 Subject: [PATCH 22/61] updated stats method --- bbconf/bbagent.py | 6 +++--- bbconf/models/base_models.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bbconf/bbagent.py b/bbconf/bbagent.py index ac673786..8c06d24b 100644 --- a/bbconf/bbagent.py +++ b/bbconf/bbagent.py @@ -57,7 +57,7 @@ def get_stats(self) -> StatsReturn: ).one()[0] return StatsReturn( - number_of_bed=number_of_bed, - number_of_bedset=number_of_bedset, - number_of_genomes=number_of_genomes, + bedfiles_number=number_of_bed, + bedsets_number=number_of_bedset, + genomes_number=number_of_genomes, ) diff --git a/bbconf/models/base_models.py b/bbconf/models/base_models.py index c5423d53..63d38068 100644 --- a/bbconf/models/base_models.py +++ b/bbconf/models/base_models.py @@ -13,6 +13,6 @@ class FileModel(BaseModel): class StatsReturn(BaseModel): - number_of_bedfiles: int = 0 - number_of_bedsets: int = 0 - number_of_genomes: int = 0 + bedfiles_number: int = 0 + bedsets_number: int = 0 + genomes_number: int = 0 From 94db0b43b463c18711c38b3a70930c41c1ffd404 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Thu, 21 Mar 2024 20:34:58 +0100 Subject: [PATCH 23/61] updated handling exceptions in drs --- bbconf/modules/bedfiles.py | 10 ++++++++++ bbconf/modules/objects.py | 10 ++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index e77f4438..7d2fb3d2 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -162,6 +162,8 @@ def get_stats(self, identifier: str) -> BedStats: with Session(self._sa_engine) as session: bed_object = session.scalar(statement) + if not bed_object: + raise BEDFileNotFoundError(f"Bed file with id: {identifier} not found.") bed_stats = BedStats(**bed_object.__dict__) return bed_stats @@ -177,6 +179,8 @@ def get_plots(self, identifier: str) -> BedPlots: with Session(self._sa_engine) as session: bed_object = session.scalar(statement) + if not bed_object: + raise BEDFileNotFoundError(f"Bed file with id: {identifier} not found.") bed_plots = BedPlots() for result in bed_object.files: if result.name in BedPlots.model_fields: @@ -203,6 +207,8 @@ def get_files(self, identifier: str) -> BedFiles: with Session(self._sa_engine) as session: bed_object = session.scalar(statement) + if not bed_object: + raise BEDFileNotFoundError(f"Bed file with id: {identifier} not found.") bed_files = BedFiles() for result in bed_object.files: if result.name in BedFiles.model_fields: @@ -247,6 +253,8 @@ def get_classification(self, identifier: str) -> BedClassification: with Session(self._sa_engine) as session: bed_object = session.scalar(statement) + if not bed_object: + raise BEDFileNotFoundError(f"Bed file with id: {identifier} not found.") bed_classification = BedClassification(**bed_object.__dict__) return bed_classification @@ -263,6 +271,8 @@ def get_objects(self, identifier: str) -> Dict[str, FileModel]: with Session(self._sa_engine) as session: bed_object = session.scalar(statement) + if not bed_object: + raise BEDFileNotFoundError(f"Bed file with id: {identifier} not found.") for result in bed_object.files: return_dict[result.name] = FileModel(**result.__dict__) diff --git a/bbconf/modules/objects.py b/bbconf/modules/objects.py index 8d36c1d1..294916a1 100644 --- a/bbconf/modules/objects.py +++ b/bbconf/modules/objects.py @@ -107,7 +107,13 @@ def _get_result( :return: pipestat result """ if record_type == "bed": - result = self.bed.get_objects(identifier=record_id)[result_id] + try: + result = self.bed.get_objects(identifier=record_id)[result_id] + except KeyError: + _LOGGER.error(f"Result {result_id} is not defined for bed {record_id}") + raise MissingObjectError( + f"Result {result_id} is not defined for bed {record_id}" + ) elif record_type == "bedset": # result = self.bedset.retrieve_one(record_id, result_id) _LOGGER.error("Not implemented") @@ -148,7 +154,7 @@ def get_drs_metadata( record_type, record_id, result_id ) # only get result once if not record_metadata: - raise BedBaseConfError(f"Record not found") + raise MissingObjectError(f"Record not found") for access_id in self.config.config.access_methods.model_dump().keys(): access_dict = AccessMethod( From 99df13ad3c777ac5019fb6972b351fbf2aab7e1d Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Thu, 21 Mar 2024 21:31:16 +0100 Subject: [PATCH 24/61] updated requirements --- requirements/requirements-all.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/requirements/requirements-all.txt b/requirements/requirements-all.txt index f6fb14a5..5bb49842 100644 --- a/requirements/requirements-all.txt +++ b/requirements/requirements-all.txt @@ -4,3 +4,5 @@ geniml>=0.2.0 psycopg>=3.1.15 colorlogs pydantic>=2.6.4 +boto3 +botocore \ No newline at end of file From 2030c13dd1ec431d22cf5df014a8747cc8fd651d Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Thu, 21 Mar 2024 23:13:30 +0100 Subject: [PATCH 25/61] added uploading test --- bbconf/exceptions.py | 6 + bbconf/models/bed_models.py | 2 +- bbconf/modules/bedfiles.py | 20 +- requirements/requirements-test.txt | 12 +- tests/{old => }/__init__.py | 0 tests/config_test.yaml | 38 ++++ tests/conftest.py | 84 +++++++- .../bbad85f21962bb8d972444f7f9a3a932.bed.gz | Bin 0 -> 641053 bytes ...85f21962bb8d972444f7f9a3a932_chrombins.pdf | Bin 0 -> 18712 bytes ...85f21962bb8d972444f7f9a3a932_chrombins.png | Bin 0 -> 213162 bytes tests/old/conftest.py | 37 ---- tests/old/data/config.yaml | 37 ---- tests/old/data/config_invalid.yaml | 4 - tests/old/data/config_min.yaml | 6 - tests/old/data/config_noport.yaml | 16 -- tests/old/test_bbconf.py | 188 ------------------ tests/test_bbagent.py | 35 ++-- 17 files changed, 164 insertions(+), 321 deletions(-) rename tests/{old => }/__init__.py (100%) create mode 100644 tests/config_test.yaml create mode 100644 tests/data/files/bbad85f21962bb8d972444f7f9a3a932.bed.gz create mode 100644 tests/data/plots/bbad85f21962bb8d972444f7f9a3a932_chrombins.pdf create mode 100644 tests/data/plots/bbad85f21962bb8d972444f7f9a3a932_chrombins.png delete mode 100644 tests/old/conftest.py delete mode 100644 tests/old/data/config.yaml delete mode 100644 tests/old/data/config_invalid.yaml delete mode 100644 tests/old/data/config_min.yaml delete mode 100644 tests/old/data/config_noport.yaml delete mode 100644 tests/old/test_bbconf.py diff --git a/bbconf/exceptions.py b/bbconf/exceptions.py index 88a26cef..15529d2c 100644 --- a/bbconf/exceptions.py +++ b/bbconf/exceptions.py @@ -7,6 +7,12 @@ class BedBaseConfError(Exception): __metaclass__ = abc.ABCMeta +class BedbaseS3ConnectionError(BedBaseConfError): + """connection error to s3""" + + pass + + class BadAccessMethodError(BedBaseConfError): """Access ID is not well defined""" diff --git a/bbconf/models/bed_models.py b/bbconf/models/bed_models.py index 08b7c57a..b20a9e6c 100644 --- a/bbconf/models/bed_models.py +++ b/bbconf/models/bed_models.py @@ -74,7 +74,7 @@ class BedStats(BaseModel): class BedPEPHub(BaseModel): sample_name: str - genome: str + genome: str = "" organism: str = "" species_id: str = "" cell_type: str = "" diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index 7d2fb3d2..a3446c15 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -9,7 +9,7 @@ from qdrant_client.models import PointIdsList, VectorParams, Distance from sqlalchemy.orm import Session -from sqlalchemy import select, and_, or_ +from sqlalchemy import select import os @@ -31,6 +31,7 @@ from bbconf.exceptions import ( BedBaseConfError, BEDFileNotFoundError, + BedbaseS3ConnectionError, ) from bbconf.db_utils import Bed, Files from bbconf.config_parser.bedbaseconfig import BedBaseConfig @@ -342,10 +343,11 @@ def add( # TODO: we should not check for specific keys, of the plots! plots = BedPlots(**plots) files = BedFiles(**files) - metadata = BedPEPHub(**metadata) + classification = BedClassification(**classification) if upload_pephub: + metadata = BedPEPHub(**metadata) try: self.upload_pephub(identifier, metadata.model_dump(), overwrite) except Exception as e: @@ -521,9 +523,17 @@ def _upload_s3(self, file_path: str, s3_path: str) -> None: :param s3_path: path to the file in s3 with file name :return: None """ - self._config.boto3_client.upload_file( - file_path, self._config.config.s3.bucket, s3_path - ) + try: + self._config.boto3_client.upload_file( + file_path, self._config.config.s3.bucket, s3_path + ) + except AttributeError as e: + _LOGGER.warning( + f"Could not upload file to s3. Error: {e}. Connection to s3 not established. Skipping.." + ) + raise BedbaseS3ConnectionError( + "Could not upload file to s3. Connection error." + ) def upload_pephub(self, identifier: str, metadata: dict, overwrite: bool = False): if not metadata: diff --git a/requirements/requirements-test.txt b/requirements/requirements-test.txt index 483af844..65d4db9f 100644 --- a/requirements/requirements-test.txt +++ b/requirements/requirements-test.txt @@ -1,5 +1,11 @@ -pytest-cov +black +ruff pytest -coverage -smokeshow python-dotenv +pytest-mock +flake8 +coveralls +pytest-cov +pre-commit +coverage +smokeshow \ No newline at end of file diff --git a/tests/old/__init__.py b/tests/__init__.py similarity index 100% rename from tests/old/__init__.py rename to tests/__init__.py diff --git a/tests/config_test.yaml b/tests/config_test.yaml new file mode 100644 index 00000000..8ee5c8b9 --- /dev/null +++ b/tests/config_test.yaml @@ -0,0 +1,38 @@ +path: + region2vec: databio/r2v-encode-hg38 + vec2vec: databio/v2v-geo-hg38 +database: + host: localhost + port: 5432 + password: docker + user: postgres + database: bedbase +server: + host: 0.0.0.0 + port: 8000 +qdrant: + host: localhost + port: 6333 + collection: "bedbase" +s3: + endpoint_url: test + aws_access_key_id: test + aws_secret_access_key: test + bucket: bedbase +phc: + namespace: bedbase + name: bedbase + tag: test +access_methods: + http: + type: "https" + description: HTTP compatible path + prefix: https://data2.bedbase.org/ + s3: + type: "s3" + description: S3 compatible path + prefix: s3://data2.bedbase.org/ + local: + type: "https" + description: How to serve local files. + prefix: /static \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py index b811c485..912621d2 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1 +1,83 @@ -DNS = "postgresql+psycopg://postgres:docker@localhost:5432/bedbase" +import os +import pytest +from bbconf.bbagent import BedBaseAgent + +TESTS_DIR = os.path.dirname(os.path.abspath(__file__)) + +CONFIG_PATH = os.path.join( + TESTS_DIR, + "config_test.yaml", +) +DATA_PATH = os.path.join( + TESTS_DIR, + "data", +) + + +def get_bbagent(): + return BedBaseAgent(config=CONFIG_PATH) + + +@pytest.fixture(scope="function") +def bbagent_obj(): + yield BedBaseAgent(config=CONFIG_PATH) + + +@pytest.fixture() +def example_dict(): + plots = { + "chrombins": { + "name": "Regions distribution over chromosomes", + "path": "plots/bbad85f21962bb8d972444f7f9a3a932_chrombins.pdf", + "path_thumbnail": "plots/bbad85f21962bb8d972444f7f9a3a932_chrombins.png", + } + } + files = { + "bedfile": { + "name": "Bed file", + "path": os.path.join( + DATA_PATH, "files/bbad85f21962bb8d972444f7f9a3a932.bed.gz" + ), + "description": "Bed file with regions", + } + } + classification = { + "bed_format": "narrowpeak", + "bed_type": "bed6+4", + "genome_alias": "hg38", + "genome_digest": "2230c535660fb4774114bfa966a62f823fdb6d21acf138d4", + "name": "bbad85f21962bb8d972444f7f9a3a932", + } + + return dict( + identifier="bbad85f21962bb8d972444f7f9a3a932", + stats={ + "number_of_regions": 1, + "median_tss_dist": 2, + "mean_region_width": 3, + "exon_frequency": 4, + "exon_percentage": 5, + "intron_frequency": 6, + "intron_percentage": 7, + "intergenic_percentage": 8, + "intergenic_frequency": 9, + "promotercore_frequency": 10, + "promotercore_percentage": 11, + "fiveutr_frequency": 12, + "fiveutr_percentage": 13, + "threeutr_frequency": 14, + "threeutr_percentage": 15, + "promoterprox_frequency": 16, + "promoterprox_percentage": 17, + }, + metadata={"sample_name": "sample_name_1"}, + plots=plots, + files=files, + classification=classification, + add_to_qdrant=False, + upload_pephub=False, + upload_s3=True, + local_path=DATA_PATH, + overwrite=False, + nofail=True, + ) diff --git a/tests/data/files/bbad85f21962bb8d972444f7f9a3a932.bed.gz b/tests/data/files/bbad85f21962bb8d972444f7f9a3a932.bed.gz new file mode 100644 index 0000000000000000000000000000000000000000..8ab86ede835345ef653ffcda6b91b6a66ca33991 GIT binary patch literal 641053 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�~bG0L~fmMqtw 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%0A|$#QFRU8dFjH?&g;6mKX0voqhyTWUs#s(e8FCu zj@zbOLWY}arI2Ffyzg8942){fFuINPzf z#>0TL{36}MSrY3!#`LF|G-h9EGUC}kh}8hDz;H|Q76jwJNJlPp+@QQrM)d-+3R2Wt z&&9IpsHTj#Dxrp=LBJ@)Es%>Qz&5Hs zPRlJ?2_3}q=v561(3F}yJm1zXJO<7%O7xEMnp+sI!iwOau$7RuEu;+X4W#YLs&BWI z*+Cig4^P`(ColV1P*5YLZ4~c3l{uwkz7pM|(@Sw< zZof$P+7ac%g~PE1N6NgUn2~m^%gA0*^Ma)H7vuMjuxx^mo4yU;v*e|g zESe#D8Rk8lzI=nKMTqf-hEs(Rf8)IAYKb7fZ!$YO7$p^1j`B3UaM-Lcn!gFdV6*~8 z<`qC$@oFvFpJJbZR6Ji$A@gRR0X}Dp?9Zs{yiZ16n@&a+^m8&EiTG6MDzs%}FZs*j z_;{nzeCo)SiVRvb%NX7cCM-Swa@$|lqC=vLhAv;1;A;_5^~hf_!aHG5NhlyhFTqX$ z7yl}BGtV-%fCIKh&Gfp*#|ka7chR_O&rU?Pw~_s~0Q~f?;Ep4cjD#anOq1K8_dx-3-c8=S^6rWXw?L^smt`|<(uYJm+Wgdj8l7P()V@r;(S z$P0Kle<=#`@y|#VQzl&mSwY=k3oIJllBZ{zYG*cY8`Gb_L-zHqiS-;7)pG5~EsXJp zu6P$@L`9Oief-Qynu=)QZXJd}MtS**ZKSCFO&c?C7n9zSJ+*21 zwp&O!#Jf!C&C9M(m@RxSr=H{zTAd(i3iK(x+=vAp-!H^|k6Tz3IKeTRmjFz20*fSM z{4i{o1mKy6QFujeIhtt!&348P*x4zQzSp&ns>dY1n1_p*5{!ay={E zA0f&SY*K1Dmn`)uxpn2UVHwFwUr}I0O?l7Uj9fXdGUTlU$F_L`rLpT4uuG}ZtHo$; zhTKBL`5u#>q8pzosU#*N%*?iN|!j&NW46#z_9Az>Hsj za!*EUkzIiALWY|*qlk-ct_5Y!I&@NuP!{X_n2dfN8LMPFXErJB#k#2WoL=ene{}Vt z*hDKsT%ra8<}OXC=gZoqH0l1yNd5*Qq#zp1h`Q;D4&gQlR};14&Ea|6+Sv_Y0HgYo zJf>zBRw!AZMkh3(W!e@UquqVw);BS4MT}V(e`yYjM_)5WmfV#EjSP`NDm#BBAT4#{ zPlP<}X$ciEpnY~bW;Q$S>C4XIB=ZnP6(*ez z)_aX8!_gkCXDzo}R5!w?e{gGyXAx?{G{8_zqB;aO5}!ESUoH`ip{%m zqZm&9d)Bnq$EjU_L|rnvcji+tz4y7maJelo?Jc9YOPl1U?{(ZKctc_fve9Ks_d1r? zNZ3^pI}*pLQix}p0$h<;@k4i$?LHRbU4|d^1}gP^RQu@+m^X`JsB~jwck>e3fG-9X z&bJ-5*$^JY=x#`G#Lw%f_LJ&myC(}JWf|2C38p;$PHg>1kK#=_!WbjD3&=pHY0EAE z^kgieBBmo1Ay9w9RzKBp^VUKUm*a$U!tZu|BMJX3DLbIgww?uG<&^6lB$Y{vx} zjZED141-Af*?dV406N{W_`OaEVL3r^ApG-y(cBXEY7Wr)%(ofT#89MuCEf4B*x&KMU)wy0p! zCtuW7R4+v7(i(UUDZ3*YYa64xnRaN#{wqr?ZdgPk5_7w48z+ce3Gmg&3lVJIAhHEPuGfkEJ%y6FLX!#<|FT}JoP zSV&dx9S|JT<+i~GB%}I|Mlj~Dvae4nl9O$5sDv?6^1ox@>9&F!00!`H92P@tO0_hK zrw>BOTv=+*+zJL7PhPj2oG)t!G5v6i9Q^?e2TD?xA7foedRvc;x%gdGN!xBg^YXa`+gsqplkgH zaaonaAmGxV@#8k3<BmneTm@{RJ=pJE4DCZ0LinD!YkJJcd zaHM+O0+!e+Yjm)hXjFmf=pRx+cAl1AhM9-DvJ8KJAd*F<4O0b!#i$E&wt(an33 zb72OY4O%fURg3_224I$FL?Rap+gL_2+)^Fpwtq&);CTi(TE&&fu3`p9V-WpWPo*q@ zcZ?jpd{MB&nZtcRg{mr?MQ*}u^q;Z7`=|b8uRKl7JlngEZj3i{9Zxhf8&!9aYQqzG zNVQJ}QYxukSVr>~D@YIDP%PmrsA^dUCk2LtESz5B7mN}Q!osek8Q?<2h#WIsw_G+G z*O6FHlsI)8aP>sA22KQJtEnjv!T3X|Lb&obpuf60Zb>!T2Y;Lv6MX|WPP$jYwOy1q3>76cn=slRmee>6iE4W_ zs38$G7!a5eR7K)?+QG1h3>XRAZs9L&s}WxZmHEd0p|IL$h=`QzL^I~Cqu3;4xEt}5 zSKiw%;ka!PrR8O~na_$U!5_)XD3Po@ez^Cuba{JH9|@s?DIgy_9m9fcBq?VHZX&R6@Zt9{VOVF@PJ&iZ~=D;hyD zp&P~@QUN~B%d@ugT@wIG4MIU0={}9W!j(V5W2#U9YP+O7A~O z&jEEUf|{2Oq$T!Y0_MnEchw&rgDoE$Ov0WWq8gwpDXM`^t*borSmq7RioOg#s*nwv z>kg2^gqtNZ3|O;5R;FyjuUnv{q#{Wp(DK)2gw^aDOfnz^q&-^*BT4v5p}T*Y(#X;v zV1cm|=bUaWh!QzGZ2%@8;CEZ_3Ogd_kSx}tG{f6!#1yx8b5V#4o+63PTqzX~Vk zkODcIw=w)}5CI!rBh|BS?fGf!%4lBd@`BFo7xm-k-a}-fawJP_!aXHHl=vFGJ|H<AVuoj<7z$|mQ=L+A&o2^qs5R?P60_B1t`?6_Pd~UY&98vKJBQ6(QC7G9JdpKLK!psVL^Rnhb<2%#EqO& zJc%#|vlE9tQ5(I2o|W%2I_Yk^BuK*7#DD#PSBpRXpaZ7aytvewo{~XHu00heVbk6pPnu{nwTBAcHumuXSi& zBzGJw4bstO|^na!9NQns+oZEv>f0yEu*>XGPKj) z*%;4RktOGlmofhElE)X*5l;!%ypipsWpp>#fKp8AyCK~dst>%r*n(*NNEhSW0+dj5 z%*&`=;qU^+t(FfJabQPO3(ULNqX0$;LYL3C9dSg6gLBZis>7D+_R)C9il%WqqWR{_yCkd7F``5lqA&gnWNr|5_LJ)K%{vnL2*Fsd8o0N4MkdeSp*Q;3WKV#z4(@>c>t*fzPF-8!pQfi$fAH@Jom z-B|&DNb6mOAHV{a^Q$b@i7ZMQO$RbYb5{)(gMr#=1dCa0%FMgWsbjCubNWTFW9MiR zSFMcUZimBE@IEqq;>J?*C_1>!7+xJPQH=GEbf29_LBf}mhnv8vNNd{*567+jU+gHB zG5v94LOZqY(H9B2w#J+(kDXw^B!Wz5DYw`F&tr7|>_12D(ga@R^0YL8v;CFQ1kP&Z z&U0MYw|6 zih-CBCm4(vNExE&d)Qda8~kfw8Qo0+L*?oHSWf4B98-N88O05_PLk4T>!t^hJRmVb zc`c!WY)3}F`O?jky?Y6Oo6+3uTIS?x+x0gpO#TOBOcPsWoTH8QpYVVu5GL(=yMDIaQPJKZ3O|xEr{$uM{GH?s-5k)HK*j_ z7{!fLWtgRmEgl;ula;oTEo7<8zW%5Pbr-|Rgq*C%h{+9m;|c=jyxbBX|J;0IVj@}_NU$p+$WVivK`!$aL#uTe z)2$|7Jz9Ly3l0@@XHES!Q`=goy zeRf&d$SlC}$p)lcQlR}*d#%pnwsqLPA!M_(@CYdLBYmdW)%O zA!i2H-1h+e{IW~Q0M=FUYlC7Y7gAcZn`i%Ih$z!C{B+(B+P`a6mCJ2kU zx@JRn0doUEl_|RmC>Q_hgDpfI^`;Yl+ozyV=?`1r#)UUC6R+x?&*Qd_qQP}iA$QY@#OjO6)OpEi zg56w3_Sb5->e8;U!k3*{$#xd46l_@5{;Lnvpq`;Mf-&6MGq5`X0sf&#Z>OSt>IoIi zvVz*{Fyh1{XT zAEImKRR3%{C-F366!)Asz?~L%9h)ZnAabniTO!BW%P*2F^JbeBYEX>n9uHyqrha&2 zC#X#>T<&3AxE+m_Ysv|4B-6_n?!J5?uX~M?$Jsx&u*ryJ{NW}L(0o%V5hn?%l*N*g zx`xLos$4I5SazA0(cQvAbhT>PQ>SUxDIFLhCPl9Hth)EEl{_sO9Ws)C%!&HyhUkJC zrK1HzHpCLgYN+Aed3$K?y7lEhlO*hw`{J4dHGb|(d%V8P|+b!}kCzDfX zT~D|yAX=c)dM1C0U9nIlE~7>NLbiPJBLGeDl8(8Z$Q+ln$ot4Q6%3>$_8-Y@9?_p? z_VBN%Gml6J*(}1fmdXzu8x}30&2lP#_VO)-pE5>tGbtr1<~3~m8zl@0=nC8e2>@}& zRro{JyD2F%WBThB{gdy3$L$Q!)zz9W%J-U}vL^*2@T z6!x^SYV;!zw4$l-fS}D`&${$FE$ikE--y@L;sa1aQfq&N>R{>VA+}sDBC^uqTc;+4 zk^Sf)=`n8J&kA!k0r^Z-2_2*HUCNWktsP%>Y|5zqGR^qrj5--LkQ)wh88y0BGJ%uC zYnhz0PpN@9Z~-b@*eMi$6{R{d0F1q16#rTl0&HQvEuE$8-dmY=eBhe!x`;i`_f5W9 zYzs8*i2xa+`5TJh&Ev+K+x8*xi_mz4vgCTpxZ`rm6WDQ6MviWU`ZPaM3(&}B2=*wI ztO%VA)#-LUXH;!1Ej3b%Kj1v{ah9YJV4$MTNP~WW2@xt!4>+qLv4aeoj6U5r-W(sw z5PCjT-b5KPFrWVJf+AzOnHFfDmHw$)H^j>efUGP?IkYgL z{Xe&p3lBhY@M{aHtoI7ieNN+Q_kPc58_j+5*tPj@tYKHX)pOS$rAAr*^^Qt0$6_m& z+tK*9VNAE+XAWvPXdT;L$xCG?Fc1Sh%7rZH0NJa|g;W*ZrpP3OdRS5zs+za=22$Az<8bQ~9rD!RSqFBl#k&G?!J5~F!JE%?G9qjfta&nc_u2DzB1tqc$nWHH9Ax8Pb{VrABx#C5H0T=&Sp~NWuv!L;W^RyP4!s#fZxcdT-g>*?B zB(yTXa$8uDfa)u(u>YW5@J)GBB7iad_q(NQ6slMAG9&m?MNtoaX91CK(SeGX(QHk| zNbVX5`io_alZiUE>0qplw~!fBk?LB#+;-GLmhp$6Jc$tYGmXji&zbNX3J2&Nl%k(V z6{iXnMC`(Rvh~WsNQf zTX(Nyi_{^Z!7z_*x6;IV8x?#g2=K-<`7)AQz#PomE49Q!IBm{SPCBH_sBVmT<}i$# z^%D>fdNw}-X)1V}5{ZwOTeMHhGW&bp{IQUiwWZpcti|8 zwh(IVceLsQZO7XHeIcW}=LdjWwWW4|TY@ILZbJmKQ(4Hu>^$62=FO5YX)l@K7yZm% zahN}3;&sL#NTH1CuULr3=fCNYPrYKIC&84g8Q{R&PRIL~Jz!PDc?Tk{GW>IbwD8^; zJmUGX#5g*&BaD>pTMxG7MbA~?QfmD1CyVC4#-FAc*eia+o4o-UtHtVc%b~D|WKoP4 z3Ty^duk9Z)s+h1Zw|2|syo}}^Hj+rx+~CdDxOnM~>nppDL6rgth~*Rzh3rFj-T$rx^Y1;WPf>ND5D zNHsLnW%zqO5|May`-lfx=#x7$vNEc>R!-k;UwRA;u%x;4GRSr=y{1y`iB)H_Fj8lf z8NbgnJ^lmupf zyrx#sjh6w;!s|7E0mXV|Fk1lUGW#;J|EQ?nutzS9odz{aYJRul8@Kau+XyR? z49$Rg-Oevs68$`_9hJl)GOB+ixA4kLe2C)3_{_qWQQdSu8c|y#>WM-{md*n5Jt8}8 zW&E1zg_bxW0)U}%z1J;w+s@$|WkjwzrvIZ9VeEj;S2AGUZ1n3lKE@(XKg|7Qq*_ zZ8SH-(V~5RrR+W5wg@P@jNw-M5fS@qGE&aBg*1dl97c6h%A$b|)Q^n&&wG89yKKUb3bj;;lKv!rHhRdU9#|NC09oA z`!f78r>fn)z`f`Bveiy#yC5)n@|XSkc&Fa6xaqh>9k?%}_>*e;l#IXY%fg6bX9WFA z&HR(3lZy(yUZ%mO-k;eSkw})B;W4QTmGS3o}7i2q;27{gUXG;tQ z$6g4`pQ?~^EvXR^43&}H>IYfez(eIBMiR2rmBwlSScby9e7}~Ioz-kPjO-qW)J*A1 zZS~B|A-Xdtv&$%dc**4pgvW`d$bl{UT1GGaH%v68m=y+#spul0{7gj2xO!jYz4^T6 z#vol;#&FO5z!&^FlakNIwRjqad>Pd}(WSycQ2LdjWy$*~Z9O-QQro8lt~8G0PVhFC z(fs9P@D%T3f@cTyoE1r9_$Pm|TI(&Z=&>evK_X{G-zs*f1E36@&dLIpMS6fS{U`Gb zdq5tt5VSuvAYYjtWEvD+*Q@Sm-hfl}W&9x-nijXM*=xWq$qenOYb=IiIZh1vyL%@&Xb%GxqMU0SF1UEWtXv--6Dziq)M?s8$O7+QbS3Y`csHAZ*a;kqxfq?Q!UcI&SXkc z+_W^^w3LJZ7aKx3pBH4$+{SdXX%tbaZBeHjEqYjZG;~dcM-x%<3FBxxfy$PV-O(eW zYVX`34?#;yb|WKFFC)3fa1i!MTWi8nF9_vr2hY|74Cr=}w7WWGXBMM+%c$;q9zKD0 zGJwl1f&e8fBfCq0kmRj3HK3P>ab+Wx*sg3uIMEX-69}kqk5Szfbhz^S+Cd4vdSej<#yKSo;@ufIRprx zL#_g5rPoG+kkFsdaNXk+k}c?H6GTw%xB?cGcR|4uS(vXuge9Z9OMh#>yj=40d|0Mz z?Iy;^epDEptDGn>213AY+0r^!ZwDx$_ae*T^gXCbFoFuB+BS+P^CiBBq0$yAuN31tx2*sEBdvM z+X*b=30G5_FiXgwK-f?IZ|#PNmF zcQ|XR5An*%@R#h1;%nt0pdIEaHIa!ZSFnGJ#lt21de40TlUhb`cT?fUc-5!5LK<4A zXaFV&tGmChC9&`1Z@1eay(<}h)SpHT+qw!YSR1Nc3 zD$$|hd4l$uBWQFxC{SqQse@*Z>bTraX;)(u_lUe*WZy_Ao&`0N?f@CdjXGyIC5oT#}~Trui5Q0yxkbA0HY^k{$WAUD&B(X4cU5q<6f3tqy@07sFP@tdb^oVx!Q2Jw=HdLS=L+gkIozb5Qx6Bedrc$-RXu+M! zGyV5I()=LOTDCV!l!uXnyTV$~*L>~9Jo5yQ`3**`FlKajW6D>==Jl*7ix(lVk&)f% zvIVHc+pdlAJT1e$#8Mc=4M`Kb_S>N1!Ak)kn$#N2XeqdFTlh!nhcwu-MzN^F`5k}; zbbaINWMn=ksR?LCbt53ea-7$^?Wme?LWyqmDJh`~rFC90+H^$81Oa~t&NIE1vKrMh z+22H4oJv&J$VgCE_|&8_;5Y&)41e8^+Sg9@&}4>Mon$Xi5UR*AD0mp>X;CzmOb_fv z{(Aso^VdtSoHJ?$`V-6WLzBf7^it8ipbt>WQs|J;+~Q806aPornI%ik<4XGZ-^?-2 z!~Qqc_?!%p*$-Dy2(z{hWL4cnO5%XQ;r`AEP%gLJK4Tfhp8z5L_6C~0Pe#CMVajOH zf7jX_@P)3%6Gj!facLXftwc?o@nNU5$YKg?4t`0KBKDWJn_iFa8kl{>h<*WVB+A|q ztmSgcO3ure?slg50Mk07_JwZA7J3dO*_O#`XFdn=7Ux_>{$U~aFX$d>xZDnOjxc8M z-vcyj7vVNJCTPt%!x2smY6Vtq%MjgZ%ELwu!Iq5bRyId2{Jjx#f;Tu_*fcV-yTisqZCMQv z$pFx+$N`F!OA-yni%|n_n&6Sq+`|*3;THU@ModlI-knlsS+psAs%Ll#Vep(l{Eg9) z8;d4=%De|-bP%wzT0uI4{5nQ~`p)*rQ2NhhbT_*mVc$D!_8=|(Mt>is zeKBC%Z?B@hlTrMq1)S!u`Scl5F>fLy!|1`yt5Ha^RJ5>1%+mM-ER=T}D8Y_6&!%l- zfFqMJ{SCGz5Uxrkg=SBXc9f+by#S{CgQz#%_(pn8MG=h|{=qW#LYJ0DLhk^qP$zrW zly#*s&g9v36Cf(0V70@x;*Mwlt+$(-3vMkSa2O(=C* z<7E_4GRgQMqXu#QT3J1#bmmQj{WAPShHzxexrZ1kI!^XSJBc~GriD^e_wL-bj6SM@ zi^1!5Zy+kT?tmIU^_Fm%TE%v;h|!5IE#B6vX+ z-w=YHf{aX&Rq|K=by}wv^EKY!#*{IBSjFR;WbZ_86=xvwAbIC7_qs(|eYcz}RbIok zjR|qFLtAbOz0-3-*`X*lEsS4KG^mjY=Z?;6uVIbCSVjaZF#CyVfquEIC7_myk$!l| z?fq%5`Em3bZM!Zb`>WS>0Ozn8Y?ffbszIpSR15qAG@0)vjCra617%Eq>vS-ww})bE z`*d^`*hoz9S<)E?XURBcg&m@kjHzbz6WwmXkmP;m4X}gYIXh!Mi4`rKy?VKA4Msp2 z)lFdq^@Elw8O^O_2>DnGTYP(Pp^?wp8Id(ENTs0M*^foXFm=h8(ciL#)BKegAYN`4 z2ak;APeVX=zfCF5Ckv?-gLHbBX4nPfzG>$dN7RvXH*Y17<6*?;k1OUkN7R`RsSMdt zJizczE~rQPHivV2wPaB8OUPjOK_yUom)#8kCo1~f0;j3odW918q_x%3voN=j{hd=V z&v~`iAY@c5KB~xB0@EVgre_kyoRy%s!i?f(e5isbzV#C89 zR@bhL!ZSiiF7^fkY>CLKO(CNUA6{)IN#L?htqsY{2_@v@e16A zCVrMte|X1wg>B76hARA(#wC&}mlRAQciw5Q)zQMDJ~E@aIg+_$HV;7ujcj)|JOq8s zy8eZ(&)lvD9?IM?YH;(zRB6iT`Y8y<>q56jZwpso3p^IaV(jq0JZsEWM)&U``@71@ z;w^w#9MP7=H*p2Pyo%&TI{kP$T~m=1oVM;}ml%Y`o=d46?k~$Nb5|A!_grNF|7>19 zF3F3G?k<`GsT*l?0@&?pG4n{`7mOfQEdVJ0qy+Y9D^ODzexhW!6Nakh8LAWtnuF1C z=+Fj?&CrcsmqCMw+%~(6=5B}puKwbLJWmS&hF#J!hP(ZPCd#Xf$RqOFXqh&EvJHT? zJAhmIVmU2{RNFX)Oy8JXAq*AJ+a-(E7$J}nF2*mf88A*>i^?JvCQ&jvuZWZ|K`83_ z(;aWH%j-3p;n%|f)z$m%vRM+zQPug(K_YZC;KyBCrRpgvD>IUx5l7|OH(Cw5d5&8k zdE4;U{b+)`6S}AKZS7mL^kn#np+yp_f#zc2(^vo+OL9xK3vr5l=;{$HXkn32{HeSY z?)t_^L8m~goSGCoEriTNWyiB`q3~~W8P%O;Qs#f>;2GC~vZcNjl)Yegl?Kj}96uz! zmE4c=IZ{zv!uCG7%@61swQ9}EV)zL`1?Fo?Zy}T&@aRU#u)$CoZB4Zmhnztx03Hae z$nbNV!>smBOml{hn!0Ptn0~EF7RLK~&X?QHJhP0M+~O%x6;V=Ke2#-q~G3%Bjz+p}F^?uP7|Ez0=%- z+AGL#x4G0_nH{9Oeh$cP$Cjc;Sfbr+#maQv9^r05IQN8lG2jE+KS(&Agv6p-@%zj0 zQ-$%JHt$_zN*r1GXh9U+5P0wQ-8PQfCK@k{>7SqzR`4zFJB0)Q7o zEk=+2TA0p+xvn4EhZf)15y6706vgZsDz|p9d4p!CFQfb8D2;2sRFvoSu)R=Gmr?u+ z3YPP)ors3yTvRX?}H?+NL}#Xx?isWiq~cM z`7tZV-&Yp41BC9#%aZ+IOt*w%l`>UXX$ZXEP|*E}%$4oi(xQ+&OUhDh>g_Uyzx&j_ zK_HyLe2XPo*Zv_f@<(rgVP6u=JDhsKV_*S3YooqP~uy3yvfeWPY|X4TExoQzG_Kgc3X_qJ{S8%;~Mt;H08 zjP6Dx^LcXI^vt&VnFosYZ9(~2s7&pr-s4VoKvfz)7|l;|R4sqzh*(lfK>`rATL&~ds!u@|5;j2QGOE97&We4N{XS`kd7Gk`z^MLC8?ucb2u~r#=OpebOxQ}!RcXkX zXy(?Vq$8vIPYZ_9Uqg#?NLe1B?d)|>>g#K z%#}YgWfrYgiFSoLmegP$Q=@EWCDRFE02S@9=q8h*L;A&4@EjKdI@z`jzqAx%X`<2^@ne3e|_I`6Lv=NuYdxzFU4^S`ias`jYh)j z+(2eb|8NSC_7^1b&$pdua*)Vl_{IKg$^K7}ni=iB0+oz0syn)X73K9RIH#0_?Fp_& z8Gd|Y9aN+~Gcg%xS{jO%m)IW)4>y`~HUuZP(fk#ukv9_#B$07Qd%-@Q{mt}aGLL^X z*{cj=Uq|I8jN ze5=bCZYZ?aP2XX<=M^*40FBfXle^#T7ovMtLmr-O(g+zd_`fUx)7GV~`p}t7s3ld; zEyW>h>}U7bM`!8F_@NF4-u#^t;4CRryGVdAia(PVm+PC`Lu6>)s_GUP-7U^m8D?7G zRh-b-t6c4n#MlwZ1b(=~M)L*^O@^6%xA_Z!jcWtJEdpy6Ms{j>!4M?G%@Wj31yS^BdaWc0KJ>aY#mSQ!|s6 zzgOU%W*0|eXA(e$ALw2|Y`iv$$9&wP>y92e#_;!Hz*)TsJf(PE@`!~-7)Fh5*etxb z?_H<*IUG9_<6KHIs=I$mo0%zYoyqVQX38XE0Hw9q+)^A+Iu8;JZw)vkMvrc7HlTA~ z?AzluSt?eBj1=5uPQL4V|MWr3+5@7V)s`{b{T~hLzR2PnErhPJpLCMU=pe3-Jq4(w>N5Pd4_(SpH~VNs#+}46cGQ9gJqjsDJ>grY=m%6lMs>$g zAQ#_d5XyO4=ulf*Mt090fl|#vRI;ENWMdF;Pw2-ovQpgt|F|76qAtT9HIgN!_Cfkt zLNEFQ2De3a7Z)SkQ(En|n@7@^w;9E)IVAjI-IrcWmiQ3ISlkd4BSTx5uR?N9#U8zF zqyFF)S(dSu)C4&XrhWjjW=Wy8%HTvgZnIcjWcXpL#7kxA*sIB9=}=)xAC8BzXj{hB z62Y4-sl1Hpj-wj?K>s80yt%!`qm!6fv}z++>Cn z>$moJhKssrLZ6wyChhS`nd&e`_9Q~VvW)DOoS@e8-X9;ATi9%uQKB2x&xFDd;GA3} zlcz(t&2=u$iJ;cglg!H-kW(4mJ$%&C7f{aYRJL!bgdanQSEtwUMO1SgQsAz2<621V zrx|b1(u))t5s|VmEapE&ed7tQ_chMe5gzBplhOTm5W`xp+3i!W?`T!dQe@2NE`~`g zMSx^x6nV!QlGM$ErqmEO{d4o#qb8lm7(WD4z|F%>MIh0rv``llzC|^5{7Ps&9Jd`b z$TG59W=T5oFJonW9H*nwZj@2oh<<2vO8clCsqV++-UWzY?5YzSKJ%bG6S;BMVl?-x z2JiG0V|ZpY%v(loLrxKM^)4x5;t`&M1*qH0r1mH`FetOF`;4L@H`%ZyB2Mt7H_6bfw-RD`>7 z-6E)s^6KQYj2d1!`<7`L`ZpN0x^G+RGOs0slZ|9^*DT7CG5kpo<(RRV5TGXvLbJqf zZj+tOQ3&8LFSlCfGKN3DEqu~n@0vK} z>|8`O!0=*pe>TE997_NQz)n>wwQD|+S~88>Q$n!VsnML4QQWxi2D|x(dAp0Bs@hI! zf;|qHPa%F7=S+s6hxdRnqx*2Q{rNhweic`l#ARGUhD5xbZolEXJDV0Ik&tA};1+ys zlA`{cjgdiVl&J@JaFnSv|8kg)y1n3Px04Kr5ZrD7AnXbp*b-=8EwX{h%MOiNn{X@V z9fQqoRYpwy(1PAo-xm;tO8}E7X+dje|A~wvE(pU3?L-U`1Haq&MFIOHd$xQjT`Z%y z^}?EM%2#m7Gf801$a?ZJnmfviJHEEIRqJh$_> z_k{_2ZXb(r(92my_eWBkfGU?Dz%6oIi1R0{0VZ-NcRnM{@YoJ8ts=AyZg#Q;xp`Pl z`4>!SEe+%(A)YHqV?f6%3||Bm7|qQVNewmkeN=S2*N3pVna(T_lQpgWOel7U?kP#i z=>8T#g-mKCA)rSYYGV^glJ2h&8{Q`cP)HC7GKN3(;ibNUW%F?hpq1PQW4Q4wz<%JM zSyODKL8}}8dSLHHX!FTA&V&`!^n^aFj2_&pxIK-%0iBbrOd5M7tqEUZ?|JtKN{3RT zFT+2rK`W&#Dnmv?#8SwpRn7{gps$E`HLBRrq&u%LK;a&U!R0HWB|g*Jy$nu|yo}=C zwa|*cjQ2kGY?+qsHgtt2Vi)c`%bod(w0Nioh-?2GvGt^SQ@@iXhxVH8|XYescbE5S~j z)`*BDKAo~|q8%QA>O&hGG*x@NLdjWVq~Jd)>;PWON{KQXT0k%>4bEtom6}wT`|Wm+ zwqVTQFI*GhPEFdv*fG$PvOoU;xTkb%=SAs?XY%oE|5XUf_@N8K|78+uiJgc&mL+k^ z2S=-nWizg)1?!iV;is>nH~d}}da$Ftf^P?VP*k%|ny?GKRlHO{ZsZ z$J-fIIiT&TZACLrmdVe-sawgF@Hb-Fe3aK9zXQGy_V3Ki^Ujz5k-ck-_NLV zxwXqzE2_}wazE`C#O6nEwNrMZZX%=kcP*&RwgY547$M4EG?}0*|H$QTff$r*kqBGH z@PFEoz5#=sr)4|qvaLYx{ZC6dB=5>W6{*w|2f$o~M>^Q|)7ox@ct=L}uP7vq6wy$4 zs+=28cLZj)SW#2enN#kAKbKyF3_qF@IqQ=53_;h~VY_vLe!xFb+PLd(s$lf63_rV3 zgT~@5A2^U9dmTB3v5e%$M~Px}uB0|-hIQDp3UFmBdvc#%!5jMDeJ*3VheM#v{$f1w zEaT2tbza5~jd)v(rF~tVUcm) zM)UWGr9%J8R(!s##Q>C>F-CN&(l8kKzG<(QJQ&r;GJ5pa=pi=W8JFFnbN4URH=}g&0YG73JSjP0XU*;Fo2l>P^=FMJ7mNEUqFodRbxIdR( zWbF3OE^i9R;CF1@-lYS(UI)-Aj2YeYdTojgYF~P4dNo>ksv%fjVrj@f3%O;~fr5{G+>4B8=GM(*?Z+JG5A;d!gSo`LMc^7a&rNo{rjp@IWMo1 z>A+=FH`u!q^}qI-4glKzVI5U58QrZPPc`-(Ju@%2FlueXpXha|zpPSjolNbL1KH_M z_v5cm=0L7j%#0DJYmDON^W!4T%4iv%X55gzS}lVyOafNCUOgYYjma`bk!^`=j77B0t5-hC~i@~E{u8J2NWk{Ca1R3fAt8Urnxd7oYAYm z0FUMNYD+?8k^%gk`eikm@!ZM7}e^!;h{88HeE&6WZ86|og*P%4{ZCD z%N8TM0&=ms{wCWVGOhMhTMo-uM}p+d*$p}j|IAR9G2Cci z`@j9qqL}rpGe87}ebk?-CmLzmtK}skIzn5>(2V?&f6& zU7pe>hGO^FMGGmfj;JAl)B9wE^afZV#`M2oi_B`;dnbaJV9Qk7q)Qk&iC!Q)*MNmP z0meib#hqPJ=*sHn+2UacTYybVcObt3r6gg)9FJR2|7{t5UX~7hgeEj>%a}KNw@hdV zUNJO{$u~Zwa*K@%>`gMN8|VNWKP`pi3_g@qjePLvVllM4hBkbSm)kbAhJQ)u|SBH5ffwIG>ZVY8-M(s5RdDvjOZB!|E%IH75;_%6_i4Fw zKCNAJxz1%&cUO8bWbA%k(@X?i7^K~aG%Sdy*X2V~TCiCe-A&F#H8qws*)$_rwIx0T zNKL?@1S8c`VH}ash_sC#Vko6^|MwWm<+M!3TbJP{U4vBeeSY~_P4@391q6l+Kka8{ z?&2M3Js!6`koL(y3C`^nM0HxnqGZlQdQH}~;L~bwaRm@`cvW&!E$iNw#t&IJbv{jFTSb)kDPF2zF@8NNyN? zC)0>)QlT@8yrc&hqrSv!&qAiqH!R(<->Im&R3M+~mjxa} zBRVpszre`MZrSucwm^YjsR2L40o{;ZzUDp68^fh@8QC9_gJn~rX-H38E$I-XG-~b} zWvYi#b)dor>8uRD&?&QcDQ+w~iqe|J7~F$I<{56{aXDqsGAyIG5og@p<epB zreAt$=P)i~PN=wT1zU=e{SV93?7jo)oX{C?PN9rtkzC3e$$01-2GuqYs~EQS-0KPO zy}*QmiK@ExXNe<$AT)YG=k2p~svVMW+{&nK!8Ne=X+?{P+?hl`^yL;wXCMt&*kq|# zP?sXb9PH;a=?PPAvHvHdW;ZC7!s4Uak(2mU2iI&?j#>Mvl0R-6#NwPDW~3kB9Mn3N zcvC{r6viHa4Pa@yxgF9Wc@Srm5HkNv8N)3LNe}j22Ex{u(mf=STbuhoLo$#lE zYu+GooicvVpHURCngW(?R0<;&OJuNCdThn}PsNQ?r!l84!_V=?VE;P{Gg2P`QBnA`OfSOWsRdliGp! zi~{6w+uJ6n7D&kLR-^T6#I#0_BrzTY3`2j&_`~cfvA;Tj#*S(sv26lYLl_6F}?ANPc*b_^jUw74f*8^rOQvhQB^S zCfPR3fZ#-n*q#=0`pht|uvq8ALZm>9ijn#dLZQkxCKQZ8U7I;arJ$MUXTY@{6An76WY0D@g_VA*-mE**xE9h zd%l!teq}vTMckp@l0{bZMJ(+pFoIp*w&w~5mkfws+-^m^u`YN!pejT%wBcc7hIUNs z{?BBqt#nkH^D_JtMo4UZAxMq6d%;1-1hG5s#;aDq2m$4J*Mqxw-v^I@{% zaFB=+oLHI{hkpj4^ea*w0VbNZjP4#SA|lCcZy=O=)MWzSl^3NCAd`cgMC=)~g^c1? z2WC1cuS$7FXr_pt*OKKSeqb8={lYjvj;yi`hTR|jmCWF3Ur9&_Q-w`vaFZZ+s@0sN z)`G-BSsSDN5JN4VM^#fH;-cmB2ayd2BD$OEaXp*XBJx5*O@?0!j4wIjo@-s#`iNqN zs>prXMj?YdcP;Z>x@$4ITT5aDmg^1}BfxD|Z;qtbc2+TR-tJ911LyxT6yJH>GME=v z6&K7^(r8Zvsbj$u34FTx7e zh$wyHoRHxsQHA{~YFv53%o|qLPES&q0gbam4~1S+vDYC(XdSQ9`d=%1a?AexD5aLa zFoGt!{%943OHF7JnbM4xQQafq0B;|KH{cRo3U5=oI~@=`H~2$yHUk0>fJ-pCyZEIe zPq42B=Wtf%TXIl3By~0)E=F@^X+WII@YCB+$9os^j%PjD8ltKqWB#y+=WC1Ul;#;D z8fZ|EoU2A|YbU7C7sQ{3 zm{D5jxzE);6MThy*(4y3`xS#w=&RypI~E_E`V1HiR1QF>o;b#i4|E2`GO`;FJH%N2 zriJokTTInXMyh4_vGY(E$GP!W_Ad3uKl_jA&@}+hDhoVM3pXRQ<}#AIWB{mXb++ud zpYXrX*s7GbxQMDy>W_x&v}jVCT{5OyZw3{@*7l62?H)SuoK(ayE&fepzU~9c?nAo( z(=z<@kM=VE%fjo^VIm|GlUssUHFNU-;5n6Ji*RhymcESg!#f5oxOo_n?o41vY~`XK z1&aiw(^J+oZ#B_bl;P(l91P690#mP-Z0ne-S4MLyCqZcS+C7|SMa>jR3q|-7+#^&J z_-VB39oM#59Bj3iVOL(X7ZER9>a;sC0<*+O!GGl;Ebxk&e4<73HZqA4Mu~2G!+@;( zwV3*h4Fey9TyGivT#KRD*cb52lGm<29>vZf*1)8ZymJlMZK#GAMh)%}X}dQW3f>od z2t$cwhW&$=9koS|6pDER)H0XR-E;~tq-}Kr3uh8d0@Mvk7Fy}g0z_f7Kga?J-q_44hQQg%* ztsT9zbRHz3c>}sKmXZ9I4-MxRdYgWn+QxzAMTVagM9Y6W4G0y;>59o2eFul|RQco! z%}E)lQg)-wCX5o`Tx4W-0auNpk76uJi%T)KNI+pL z#$NYb3o)U1EhG8QM99#~hF@`a@<*U6;8iWS0OWSCzsN{rk~0~8&?NclCeUtw({lMm zpq*KwAZNMRn=e1M%%=sfW+0g8g>ZG65(~dnm^Wz3{RG|l}=m^zp zLP+`sI>T`c+)PG^ZZHR9urw&uhoE4XH6a#qXbk-4uCwA)-0%hfL>$Y(UvYz^e2Eiw z5&;HFEp4|bLq`;8M!0~fvs*4gT}}p#D6iXZrd`f~+=U_^%lP3yR@-@Dp}I(nkQk_N zcJS{&@al}d)4Hu-00gOt{tJ)2S@$xAq)@zOp;8me^qeNw@H6*5EufgB&oYL)jYpSm zmq>tl5!I+fLO<`6NS=;Br1IH>-jvn-cP%XCuL*p)9Jj&1^^9G`aE+_g=x2bBSzZFPTv9vo<0y%#(9xm_zND3T7c{Fd>s(^NBWL~ptuu!>ud z9#~ZztM`zl4R}LMDmsd9+lPo)dOJV@uMJ4sIuU=wCo-@?sE%881I`f z-?D~#ikCsDSDal+m*dd_2nks+`qKg^%U2*r{HCb^3I|M@WFhM{+1ek+sFeVWk~N~6 zS7CfZTK{NUnIEqvJk3^tKnx#h_OZOAcAmk@j z^f$+c)N0?vYtyy13Z=)stsm}(R^F$Lo+5^Mt9D3&Vv_a4ng(m0_9u?33@9BXo@rXB zMe;wd=WUibsC$9c+`yIrp>)`hogL0ec}bQuiL||?#GEh3ND7f9%kqOg27vR|S*LKV zX;kJy*;exxT-*4J9l=mVH(Fyyb%Ek+73m{h$K`~#IBzTa3uKM*d0LgKk_kO(q%9OR zlw-NAZtCMW+dgBKa#_VKmIdkidp!Fjq3CLbsltt{>`%>rp65+xZYj3NotTj?8hVOc zy#Lkni8FQdRJWD==VgcCZ3BtwK)NKuQYpD+Qd31W*XdzbLIdo%tmKciD6zh04%eHm z59`1V)kl6<{tQvLq1n!mITt+}w4N$mn zz{Fp-T4a)_V1?Kt6$vFL&}vuRH-~mHllDC{@=?g+>`H*2v07 zR~sc!WxmSJ5stsT(6RhvR)c-}8s}ZPS`8sAAX|l`)jgHOblyAZQ9dViwWCF-aaq-k z4Y#QHUCio0h~+L(K9-gJ!cvTm>>-Er7Y5}dh8+6L0ud9C+)A@{gavyUVh}KE{7`?O zB04rH12h)Z{%DS2+oe+4;PW_@C39zgNJ`hRiXV_dT&_x*z2KxKAB8kPdPpoTvgUM- z4;nY(2A9>k|ADCwei#mi+P|=tiA-bufjq2NZPwgPWIyV*(hqB^A8nBi*Qx3bLE}f3 z7u)j5ht}6tT8Ld!XR`Vae#aN12l?`go?_b8aLeG4;qFo?1blgQ%OY=cmr5zDJt!P= zXCc-iAjATO>vW9N(rZ3m!sWPSsM41;-8#EtexYQ1om##2Cb}nC!_9FuM0~zsBFv4b zIvXUwn<+YpOy-L7dYwZdhph3#o2CX|cFD!Ux=@P_jv_^y(C()4&mQib`?_x{`|)g(+SY=g+9|XOEp+m0sPwt5dF#=%_N@MAM;As(749n{N;TD$cyCTJvp4wwBahU+iWAI}_ z=lB#L2suPO1tDxst1iC!&{xhh2t8E!!160Zz{=bf&tu*lj#h+c5a4$#owO@U91+d+ zwyfbVGQpnw^b8XyT=fhI!cNcdDqo5yNSoNK9NibOE&@$`AbSp+Rsnr!3#=L9YN#B) z4e&+XR&(>pu!P!LS`c;fVVk{i@q|}oT4%e-dvG_q)OxT+a`*7;F0z1q$J1z5@<)5+ z&;%CH2B7^cpE-_uuB)1-DJFL{4~ExQ_IHb8k7G;V)jgF}x_2`PE$~9Xd&gQ+xRti8 zUq10SDE2FywttC5!FgLk_B$Q-_nG0l4ln^Ps#1(q+>{kU-IiSkAbLsy5rW!LfiD67 zZu9bMtFC>l>SlJHu+Xjsv0eC6q$+Y3vPNwtuo>j+DJ;Y_ z!S?~DrVEl`x&QCLz#wVNAqd5YmE632aL7fC!Z!O!+y%p*!Ss0!OZ-5!-Yq*#bm z!Vhn{enFgZ`dgGc)@+xo;%+m6uzPKO%-e4t;&GBCys*=6|AwCZtm(**#7b8ZYIpuG zJig#kJ;$ZF8+nhcQU3U0Y0Y<%l5;UdkcDB_w&9%a#Onw8xx z+X-j7WSi)TTf(qpn?M?f3^PW}(&gK+?Z2@te@T9R19P9((kjUM=4}l(CT#-rd%GX5 zRsdB)K_g{VKiSVrUrghS>w#;laXls_5qBp*VBoiMOT9jDvj}??S(+WvZguTR!9VPJ zypCQ-RhjgM0Gpc;L{Bfb<5JejqCnuTFQI{z>+ZP>CF6D-RpCp((T<^hUO0{|2hVG1 zndNUJPBv@XDI%(7f)Y(>M%Wr-yrKSkT#gbqy*4#v|4mHAKkrvfkjo#*#;4d)EbLRg zWn7NId(>sw`*N@89NvZX(*49U$5FSHqW_73X}wR>T^EEUXgd`)E4#(EkqLii6nuuN zfuKh^dE4sly7(0Nz}%~P0*s>cBF1Msw`dxd8;D@;dJVb~vHZN|8tDpRDFYZc;p;^K zCkGLFgaRayQot2dr({RSg0Cfr9Q_YnznNTVmt$C6iYzfbBsNm+QeZzC}7eD zqF*fB`Tdpcf82C6V2vOA_Fb{1b;!WPD%rvhbV{~Y+LRJQ?0H*$UQkityfJ*tbAq5& zQ3Dgx8wF+&bx2pj3%{0Oj4%c zKeY-pM4Rmp^^Q#ZQ6>pg%+&j9^;u}nq4J%OUlM-)Xu2ZwfUtqKCgvkajkN7tm2>ON1nH?J$DVtxu{dy zB(7!u0$Xd4@?D3Pomp8M7t7C2F)Pz=eeEPfH-I<8-C&a$SuO$G%#Y|P@zbm)|K2{XfVl_8&=&awUL!1>|K&NQ}0js*1pe)V*Z>SM~ zG*ISZ9Cj^=Fua5B<-bg=U5+iD?b~X}pSW=C%?-MM?L^Ug9PmgmE>`F2RUXF{U2BzN z+5PX|!}A*m)Ag#8MPchz!^G<*EaD$u^4`NRj8qZLcV;L{ptMB`?ZDJoa2oxJYP$z+wm+KQ8b-Yy>|Mw^FmX+$P4EH>H%yTSi^4Tb<-H>X`DvL z`4c_rpAr1Tr_bE^}cv~5j)15*UxLLrPlJB4gT4Mf$@ znWnL~utsNE4W(g;XD_S%@Wk^ALELn9aZN}Wm2FM`qVDgp*7c%okCmoQJl1fFesRf^ zv6+1kVb#zwKc?-=cwF5qN_K!+mZrJZ>rGqywJ3J5<_{0t-XHkTFXPT`L5)t; zNpZ$~PQ%pR<4zD8X<6w|VJkTNqu&1ZQiCAn~{j8cT1UP zz*>AYU7Fp|t7wXq{KqBKp0CK7t5s|vWf5LqR&%SoO@UeeZ}!b=2qG%fntfY-s43N> zzCwWdXNN}-%p)uF?^Hi1W#%gcXt|Ch9FFBzdXsYLtK`}^wFfTCAP5;&c2giQrSmQ` zdYzY+n9c=H$LjvV76|!w?uE09Eea}{SCf_e9X+nT7XqH^Mr_)aBgRTh^v$9`(2f~4x_8?ON&`M+%q~~t2 z4<$kgp7U?VpiyvwVK>ouRR&)q)9ntR4MNxGmU)ZUJ+O;aRU@qbh-x$%;os1`8Y70{} zj0$83(nLRTl^@!emb1@o{m`%lA^%!oI=iVez@+jHR`LTcVRL`g&$=2tJz9>TKnH8O z`FzRoQr-kEoV-&^(F4`xL{m}Hz~O%45tCvqtmZFm&GBCs?-E6a20LRXNu`F^?C2h3 zt9KmV;ZoE&NnDcr;3*OG?;wu?U7}NMYpV%&5mr0tx|zB~NJS|kR`=Fhm@fP;O9XJGN-_k(!Qn>72imFr4+x>d+u!oGhBv&dgv({5XQBxDTRTS} zMI$S2J>>LH!38zC#nO#6et6YotM4&{(3lm1Lu?=ii~1e|3jY-3QNPOyFR_}J7`0L- zeaCxTD5egQtZi#VZ^}e#=()q=pv-khl_NqQwU z3HLWnDJby4a)U2Xk$n|ly34g)+Lh}Q+p6{|=2Q)qe3;j5X+cy6R1Wwm2)R)ilQ{G- z(N4=+_1Uqyw--=}H{R<2R};eAHI;v`dh$x2gV*`5ENEV(W@umBHc^#iLWzHNgYeF; zlNw2mMSLr94sVuNX~MsEsLwdFZ6I6viuACW|HM>w_Li(&t#RAMan0pnxobU@Z~2Zw znEi6h^vlO;-f~_=ws&)ccaTy;(@del&w$kM8UZ*ni5#JI&3g>`xy}Eo+b-DB*UGJ| zf^FUeXKBr(UvHYxDYXEwiWfRnndAJQka>1|v_*r9{!uE3w+_&ir+M2sMi?mO$hF6}p z3dNI(0uZR+8>z6JVR+y^VG~x^|44N;pZ*FM=;#Y zWJJH#HZlaNB4TAPB%v~Z@LKn|ixHM1RtX$owdjwn!OO22Idfd_F;XKJ=8qbAZ(=IH z{f;1XK30kDQ)EeauB8oQSrRuA(^}$2N?OKOQ(%Zjyl$&{Yvh&mzN|tQl?Qmf?D(>a zr|S5EPUPQO1c!RvPh8vdP8U_U4x8BXC_yARLs|xm$(3n0MTdXn(AU~pr?;%qhgtUj zxnFgTA8`~5q$@8LaTMF6YS4!yutO`C<0(!9SvC4IWRM48$vccF7Am^bg0XgBDB>cx z{KgPg*o9U7X&c{Yb27y$LL4}mvSb}LC)2#$<~@3X)%+m{XV6^IH*M$~nwBSPk1+IF z|6x$aTM>9t)@Rzs<+r}W)hrCT95*h+Z4ED{YbBP;byJ&!siTBgtBPHnZZ1ubd_VDQ z3!rb7#kcM~ocpI~jFg>5Yy#|kX*G?fB#$pxz)WGo0?e{I(*LT*7Xf`gkpOcpZGB^6 zP%j=qtl33ti!G!YbzwN61@YvkqKoqaQX{C;)NjHX{zVNE{_SGw*C$50Y}Rcxe;`oe zJB!SPW}1-NsaZWAT$9f)LWylBFb#3a$_zU~z$l4KO1O8)XHw!)R}JfjFU*MCLc3C- z=8CF1Hb+T@S)|2J%Pv zi%oUu`-#y>6+Hn#xO)l|pv)J9koQTAdfW)xYF^U5Dj7Smn?OrYg2cf7(3YtG4Pxq& z|Bb09Q`l=5h4Ey6cnO?B+t^aXis&mhu&zoNH`Z-`Dn6DhWpVCel~UciSc=FyD^C+T zEd-K#USR!P>KgUF99u%H`~_?HYh1z{&eg6C>XK*Z#uPRF#f;wz?K&;m3@g$??aCkG z)o)sg*QnftFj(V6SlwSQww3X}#g-k?tu}HJ0=d@oG9M5=_P7^rZY@$;m~& z9g!go>gQo)uVAvYe^S{bW3f>$hy9_qqLC`VFXJEJ2OYP(E+!@xyfXF`H1<0b^2!h= z)F$gDHmmsy)wO@&cs!07`OGlCF01-WYt>S-&sCg~Ma%5nCOREk)G??UUdrXTPe_Kb z?3nfr7FB^PU!;9|J#NK$)wfmsArG-b)?u0Hn4&Hf)k+k>6#x`zm0jmF+%Yq(A`sV> zKUK4XqDyL*d#IBtb>;$EP&7bcmNrSe9QTxJ+gA08x|m}i0DbKz3QQ6l>>)~t1SuVY z*n@aYkoK#Z2q$!KODUV<`~@cAF!$n4|3}NpUPM!cf~E?^4V}uMsaP{pzI9zvO)`${ z`o^{vr3$klI3=#eX$nYopjkfXVXdx8uzBS(Y26S7F3|owqq6U%1O+ zbCgx1m#7eZy>~{)GxjQP%tFg*(cfYdTit>N#3d4d&@eaj5gN{y-wH*>+}7~2V53Ly z1srl-o5}8O1jd$?y+bcG=3<~4qU9lsVd zBgi9ftNNSOJ$+NkyH3k#SHEcOuvXE>=NJT6{=j=QKW~R5%FUX-S&|dsde!i~uDjSG z>L1F)K*ai{umf-?_N&Zq3n7GLW-f)(_zaX!+L> zka{^THATrqVHJOX38Va*_Q!QfGY6rgR95##0G3!+m8TQ#^5Q6>KCM8rH`o#HYsqX0 zge=R=ieQevU}jF^_Pg{bWM%*LV6W<#E^3hsiRmKcMNAiE1|#lc3jvPhSW+DR`*7q} z9o37k$6|dEGj418mo%N>7i`a|UE*xO5xy+p_ndC)7tDEA;*uCb#P$Ib;CWnAZ-bgNyT zxQ|#M)tA-1kY@C%KR}oHmw=)P=+cSq3nL0N`>swg^ixgb39^d6{s3Hl>8$lXi@Kuf z9bHNRma!$+TI^+9=k%yW)B3WqmnNv9&eJ4|OfVT4!Dz@Li(+p4eM-Xha%?fu`o^~4 zgTFT}y!=koEZc?h6Zl6jiaqR1l;i7$n07)F++jsGvHL>ls9p>DL8nxv?IT;*pKr%2dY9#9pfbnvy(NFJTkLXMiD_HSow&pYEDxn>QjvuO zyb8r;m!xnNhsWNYcHc*`io0w|<8WytK!M%z+#(73iijjM)%wHbI7YSXWpyuYZ;cv6 z_#~%Ik^v3k;2=TwX>nG)bvVr(BWrnE*_{ymC@F$XA zfK{V+kgH0i_mzVxUI%6cc=@rU$?0?)zqldt{i=Hxy_qccWHTS^i*PGnR}-V$YjF|S zdIitTasICfiI~_!wv0#}GJ|nMxE#gg5Z5I7A9<9~L}Q zKv{>Ec{}c50exgmcL5@bQhpKGg$NN2^yU$@TNRxYoc!ZAuE&(s+}&~H30mBOm_c)0 zE&kc*F_UUdYrOUzuQqm!1wA*mjw3=>a6*qtz49$DDI9zXoApBw z0JZ2V_r+D~v7pj2$F{BECC@X*-zZ^R33*{)zJ09Xt_0X_{I9GCv;A4#Nh6W*YEqVL z*K-%)*A?j55!$qrWx2&p%<&ftHW$c+;BE-{Agj4+@>CPv<+!ibX@TKii7}R2&&C|L zJ;;St;ecJ1L9Wh%W00#wPRx33r*7v~3d<^PZZ%==zQBE+qZ%AtP$v<~Uv!ZKMBQOP zX|(9=HV$005*{1Mo34ZncU6}nRvYdUlknnAr0Ggfkq*y~)x0F9l@j#(Zc6t9cccTh zRsH!Ir1Ec!!8u>sn8|Ws%dwI_?txVPRXE_tj!@f-Yd2vnk`$gajRtWup7VnfCrJ^tO10a)s55*MeH~o3q-bga&=2bb>tji7m&%#qHqjqc z+vn=y--K;DK_%Yd{y?j!7obd>5Z5+l;HT?y;tCD^qdGG{wMhy(e-+i~JYl1(c4DTW zV!%I+M_)*?jH;D?I|1_8Q^rAf;lgEs7Fvdl6511sI4{Tc@5~>oCcoqHg#`K4xUC$| z64R!Znf$4uMe_8HL_}dn(fYI&OIc(=D*}+1J@L34Z%rFnKg4>L`S|E zEeyB2qmTMUymc3C8;lVnEGzn_KccYmyGb75L=ZDU6t91V$*u|zcN{m1I@brLVeCIW zAQpQAex@s?Zr~G_lu?hHQs3veyi)gFc;+@Ik;1mRzmjN&;kydxm63PYAygi~>TYU; zC|>!Os>>AtNZVeu4{6(biQUYvosO$R&QV2jNXjya8|`}Nb>%5%Nn0dX7ubiGF#3}< zz}aIHyTu?m8B|?>b|%1FiH~?ydmypV+$UCv{-R4|EU~ShtEVVaIq zBeG0tD=*7US6HDOqA92g(N4f7vOuZ}f--HUiz{ieMQ3lRY-{*a2oZd~#s9MklJZwZK2W7nK#i5% z=xs(Y);PrcLydSYUbR9?1^~Ox>c(JpnlECKv&(-_ z=xR%u@&3l6PR%0%qUNo;9moI1Lc8*5IUfglkq|U?M)t%KeL?hwJ!n_y$t>}Ncpax* zJB`Q&fybnFTASrFwIh)M)5pD!XV3)WvXUFK&IE>~;j8Im_g&C1#0V7+UzvKu;PEAt!L;%jwvaL{#Go50xRcxWh|mOue!!%%f(A|Z(i zxq#@_|K_j-na9?Xx)E5#P148*ejl8_I!<%IoG`aF+(cN+7rw&Bu7dHT%p-AT!mdWo3U8WPHN~ zan8&PsdCoL5mxo%14sM7^g!n^)(K2cWe;F_fr8T&2;i=02n4JCa68enTq~>Chh->& zMpqka0yc;)^MW*)JE%L$w%lTG=6HMo4G7n(9tq0ZWsTr3kc(peMKfVuZ+egt&t(BF z^7@@(A>wvI0?dv|VSb?yWETTG>D(JB-_JZt5f}w)1a~Z8Td7NHvhp_|-4|Z_S3|G2n*D{&t z?b!TEY8I;n|K&vAM8yAfAS=?%P&ok^s(Hk(Ul35cY&YQ;Q7%-MG^xI9F6^k~Q7fQ!pOyNX+Z7O!kb7 zCojuS-;DzL>G{wRQpPZ=t*D+oesnyRWp-_*kXw-`XgrA%Cw9|M}wH`6}pT3nW_ zX*N-oKTS+b+Uod7Dt3S`?&=DNcEn<7Dl6^m^5h0<*o#|Xd>CfF1 z^%3jsxCqxSYs;|t9FJG%`ncV~+WE2k11L$b$IV#W>PA5>1;xUQfS9k3>T52MoJr41 z?BnjfFeXSBZ?zONhZPF4Udkbum;YM)#|ZOQgo6>VWv z{{@jz-&X#RV7%xM+^gdy*3kx?%FQ}z?q(JPrYt|>xn$H{kW>d)#BIn_-L{&$#|54B zyEx}jx3O(!=}P)o*}sRCWd?<{wn}NrQV_@-*Yui3{f9BoytSdhYFX3Gv!3i;`GR`m z+Dm{xbKaJpE+8Q)^PaXG$A}Fy(n4AOiEhOjFCgwc7zvast0Yz7p>#W(UufHH?h9rF z5J%wWha{N4L*dnXy&Cv1_CZ5W<1L zPjwdylg{54=K4>D!n+3h&rfp`AaJIBoov%DZiLd6!8!NY4_CSvAF23uYDXjefdm+I zI6{S0{d2oRsXu!G?-71T{dBD?(gXXZtdPkde5*X|?0T;|My8I`V8XDU;^u2dm9z^N zmBc4uky6iS^x2AP17yWGGSF}W({ARcx&imVBv!+DK!=<2%4(&Lik64CBX=zjk43of zs&=B+<9Owg_~?jP;1mnAzv$xmZ(SQuQHFwmhP83NTq7m{lRro&t8o=SiXS5rt%6rq1oO z9ev|5sbHgTjMj+sjk9>h!toefn8={!VOrwoJE=OflYmiyOjqB%&HY zdIi4l9r;+p zf1k>K77}B{qPb72C+u_DAG(6+z1+yNIadn;d1(3sk<4Hk*HNe(vL27i* zD|5fRcj->vi}I-5E&L`o<&pi9EhKtmdONw0C1^FRM1NF`$~;GJ8ZpDX&F}Qbf~d6% zgM~0()L}DV673?YN5iGupL9?c({H1S>2=z^z)xIHN~%5dJKch# z9af%GLP046NJ>^@>W+|jS8v<&Qvj6H#sCw))sK|`WuEtWU!hnNFh(6dL1dfQV%y`i zSZF`>EBJ=fY5HPz^T~!mTT_AKxBu{ZvxO(SuwhXvoOI!+gEvgMNp4SUT2iP#n z+btzYvE-f0C_S$iZgNZfGtA`49j%OSW@4VIQBHkbhIG*Vp|*X*u?~lUe0JeVu?r10 zg^{V(>k2qd=N#M-IRrn+K1jh$#}QQISacjkRacT^)r$M)mcdzJVA+2C)T?yM^Lo9( zVnBEhEITzrkMjpnDa?D%;gGpyL@B|{hTG}2Uc_WFZVyFTdfhZAM;Am$W~4|D(gd-p3iX_+FT=C}GQbR1}}S4?@9(Fh2l@Vm%OoKD++2r_P3cOZdv{*}R5 zQ-S1DIZxqvy~HRq@9p;oNXsODSLFDl+z0LcsFz znV5BH{PyIYB_Sn!*XVl!vI5X9>32kTWDjA%`&h-3fR_wvD)8Hqn>vJXiuVNkiFb=7 zZyD|lz)(ND-ukX{`MF+-#oQq4_#N&+P9}`r(>uV0kilHihathWx!v)e!Khf&heY$=;{BU zzXVHr;Tm<B|x80>=Yzgq1Z{1BR@N4h5?MCKn&w<#boH##JAt6Vb85l zCW;6Y$|l^w{o}LREeHDyzuAAmSX4XIF|}lHiV<_zH4aH4NfVIC@(hLGGzsU!ub&z# z1LI!n$ZoR+(FW_tR!-D9%Az*N=Shb}!0Xpfyb2@4yFy2LuoJPzZo3L54ZjjQ#PMGY zIzLYBzo`IpfXKR|qf80zRXciqqJ~;5yMQXyew+U;B?fD|&XA=ApBf`%wu`_ET8K}b z;daUj2eBF4;VyYd&ii7sGcc8v|1!12O+IwMKBc*8*J!cKj^FM-8#Gh<29ta6DHX+m z8T32cRWcFuy^el7Wt>XAGZpgVRgt{|f&0H`?RTR$J5v+;)Clju%3`VsoTH$VJ zJTwkpY?#j#Q+v@>$ZvJiicsi!BpTyHC>V*x)sQD+ls5TugIjpo7;xs--~F*$<-fl2 z!%2`}{`+K<1~N!XW?B=3;yHO~=vl^Yzd1GkliC{1`(6W`p=oJL8tM``OPYBr&n~qG z1y5?fR43g|=`k&I)hy&_kUe#U_ED5ucRo?UAL>EJ>P7i{T8!J5s9L1|g3@~W8y)eW zMtP7b#|KiH{(}XZVFZ4QfAQw{1@~f4k5ei=RlnH{w#*iD)x0Z^w)HHZuV~gFc3?3} z?#dgUGETFgh>0qGn|nNpIfk^j%j}Bjf(7P3@ssn} zpVa;*CF^(iLlyS-8}|IOM_Zg+1NxnAkSE9dJ^~}O<;=*~5!hA%meK#*u8^$36Vfxk z(@zt^;XalCa<|}`Hq$_q#&mZy$TlMcm_U+j)BUMY)^gG?$rs#VTX6d*eI-a^k zp%vUhgTSV%Yx1lks`Zkr%q_Tyu7DV|g$UDTkAai*=FGMsfb{*7b8PPB|Wk^IGYhfIKRaWQ^|@>-h!3$ zdS@zR=WQ+lMX%F`o!2hWNtYCM-U=Hq?7X#bz&_1rq`(X3uS>=MeIW@p1*-xOx#O!LIf54W&+ zZsmO@FQ3&*ryNwbGlNY~J>_`V}oW;>VP>@RWj zZ#3~@I!>8m)vq6uBNfuOet$fl)Dp-2JKVfrL_oRj(E__f7w`Q5V97eFWrz>sacT>V z`Z~YUe+o)|uCB4t3?UbnP1J)lpj1a%mpC$JCO_ld~Qn<8p)bI4CF?QA^;R7WJZy!m45_K$Y*8xiXqXLJ|lE8yg zEsOpeMw1C~Hz+{nt(b+1GaA}UIQ4c~5#-~yyP~ z@pUICoKE8___99Rg@SX2Xt#yrW`dxRZ5jN!NG%9Sq9zO- z;;)(jeL#Z0>9*m#JclmS{nC>JnB#v=q`x=qcMuFHiIk{o4%~L4D87%=snKSBtG{ed zVO9Br9SjwscKhR>oyCwbwFSd$4OH)$ zDnRj!ZS(O<+Oa{lL=!XAi1q5YO0P$Oe}0abbC9uI=4hnmHHy{Hz=7?Th5WOo73&LgGdcGet*C`>D#>w zUe4!}wvlZ8>Noq>5y(sI3Cw;^T&a6yu)KgetedRb_T!0AJ_}FwoiMIQwx}A z7kd{lkwp6%yF`VDb_l=ztduIl|1bw`tIDq4so&wgObNo?X^o#$cos%!i+;14ql--G zjluCj56_kXI_bB%2N?=|h_d%fSl4#3O*$9(D=^z~<%gC(q5`Ae>V{Gj=(%5s8=nhi zc9cnmenl(ebgJ%-0$x#Ga`KfL)SR_18$?)Bj?dBB)bDg(--PF_>@gABn28Q7brkp% z#P474YAd=zpixm3l3bV5X@5tWK3&8K_qT0ne*M)zQn8(WhrckP53{T&E z!g+)=38Y8vY9PhycUrIqHfQ%9GB5gV#alTlnv#86MxO_bNLo*2FjpWF(n!tJ{ep$hePfq)oUg*2Kp>fnZc!8cUe7QRZUESQ-cds$$7=8EfuTa41Y&&%yh z?opkRKKhrok~57?>0f4nB&C1J&6+}k`XGl`e@XdSmd)G zr#aJrl;Iyig;M*StiE0!mMgX{Be`j=i>l~D&uaUHqEWJoT|CDS9YX(mu3F3Zx@eKj z_~iwI-HWUJX2)_>{nv7HqK%;{ZMYzP<_xx#ZFD!4c!574FUefW>l*FI0pPu~w--

W43j)@2N6)pg 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

Q9+ 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 z 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%0D^{~KrmJ6w5 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

u@ZoaL(MEZ0xuEf^Og3PF^GT?sGvDW_fB#ZekQ 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

y=0>$J2 zLQgJK`(97n?6+xdqVrjes^c+C1_XLS;*e%G5ap`a#ga?=H*N?;)qzxpK3=#^!@~Xt zuTV!u88fAoo(0V3_ADEM-H=39LiM7qzzy>?$=u6pT}ZPN#bcMBs<~v5c@R*NEJ?MH z))N<0G`{5rQrFIc;hH%A^uE*V=V zGm^5lR)Ro)vV>4PFRP=nHl0ck(#XWL&h826PgfM7Ek0=bfh~<1r?esO&f7H7DC$Go zA|>cpkac?>a|Nm6Fx6Mkk?aT?O7_pYw+wH{Zc3$A8fyOKwC3&!DXUzk>=_}XPqLbUV`+9pxTM8Yq(hsTGq4! z_D?DLA=-)f#j*DtCexp`Qt7p<#1ST{=fh_b<7ujqQ$5oTBuR{7MZ9(vvP)$= zZyiLX(}m+VojAnT6I%pd9@LH%4sn+Ff%=oyy;MmTWqb(g7Z)PAe66!CEXSd0>pD5M z{K@O#m9p4khzL(~G3RFo!FLm>t^2>Cj^`ef&+BNODco-p@cqC&)I4?;jHL4}thXyT z$4Q+?5@gOuSlXVZ3mdEEzVdqFme3G#6ZP}CJFnPv=-0#;k}TG-TZQO~BT{_1J+Ycy z`SR8Tookp?<{hX&>P=hRj%$u*xRUFziM`%7A&2E!my@QUj!O9X!WKg+H{baDOTLkG7QB$Q9Bkeu!Y0Yld(LP;vD+@VM_d_7+*rwwpuA6=#U1bi>;+O zdN&TORwLIwFPO?6CE7d=#Qmnx^PwUvRL)s#Qi{&wf$du&=gxo5E(L9^5QjqNx(%C> z@IFzzSvNn~u(uGJ=$33)y6a@ag_*6TV}SWQifs?NAR>`?#5}oesZ>koBQ6|mZ0_2S zp?}po>~e5S%MH{ovIp(TB6@Ris`dLnJijA*&BHf-W&d^)1>My`@w^?3lx7@WJxR{S z@^J|fCC13jtl~ylNehRiTBAb!yz4;i;x#Osqk6O5e!M(}g^Q+S*VgKGPfCm*6#V&M z4_vBm4e4j*(KC^q)X@@Z=UfhGAfH_QN3@PMQ$xpRqH=LeD+z1*hC@&+Q>JAPiE5*E zvBZ6N4~{G*#X|Z@~g84`hGKi)CS9)o~eyg4{d;SWVvK zna(9O>$;z}dJ@%%+Ocy_Wf-HV!b4maZ5`TJ7%0Sl#df%4u6Iw`W6h`AQ0SrDrt(TRwd1r zYf=XpC|*=7v-@Fe>|wE3)aSf>!UsBcy|2WSX^c`qB9y!X1>rb^rJwxI?S=7*Zxi)% z{R&J)zOAVC&I)WP@!1J_-La-MhGzd_nZg+aPAbBugdGtMswzSEw%3hy{KTMi&KtEO z?_bj1l7V#|+Q*iZQvAp8vPimcziG<{M|T`l&h;cX>Ax-L(_T3HJ}jX?7mYNp;rEZ; z|0B)IYH@0ngUZG2Pgf(1u0s(E8Lf~morjKeRV|N zW31XaA9g5xA6mB6$3z3DoJ#?CjShd<^4fpxS=bKnEDpTT&5p)zvQGA@#nEl5B^DK& z9<{{W_rlo^w{lRrIJD$ik;mbIyu@_bMCu~(H&790M;?)}VjUTvc&tueRnTtJ8!Pc; zc@-eKvcyzGq<3p)*^X;YmjWmq8zkDgYMQX85oVM@xc#$bN%9JGj4C?y!}r?ACXQb@ z*A|YA05l(%^DOe4nI$n)w@(H*SBm}Vb<`dP`YTEqG9Wv z$R{#@X#o$^U>%y#57&jgvm5P2H&N^7ho;4pMMZHEv)tv$u2LS%us;{Hmr~mcr!;J? zLH**IsQw4Kvp z%1Tfn9gLoJQv3Y;2&oV{)0jH5R17_Q3dWcV7Q(+q8GO}xERSZ|yib&l)zvF+@=Mxk zai(lB`-Zfk45f3i*-Gyr*4dD!8!knJ3^iE=`KFriDqf;_Bu7-Ce(tAEcKbtSyn|aN zamNJ(isu8eUYwmTC+eLzr8deF1GRIt0xy~MFJ+*8U}l%_ZX3v7%(Zh5#xM)iTu)N7 zcUg7?w%dx@jQfeRouy-B2b7OpFRFagr3!%;LX|~~h?YYuPQ|Ys&Rb#?hLsiQ+^C>> z(c=9$ryY{~Y%P1UO*EIR+aRrWt>@z!jxL~fu7cs!7tWK= zbHOiPNMI_0YHmMqv#)5pY72b*McvfC$UN+0s=7TE>R}%f?bOJ@zH7!4)mzfr zRMGj1OhOYQB2L>+DqbP~%vYp-u%l_qZ`$_v)S|>|2MQO}Q{^H2%-p?kv>`esOU#R9 zr4n&(YYRHWLJ&IlC#|&bzUaK0?qRFhkv2A$p?*)Jx=UC$pQpHpbEp%?BSsC{JVV)=Lh3%Hs#{{|-$54_A_4L~1YY=0(SEh37?Kvgo^yuUn{{m*tsq%cE7?|MD>Q$$td3DzVin zI#^z(mK`Lms$PQ9jXU-tsT8Qvb52Kbw(vr<^JsV>X2xt^Uy|ni#kPR&;m(DkxPw2l z@ja6VWjiE=SfFwqcR(%u6gnvNwQf=_143~1eBJi1DBfXG3$8su<)9&CTerzRd)Ga> zi)r*s(LM9$1588~%NCaeO|n8R<5w+%HyOpR0T)}2LT8<*pDXlYCYSw8UG(fhZuzm`s-Sc7Ul$x(H+T%e2A25NhYM2!n|}$BARpOsyrQiJi{NPfW6`1cJ%d zMt~rMqvZLz@n4ElEixwD!4ewSlwP7ZTtv?+fe1KSh=3||VIUGjkuT$cy#q4tnrX)b znySiNR#(rK>!E8?8;TbkDtlp%+^V!cEgO>DDid3hTNOdv?}d}SU`?QaE)0iA4~Jts zSCdaQ4f43W=BmYLj6M3munzvlsRBnOc^x8q=vl<@kEn9%PRo4 zQadloL@k_GO}Pt0eyp&AgsmV`;jkN+^@%zEXGfS#jsy!SyjJc}hql8AkWOc7|y z6J9dw+g~HaSSAONRE5$-0hy~x>S`t0UUWee zccH6S9UmLMh#V1Vaj?^hc^~{$N+Pa(FYLQWIYQ~2pdZBXtWONkvSOWTKVOiIO;eF6 z_`R^bV^=2X=dM#o_W$5tvkwr|G{@#@avwZjxP03?dcQxXUb_Z97%6i8W>?oA%4&-{ z9w5d!hKzespt#kQf$gfEW|Ev$7)tXQn^o5&N=HG z$+65$of@n;2ILtJ6TQbSqPC?=Z8`gC#1#~Z=jvVWHVasJ$@f>!7t$ypX`n^ftk<9&*okjj79HLPZ5cN%C?QV!QG zn|nc7V{k8I$^`eKOH^aWANDtDWO72?U!R=(}hR#KT-&5skvlqswk8Y~a z)!w2k@5U2bAmb}#dFN41&CtlBti<=;f^9aCAb%tV&rjX3vbK ztP8^KA~>!SU3i$%HvQ&(zRt`3J`-lOI^%q~4Ix*`8hksNC~c=O}*sIP??CoU6R z2#c{zLZ0r!7XJ|G@}LTBEw8Ak=e@U9rw3Fgs_tUp_=`TkdSW|QvUJRZ(m5Rw2dHnK z+Qoqgh(k$071VB`kAl)fS!JN~&YTO6aB%KzBCJbK2teB(W_EmJ!b3KdCw!S3qr_Ev4Ft%0=pea`}io zioI%P@Ux#~rUYSroLVb|D0ZNZpa*neONop~DYLZ}$eNf3Xbo}v5*XPJ?+G$2--4t^ zgz`o1g688WGsQnwG$TkmbJDo`RPtKKB}|whz=c@gg{3T(Ki>=QAb{;2Mv#rLc{x9| z=xK#7L$tJ#rfT~fx1fP;(nNBF&l=_$n!`AYDVK>Z#CqTaH#J`DJBFLYKmIlQj}z^H z=ru{UHy5&Il5!KeIjLzD_UDOlZXBLGc*;|sCt>`zgO6%aUQj{~$`>&}vmB+&c}$Wu z4T82tONDl3kd*i9C(agdsPsY0$(`GngqDBlf4rX9QWu$$f}%f9njmSb*b~LA&6q~P zgT!KJbOhp?j8N^M^or%HLfrGu*mBLHhA|YT%9K>W*c>6?jEr9FZ`yc3NsUQwA@9#8 zP>I>Ty(4!)&z385X0ULhoZk^Re1AKC?}N*Z$u6Z;L&0Ap#v;m3Rkhrw8-iU)UW$wi z+Psy%?SQr4KkDGJYb2bLdztE;vMLr%R%njMs#vBV4-DkLsPVbIFv`MdqHxhM?qT;p ze1S<$4+IkVn9d|>uIo)xwH{#rC|xiTRjP`kf{C7$;t-VhAU8#Esdff|gV-pXg5pKH zxc`(Tz81C^%RQ)_yHlef`7K|UUN5@mpppwHosV!a_8;971mrk)fwsxLteYJztu0Vw z7pNsS^+EL_+(K&dA$`=s919v0nifEV!dck7S;e**EnPp5zYw4z4GwPp!pJ^mc`at; zr0^hvjG@=M0k(J_s9p#o2Y$%0Ze?QKerrof8F-Cjj-K-MD@DYhN3zvI;as0sW62*W z)7HKYjHbr1vGC+L&mb6h;FK8pHIAz>r@vtkn}-{rrjGW)v6WgTYUew8SSgNK{oqm_ zvxtSxES*GBge6^PYjsBD25SC1&_X?P=s=)~7;_x$cx20@1Cb;Iy4z|kQ)5XJ)pMR2 zjo%Qb>!Ag9ZFJKD6}2FlVzs3A6Qdw6qa;u{kF@AdeYe#%A;50On(9Q&od-N@&#I|Y zL}Lmg1~nm(WWhAE+|%wDmYO_o^ipWlNw7p8&%DZ@1wc-?fH#?StBRfe9hk zP$vz+Yx*7WEl*dL{@$RXZAM`0)rr3>RL<#B&=7N+jKC;$K8rgVrBY65KSW*jwbWgZ zSoS~{aR(vuw?o11s&(7;aBv4I=Y(SBw_}{sJz3)JG1|fq@AXlY|FYFBRl+D}qIlkO zAyxXGM=1MMTezJ?H37AA;su&@WvJ$4WNRsC87NWHHz?X`=48KWyCfxz4C1ypUzoqW zn$(ovvxZsO&V5LxHzs^2H15WH$H9)$fKWRp6;mY&eSXT=R9A=qc4mh$e^Mk+vyaSf zfuDT0g!*}ZTt%hNl;TWfr&-^H!;TDZk=hJY^A)gn@eLvW+m(IJUM zRDvTOtNo90x&CIXTShG7<$*3HPa$pb`2x1;LLJU<*Gp>`2*1-!=8N<_aFH@#XdxJAvq zM)WA$TTm9`jR1{cpnTp+L~Qt*Se*A)Y!9mMODLSrVk+_d5JuWk#kQu4st*grn+Fa* zbRkyEW%(>tqj{omZZ?MQ)z_Tfx{VnOC{zmu%IAzzf}SefK1O;YGOx9uE>h)U$9Q~v z{lJ!2;!W%a^6nzkgCNsJ1;Sf=E~P?0CR%KV1?h3Teqc)_vF9ErUc|N$@}GZtAIVGq zN#oj*M#!Dmb`{1g`n3a+5Yte(v4oYZp+2g z%UIa9*!gfV_fV{p+3S^KM`W-GL6{Omg8Vg2&2mlC)IzzOe@iL<(7}xRC#I$q+C&#x zqf~c3T~60Xlgh-+g@Np1IuErHr0K_uBC*r#1&8Q|8nxZ^8s*v#Ow%%iiORVfRTNGB z>nGk91SYa_ITZ@$LtKnOtkP+LJv&OLDV0$=9gcGQiR~+pgQZYBSAwEB97j}ZUz5~5 z?Lo6$3w79k4pv9o3o~);CTbVwv^3SfoL$oXj3dIyd7^R=$8+@!r;|$muIpwB_=*j^ zWbOL2e`9vk_?iq|IIInO!Y{MJ{lIocDk&DaNs4XjdMcuu z3cCg`7NJl+r}W^jG>svO>Xuo?5IKz}4;IIh|E`NEGF@FC)Xs?}(K3&!#v0Cq1-gBO zIgLq8>GsOSR)0OQB{@auIjEn{Ln0p$hlgI!rz<(6s+o?6pRQB=EboQ!AoCN|dcLK} zZ$C*)d)@u3P~sQZgk+RnRgM&J(Pqim?kME#tK7}-l-zL2}VWXnZ2I3S=43l37G&!M6< z`C-R+AD+!Z7fxqP$$d|L><8u;8%;h;UN7WDA{_ZJHFKD{Q`IA+VR8rWLdrb#wJ@Rx z1I2Kz^%X4?$Hz@`5Y%6h=cC}$8g&T!tMqs2(w39D$3!Ga9a3(H8=u`dYUK zRHFuJ=QKo^b>Bhl>U&sB?}m_U6fNLf^+I+vEzCIxdx_ot(Q;F6+aB%kU}SMCGTU+q zr^11l9Xnqb$DUaQa6z6_n1GV*LU#2@hsR#H<}t4(lrDOw3`>3O>ArvBYTuhO#6)H5 zB15$2DdMTAr>6Q2JT*MQbI~+;d7qX!<)R|IP&wBnh$wpvVbvfhHF;p*=o0i*g|19( z1wGkvM$}h@(oN6{6=i)2Z{4#!)4(&>JW9Jo4B^+A4HMT zUbp6;Vizc16cH&y=V=LHsgd2pnF&D{M)5gQAEEtg3TO8xw1LQDP2hWnL4l<4yC5P*bPI!4?zn=v%NAU?nWwD_bpw6xu{JU%ct~kAJlih@t{YmP~S&CzhQe?M>>j z1KjB-9VlO1Oi<*%GN#>Bt0a%(feqDjNBg0I^yM6!UJo3+{v%Lu7xk9@829}Don`BO z-r%dOzd-GVJjG~ypRSZRr;AL(^{#45uQDax<@j1Gv|~SkqCaQmbNzg))+}DH#e|F# zrHSH2YATBS!$pkjsAL(UM)xTpmMA*dx)1F&m!zB+RL)On?w@bv%k)~fBJMF!K98r9 zTe3BF-#314$<{Eij%-b#r@Fa_78BZWDXU6QJ{NPNwUYJ30d3J@;dQnr#@rt6HnQU7 z9o8~dqd6C$e%_&G1fr5P6kW#|`A=qm8Gb^5MXnvo^Jjqdq_VZ#&auCuu zfRmP6P3=EM6p#VC*oQ(F4j6a_esjjx;0G0%G5#o2&vP}-4zH_NzLfln>?R&fyi6w1 zUK2$YeEX_4i%>i7e9-kMqs)_FY>h4L3O;!ZM0j4vp6!iroKUJ5D4mzZ6MuX8C3m7} zr($^0g@~A4qh|VEwsy5Fh06Ji97pcA75CCqjrcZJH_@22JzY5b(2?I2#MbQ}#1sS7 zb0QH`w5l5s!8&OGSGAZdm#OgerEXdNvv40KL*18fJ{BPHN@?}M8cG^2{iD28)PiwQ zGmrZx?)0VGM73S~#Aw#U!5GJCGNM^yp)SRN1bMx_O?zxPi$8svD4*xzTsz;@hxePd zurP&*F6*Rs9pp-I(8IlN&85X z#H4I-c$tmjWqDr^wyJ#myAM*9hk7KUj!smoz+Yp?KaHmzC=0B;=|uSEQ@kfy#%we_{I{kO^Cgu?m2I-&8f`)D{$ zNC-lAL)1yBX{sGtYBfy+3iWdxS0o94I5^T;82i~YQSs-ahzT9};rUhn6itwcXNw%2 z7`91nCaXrAC^%?dUFd=>p6ttLBSoa4FPwUjO zJrKn)5vu1>YK%}%_Q&PwaURR)X!bk#cupip4{xms#8c?Z&o_HMswNFMWvp|YQUOt!CnC_lWOm>4NcbU~a-`G-+N zw~wtXZ|I5IMUptCqa+@O8uBoDNTS8_^I6>28954JuU*oJqCxqh-IL@z@ue-|_pb~! zCAW$4Mfs8;u`q|IJF|ua@^)Dg2cX|8(W9~>pH^*Shlwt18Tgo}BMm90ESCa{`6`!0 zEL1X~{pWojTZ)!jn&@J9E5VWfyq(sBK5glOeDpw9`x?Ws+0sjT^O2EWCQXCBEL)}b zy)M5-8i)|&d|ivN{PfWCP!Z+fLnlYI`K)pEHLk|!g` zP1S(vh5J^5o#n=@*aM{-V)!Z1@i#d$tG2=M+0^OS zPh3dw(nR%KAc&&qba+n)#`q$Kclu^>cpoL)9bqC?*IgQ@TsQ^TXZkOc>CDs%1V5npaz#Sf)q(1rUJL3Hp#>!K8SLol-~b`l*_X#2J8Wf5<36UB>ut>ja` zq!`0%-CX=!H{VncYxrf@WF1~Zr0WnKMuJMRX7lXQ zu0;waAUoO4H&*>_Bkn2y)%h$RP}S+rIf(E!e(?HOM~8*bA`lK#F4!&5<3DBGmdrQH zbxp_#wTrN$GF#GTWLYSWqa@NXWwPrKC$99)ifNik`~cL$McjdgyzEA0xgoZAvQJoZ zRrbU*yk6DXVxN!Grv$now@{Up_H-vBtrBsKB-;9vZNtCFkH|r|K9;qgg1^$~vXJBR z0ftX2`~9Bnmq)-)DENzJ zEn<9mvT7MS5t+8;%nuxt!sOQoQ-Z`_W1gsAv`qD6|GSR2%ZF8yynUj6u0%jZ%MPlU zH%P^)Xugz^(jTSC`mVIV{dDR+fa1B38M1iOdRyA~-b-;oUHRz#xPi(`ZHg(Ap@AfH zVZBX&^*N%pR6Qtq;h8g0x?o(|FZ!K=uXZWR)luRBmGhYkj9Sn`{2N^~6o5FXaCj2g zv=48qbyhY@9yJjuR4>|=owGRTh=xK@-^g6+wx>CrIRVH*hLi>3!(;pBPbBF%kx9?Cl5d2mPXppuAP^W;ML zfB%z~v3=jvYAqG~@DwikY`o}$F>s}S$^m()qj@BIy_5 z_}7^Qt5r9VknHnL7p{9GFQLAukv!WsRaGq+%5L`uTP`z`H_?R*L84>$nF{ZPJF$jd zHRx(@_0PuTjmt~aCMxHbaCY&zgfZuJ+!S^d zvBUVJ%9x8P`+@B)(!91%J(m@SDfI)Dro9#(q$Qzru2DmqawfuPP13a`5stNt1j5dc z{8F7x+!~4qgmf*QE?j>FG);NM3dSSEU$aX($OmGSfP4O^P~g)#ShypJbS|2)H^gp z8}WEqcI9Va8TYz8ZXR&fC)2rym$oZf~s)AMQcobDb{yi;n5@3EL&slJru9()oy~B1hd16~eOSk{NrD z@9>`w3>dFAsa;|L0n>>t;w<`&T~#zB={z$IU2G*g6B-=3qNMe`aBU$Eq;~G{!fnq1 zB3mo>*2aOT0wSXgugS;Ez+TA@x+vda;`kZhtz5}&PuIK50xTC7AM$kFASawLQk&D* z$0caKpc3!=M_ikM^epb7P`ik;xaZv?Vdm_L<3-c*>AYxLUvrOjElewdvaC=(7jDlX z{2;lo^bc)03+`(ksQL3LK(2u*0Ta6fv+Yu6|M)iwig?I$MN=z1w9C`Zwc&u#7|lQ5 zTKt4H&7lYJR}^H@rA+o)53T9A*DcDZ2Fm^7f%Dv27@9>*LE7Hx(kMY!eCSy3z14Al zZWHzM^bopi46}mQizo--uQsN~LZ`A6-|~2NeWv0x2LZa!1GE(22X@B_@oc$l_d}bg zpDRA*@JmT6?R85-l6#~W^f|>7)=wO4*{m%Mx){gL6ji=Nu9tAT-JZ$flQfYAst?!2q;{})BSRhVmk`Fu zNm6DEH>a0#y)9RRBMuW9LtKXo|Da*IhnHDSF7E@i^EprH45V3IvOPoggn}8j0t4KM zvR2;@Ofyq+)SwHNMMg1RZ<_M8_DUkVL&lF9`?e}Z`(vSRjm=B{_leL8q=~% zjN`IQ6fV*hY9)PkJltTrcZ4OJCWtJYBFKELi?%iVo&Gm zQg5Fkgf-L1f;|)H8RIaLnN4{8z{%3!pa%xU^Qm|lDc11=V~wI%+BpeVCd>dPyIQ)h!-VWHB_2?|dC_^v(*%x=AbV|#+*2C_d5IgXkvRK%<|Mmd zkmbbZ_ps>j|J$f$=l>QS4c&U7ba4x#72jrDY4IIlW+Pd$4V_7rR03(Qg)Ic8Z3~Lw zoa;yz;gdzPi?sG%Z$TD_LiOCy6q%pt(3hqS01kbYr69)m*SiMq7u^93K4t4d-k%e+ z@oM#wAcUqQQUwYv`bzA63>~_|3gGQb@tqI>6fUgla{k3l?6t0a!m6@?;`v+};)CBm z@D6wE#4ge#6iVlsDOm#LbE2io47pMx4PzkQE-6J`duKHik-|jvA^@F0V!u_&Ka{lm zvQoAGIz3W9QM)MrBNqS3;Mv!(ZTi8E10{cM{Fo)^G_y39+K^l+7X7ZGR0dO%DtpuNT9@kGMCs-= zb85|vh0%uSvpq0Vj0UkC#{D(8Y=0yBF_=;^glgaUFqN}vEwC4WKt+!WGxWER?OpC zA2E+Sl8Je!2<+Zc#i<321)+2iTH1-5!qfmr9eHm{3NuP!d{fK^wO3<0Gv_S1V4-kv z9a1yA9CpmNB%6`UT;EQr$a1>r(!H11 zrSb^-S}KpZ59{)^aB+qI(m?%O;wiWAgHLVPA25^IYIlHAJdbGM!nZLTZvVnO`#V85 z?VoLIJ5~CM;8B!J?m^{zcqeP@?6Il!Lk9WJj$sR9lmDBJ68l9rXW61Q7O0&QhZ$P& z`h_!YDdgPt12dBTul|i{_s$zy#HXc9q#ycpRk|v3M#?UF>av#nryzH8d*8|pmnR=W zDG55+K=oW$!V;~2d6cs(L2AT_ww*Ac4Wfvb23KacXf21rOmw1p(Pp9F|H&NA`&C=i zF0z48IiCv8b_aFU{xQ{v=)Lvwr{SD`-J^RzAid*C+s9p;G@*VzZ^$g?qz+N2?0ry& z9C|f4@?;S}_vPO#$j>UmgZjnh!l+$Q7ITfMR0)S#uC z7#Yn=$?m>F$i=1P#lT320gB<*_QHM8(uK-JT-oCfli|C>W6R}HG6#j5SN%g3-t9Nt zEVgoPpyJNerQm3M)6#c**Sc@gq!kJ`3zr{gY0JOFc0?X}?V!;KI9-^z%E!^GxGwSz zrd=5xaj%$*Z6PmP&e94s06;gqH1Xm4cw#6X>W6o+M$p!Vjs1Sro$^|rD7lN47Fs{U zmyhHOk-CHjG0L&_=q*YkeTM*eYGb%IP&p5#3qtX=kAjD1R*Xi6Z}u_KQwvg#*oBsE z=T#{W>gS0#HJZ_vuIQqm+QHBgWh>g!Q7$5{tz}0QLf8YPb1}Xm$^SZDw7t5ZdMWw8 zrk4`B74OrdH`~&>Awcz<)yglK!n}-K;Xy5HvD-JOFk;JGZ=91R|H7Z9&>5GXYZs~i(Owd&{kY4c{^ZX} zUaVFm@E~-dhEtF_{`Ci-O-#AZVI@uzgqGmm-IA9JM{rMZg93D1}KcaRr@h`p0MbpL=%Q3BD{mK{Jzdfy zA-Fntmr%LN-dPMw`#w=UcN3+!@yRaf`*C~lZZv)jU5xRP(GN*}uZbz-+bw{{nT@TT zf;^>OJGv*^DIR@%_L)4rCoeV^=pPnFiC|5uvh{7w^H3`{Y@IE(-oD;X+u z7E2dcXLMX#%kRz>%T*DGh4T3XG0OI__J<-Cy(*@iPP_PkF>2suKe4Cc;U>Bm#)qOD z+m!O|nd!d>8=yrsK77wIZC#&n!!4k;iORWLDxYwC%m8uBZdAoZ=1@4_x-{VSs}5-- z%ZAu@7YpYphzk{-UK)W;YPkEd7aZccW4czv_4TjADPmC+sE+XGS;@m zO48R25=G*8*4DHZMPHX1o+&H&ud(x!c5rcAB132)V@L zg;4+uvp`IM%QQe3anN6AOmZ!gN#c^OF>axJQNg1N?H{LD2hZMKwAU1EtkMtZFIG$G z0ri18Q9Y+yFj$|$%!WCDDfrL}7){$|Ay@s+FKq8bZY@IXysd?CS&s8|u%O(&l1#Fs z=8xs$l@W)qi+HwN_iirS)4Bd{u`GpcG%78Te^ZKo_N8>$ry#dbUcwd@?pU@VsrpVF zem;(0@(&(jJErZ;g3R=ei^$@g zFWi1`PF=F)@ISk!iYIiT0$5gBK;PLQN49Le-}CpjdSl z#?L1<)Gqo~RuL6ZLcV zv{HYtZOwaG`(MN`QMxFKFJip(TJ=vB@F_!so=4wq-HFvBp`P4CIbJ+1tUo_GYVa={ zDXB-`SkZt}D`)R$1_1hSoi3`;A0#5(_rj@&7B5uJ1(yq7>bHOCx|%HH4SD>+hAz}RA^*iV zQ6{ zp?DG4lJ&IF$*Yo$;eHBXhUeRVTj=R(7zf1r zI$gNCPkoEBUvxvyyG~Tk=UeQS`JwT#pVvY_uQ?u2xUi|!*jFF5OZ#_?IqjG=&^Z{* zZ)F^N!fc6p8z{MREg%Y!Gn5X04FRVSN^@utN@IibzL;WeH~>y`^DUtjAE#0be+^0T zGWMzRI5kB78gFGZqhy61pn6W6E{LDC5lqv47!g47sv=q9#$RCb538)&Rrdgu^YMq$ zm4*Eq22-A(mIPHK9S1#4G@-R_^0xU<5*5nj{Ok}D{iE!$yvy+7&QcE&su%3Ev19-J z&k6PY`*HzB1=FB%(b$5b^m+g1y>P>{tWK2ArvbTUVG-y>Lwu0hqn%wzX9qT>192yB@W!f6Sec18h*f7^OFvfc3E^K z;R?CLHMJTR3!rw-SbCo*om*&j&?!KFd=r&qK0Bjl2?> z7_+!N%iPM+Vw4`=Ode)!nr3Z5oiP7+;q)&Jwgt_2#4RlQ&I#J7Woup3-dB6c5>c|! ziLTx>hf^7)B}z7OrK5@?<+kiJZc+BPgiwrXv>pF~^X!n?@Atxf?=5O1oEbv#Jm5hS zN?MSo|a3myQ<&ELf|w_i2ZG)f*o7ug{#_3y#jWg^P(aCR~f0EKgPJVld} zap{Hu4UEe;gUp}?^m0x^wyXqBP@#138S`b7G0J0`R1F=9hGAIL1$7D6i?-F8bL~O# zocT~g_+bv9>=)f!kii9r-q-oUFdy3UF`*xp;9k@&etgWL+=chTsdH|DvOlllk>3w) z3$x-9Ot){TL&s;YW&S2hDTWWJKxiANpBKcTc6@V}R`Sq%@DA$SKr&A{U6|4AnWe#a zQ`<6oHcgP@1UL1Xe6-~%=4k`<3+pt|q(00Z>s~h6chu5E{o;BE?FadTC1BRzS>*B6 zR}|DPHWucGZ8o*Ya!FbmdTe}C_F8F~uNaTz7)zTdo!9Uf)~FINhnsDITg7bw+9TP@ zpZ#0=yCBYT9Rq=ZE=YM*t|)&xO+}ym+Y)Q2?+{NY}63&WyIA**f}G z>qUoRuXsE$syr9@aO9VqiFj;qI_!r{l)Xt{TGrIma%;EcxFO3xA)MD*#3c>WSj!Us zp^4{%3P_#INjE^*3)_!7+(jVOp35#&%7tzO02zT2QCgG6{3|367TMQQK;BfR2dLky z+otdmjcCmqBD~b$_+^VSgTk9NW6}at2Zbk~e$E7}5aUG?BTuPNS<$t2x}hj!jsmiO zEu6f(>p}6HR0{!l-iSP?1_1RH>nnqH8uHfGYE%hS#uLit^fN%Tq^ z8dNVz9!SNH`SkK<*DAFg+sAe(XvP(`c7M%@vm8UU6UB>rSiJZzxyLmp*03!V#Ym`x z^X$QXzaRRg`&B2~_R&vtVQ`Hg*ym8q9wTBduBt37bn~jS`{6fU?X+e)Y8XrjT^ItR zej1kkap1+$MT?fWK+3bzlizqXE}42wl3NDZeR%#GXACUr;Fxy2VDPEMCcxuUOA{;n zXLB`z%QjIyXSX83n#C07r)`|Uc3NSsJ#gwpjQaD$^kYUFd4m{DZ~CYirpJ(q&#C z)Xp6N&=ZU!=1KN`QEb86GGq-2LUq-UrP~XmY~3a*7mY3W*dmw&oR-S)r$Z{d{wp2% z>DvFhu-#NtoIn^|oiE&fhyix+Vats!kWf7z29O?XAAOH#M};5mDPt__uLq|H0W#_vUe7v0iq}vY8RX- zj;U|Yr(O0)NwdTg)r*X&lppLSVt*|>O433XGt77orMAi*{F~q%Hf~C~dX}KH|Ga7( z>S`Y-xqk7)gjMrKv{!0-*`lnXu4#tdBS*;{Zl#>O8>fe%bS`mGA!YsU>&0^RjhBIj z2KM2?)%_qQmS0a?;IvG1bAH&DSVaV&jTaF5t=@ti0?$$jw`zJ9KFDRnq!PO6^)Qmt z(}2k3hP5fcJnM~isa?q(1_Hx>!G+ht4ZY@pE_@$( zpm}ViKZM}MRJ;q6J&+aSYwoWHW{T)Rh+`bDi_79nAnaIRDo<_NnxxbdI9b}>Sq+c* zG*LWfiK$x|r+*6O8JYyhMUJt~vc}%~`_RfFT2EBn1?NI@S<_%Mj0R8ogW^+^Q6%ZZ z?yZ$6B-8Bz*~>UD^jN$U!X)$NAmycirg&4-#S^D3b7`xQn!1T@8sp7>djjlM9tO=# z$+#gqz%QQnTMp3Y^(AGyxO_+x-Sj;gl+x+kW~VQV5{s(2a@bjRDU~-%tdWd%-NS}@ zJg3DYSM^B*2)j6qiAhQisyA<%3A`!aZVL>#xTLa2h>VHFw-8aw#UftiEuagzIHpML zf*UDu@uNrjXJ?ixSbW1L4gc9&s9^dB<#QHs<*OaD#CB>`J!lqDOvY1oQI+?!r`;b= zoYO$*!uF{)iG`|$h}LeG6k<;tlJ+e_g$VlxW@JH)El@kx1E^xfmr-7V!J9Pj;C&Ns z%dRQJ(_V)q7Rai3fZ9b&E6%L)2Qu%_2%Q`^Beguc8IvS|g5N)JC*CL%T})4-9GM@L zi!KG&O!$sNTe46qE6~`rJj+Mpa03Um3kpJK0)N)UqooA0xUfH5l72j*$M2SW3FH)I zqN{~%^TuhSMnS9b^};R)!#|$-#O{3HA}<|ep?1*-=xGiTOH6}Mhe2Xae@XMH!u9%! z3o!xlsL)OE5)NeBpHIArQ-#Cam4T2%JYU!n zBT3{S5L@vfE)9Lnh8D0rx{SQ`S8U74vuB`qPOQP#AdN~7nJ99w_VHR)j*uxOfB^^ zp4U)0Z*N(?^#mVS15v{v_=wc_2tKM8cV<6uk50a#Lh)SJqq!g2h_3*%`Z%7`P(pM4 zeBu1BYW$JfEbgo{0z$`kuoU#Q2bKpNmXiTfgB^2W;@Z62#W+Etb(KLNs6BRZ>nJAvi1CyT=Srbxk z33L++ob3?$zs%TJYyV-KwrVd$2@L4wVnjUttE9JGAkkP$(rpsz=N#%5+>^4A{73yG zCMv_tjk7JhTl2IGl$?UzLC*ERNyIeVL#n|QIFpjvc%&V*%!L->ZKC; zeJ?HxS<51z;rNO2`9K0uWav`@I^lOk2!a}~YEJg4Li2R5h0Cyi6e<@-7o*7^hB=#` z-viRNd7^wi>e8Ue4^Ok9*8bgY6DIp^2H%9{te@Vw9jsXk(K9$;cp2I(Sw z*z-!bcZuaSij6fqsGm#6woyU(-+k)c{^)4NS3gm_IXe0jx~hNn=rSy0z=oX)GXVb7 zl8$ZNBHlsH2VGQ7(E$FIt9xx{3wbh>8ljt@C(=2bDTSTof`IVq{euO4^ilN{x&S*@RKfBanFN|>=Oa!5FaaKkwFVvThstq^lY8t+$ zu7*J_+M{VLY{!a>+=R+StVK04jv_U*)*`~#sH=FqDD0=m`xl0XkS0nOju$!{KZdCN zYu(ao7(Xzj&5L+vOv~tMun1CPX!t+0{IWwRd)?-TCj}_@bMr~LE{`}1f=Tdd+4f4z z82w`h9rwm+%;)!sF3fUhxl}2NK!30tG1@=cjz)>1TG-JvYq5B0-J^b>qYX6lC=VC* zztnodTG)as*_;T)bEQ0ng661eM)*LJuYYw63k13lI*QlA0plm_EzpH?J!4ShMmjv~ z=zx&dCpR7%Xp-LI(&s_<*{;wsQNH+?QhHoX5?sqB9c0^0c2khQB+W^!E@lsQd}j8W z(1o5UMgYCd6w$T~`gFFrm@E0$?LSFsftA<7rE1ny=q9ujPyWje-U!umjSoH+?lv}cl2VL)#V7)_F?p*- z##^0pNI!Cd&1|12KQVe=u(+~RPWGBzimO6)dz>GacISS($Sm@<{h~NDg^9||w^V;9 z*6s>KLc7(siP}YtN&V6p%Uhi1M=Xyxjbix{RP5QW+H$%wwsgT+{o;xHcMD?q*RY!0 zvV@vDCnPq6dFm8Xt-HSjM|5N zOUMFr`<8VBmp{!uZpHkb>7n!K3bk`9287$br!e=0Xnzf-fmfk;KBI@|T~)G%*#&-< z_K)^8qu*AV^jzCJu7$%qQWu=B+_}bweHuU5ZMgTsKCOk@MYV@P)6dvrb&C-?L&0sL z;x2w;%1LvmxiTTG>QbPA1+6$@06gX3%(I#{;r{Cd02a+`S6oy8{FR57V?y_ zu{qan-nM0md76#k0O-*+q4ur5F}7|rtXIaC<+z{Bst9P{Ow4G3s;LPaNz&Np7Nk!IgUp$)kDTBqU!j zFG5J3>*ytpNc*xep(E7Y`M3?rct14QUJKg}RO|z)=O#9dFm^hP*e66WvHhuG$%$eY zR)6bXcKl;vcu=`0>h)h#nfEn;o?BCi+)xe|Rm>iL5GYtv5w?$05NlkhTu^)&8~;|5 z-A`=)gZLS!4zKmoh4T;O!17v{+#^iX&mFkA*1t1}HE)AZb5L7es9&6zh{=B{x-8{Q zUT>Gfm?3z^7n`d+#Pv+68ii5)w6=jDu3JC=^JINaOzDs77!)t+r`@8i97ga{U&=A>jp8zr&cXnV&XzlkCpM&5 z@N{AS_{q@~@FJA|1x=C3PfnslG31#MoYQCwfcm+)eAn>q|8|8~+Wodz@8UcO#dD$a?tZDxm;ECbyAFe&h%oVZ;ru=Q zx+hR@6UZ6?29Y04W(|S6be^MjOcDH3AGa;zyw7q<@6(_II&A`gySy zcHMW_F*<9uWK9gI*dO_3Nk|6j6enrd1^u&x-68kD#LVnp5JR~o4q|!lJ#W`eyy14h0e!x2X^#y?R{3M} znyE)iv=J7fZPv5;2y+*Ch5_KKNS^lmNx7Fl%wg;Ea`9|+`qM(S<2(S0%J*}Q%83>$ z5CZu#pQ{ab$nKxwis@MtAvUKFIp*_mC|Z4GTr9+8bS{crES{a2vG9;)RD6EXY;n`L zX?i#>=Xa!S%VY)9EwN9sP+n&f^N~`Lo$534lcY2>0+lL#f%0^K+GU2j+&UDSR!`46W+mjl7he+!OwMbR> zsr?x*?o&G%vLv{I<4ht|wtzuuYnie+f1^oYhX=xdanPUfym5@Ob!am#vv^+rs68Cy zKoVpC66T2%&}Ya^S&M2gf$j zG--ay4Ha(>Ek1D=Sy(1L&G;+{^VsRndhQU=Rp0%hruq4t^eQ7}xAtc~7bH^N@|o|4 z@GP2`+18)+d2dqbMB(-PF%yE*ccu!3eO;nb2tA#(#|8>a$HHa?U>A6&|>}* z`@Ri=e2q$;53Fh&kIZ`MK@!4+xtS$@{1G|CpzJ@5grzK}DMfT@`EBRTqdq`=e#C;k ziu>3}_P}zS4lOZ}aP+HMmC%=R`fV4H3T~1Xa8y;l>(A82B=eAM(`G)xy2b79l^8;a z%s8BnlS&vZ4gOG3%?OG%*%K@&?oxZ22Y$3Tf=ry>3mqWpKq)VlXUml`)vM^Fh~$CM zQsZ1#8`xwf<|0!@7kOLOw;IJy7mB@a3m95u!V)$8tcg*PMYg$i%;ItJD<>S9UPZ#@TKld^s5!lk;LHnC~i zZ@v&%6upfw1T58z3}}c{Jevj!?P3KXJHM!{oeDKSzwM%~oclt@7EU0iC7Tp?f{v}~ zNaV7drp&AczwMmHV1#-_%gD|H$~6`fHcMmvS#+O)y`}w_EwFg(H-?K8(Y{+*W5}&z z77xJ6smfso00GhpdF^ut@n;1)rO&(AT#B#1oZ$CD z{;h*5|B+!IXAycO{g!iDe{eJ3&9=H0QAAZoznuB!PV*1rC@Z#4XrIFc55Ld3$X!=_ zFh}T|IzK^aS{2)@9SZ_pt|zrSlv!1N+qp<(FK|xGb0OLZ<5X3SfE6s>?+r$Tp102i z)j7WxA|UjQvY&}55Ep&Y3i~vl)G=?ei2TiIcKTn~Z@U1x0NnUqysM6Gkr*<<`n^z> zhg6D8WeoXrSF|~ci1h-XwE*kXy3`UOL?6HDqSzpv?MZYRp)RNGV|kGU!>Rm<31C5b za0ZV;(eDMvM<+uQH4)t{n7{0$j%ivzat0LIiN9xi?yhmI-PQCP)OsqUR3TGQjQau6&zbMS~Ag4LWZL+D?#;h6=gdanX}0t zBG0ECxDUTYzE@A#a*eEb*J9unRZ;KY?9QD+$>L^9q`=3U8>vLm$ZUY}{y79K25%70@EdQO zmLCpYzkGTKe!!?WcX1xs8tS^eEmE+=0r`rmSw_nx!k^{5QWkH^X_MpzzrCNwDI{cd zqRf#z@`E`tN@Ie$t2V~MsMwmNn_<7+T{N8R)caw=e!+1psGvo_Z@Fj{bb{$Qq)M;S zvv`YU!2{#x&^!9+SZbFV#mG{Mcvx<%U^r*FsfF zTm05@rFl-WxOgyuWJmEc1;7rJ0_}76rz=t&`b<&37xKlztQOvGVKlEwNY7rb)NG`K zLS(pH+W(;_Ws#>pCK|QH>V6&q#i>OoKIr#+0F)i_ttzwnFx3MUFZzwg(r)H6{2&{+ z01efSLLxEyt^OFsORV$xpli3-{bt#Y)9*RISEKUx!+gmCUeY4YQNQOn=?0kdbFj9} zaID6d8GN-1cP;uio9p@4%pLk&l`k#dW8u46YZHaLu5kbsM&B6(X z9%+?C)#<6w05E)(u=@-F?MRUNGQZ~&2953Ut-`z#H8eS?Csj#8o5Fk z#UI3(`G<5^eVP*J_|Zb(w;WeI8+Y}rRM|UaR#TO#5G4@s$B3%mKuB~Fm^9`0W)ayb z_C1NUP^M@V(5~h8d{VcO4`e?ZrOlqRYfiQTF|d78JW>Q3iUWllQ9i%<81mV;qQ61? zZtYRPy$B-MZ#qtyng%fZ&>dtfk_d~rRr|Yi^DU~|1r8+FAzI*9-2bO83oW^^icnv5 z+$jy774nEQ7|`OpMeXo|D_y_+n1rQ)?)y9!cHO*zSj*r5V7|ZDqwNO}@7kmmB|zP& z-+J5&Y2wf;qsWSMq2j(|Nt%=-a~qMaUp{HMMg8V*8eTVw#dRgYO)I(9DFs_C^NwDV zsrx}~A6dA_Z$8%e;duF%2DyJlgoK`hBg==vvY;SIk`k9w6eV2MZ@!3(z-7C6964$v zkTlsX=9;FRY`6L+OQXSVv9*5tajU(71*5Amplbzf6$Xt_?okpI%jT%Yr{zj^dE2kK zJWXCWwEsccr|D|O$pgqoi&A*vOz05u6YC;>#?%47=h8aOX*}P}&?u^M|P%vlFqfj_kKzY#4y%YaBBPC<5HF=+t+}p>wCMGIo=`T-I+sW(;a*trzw8?erO% zgmxk%@-r3`;#d9Y2ctX>F$P4Z?if^HPC<9J+4QLrYSvqYSTE6ZkM)THTN{kG_G_W% z`Eef>1!kpQpC<*T2JkioW?1W}+yB5~8Ghr%hJl!`Pf!7U@4`S;f?$+NPKG}9wRpRQ zx%LY9J!g=kM*9O|&dn>P!>wo*-&jr4_n7|dHvtDU%( zHt~BdQ`itk^s0HE7L(&%o~ zv`{e`ovZ0DHl_BqiG~hNdEAzWj50=Y$Kxpt;=k`U{{jx1w~C1FF#1J-Bf0M}vi+=f z_zx8!lzWbw(JY)FN;$D^x0WAvNih^?pU>Tfb=BC(VA0vUYAjiNT{V8cVk!Pvg-?!TqG`WJ2jvH-~^Qn?uWSrLCXagILnvt;KF(E$@ z+?ptJ1-8;KjDC!XYyy9O$l>(uv>_+ehEb0RG|lNR2h=_n?Hdn13ygT&6K?>!KAQ(^ z5A;_1u4+ru5IPp8ZF;AQzcV5hTq_oS_rc2mSvmx{Wjlo~tI8%&VfRP* zh7gs9wo6#C#rm$nl5>4djB|F3Myq*BhkNGV-H;A%pm&fCPeWI_KW@9o;e+by7jBm( z3loZpQaBw4Y6CO?9q@(gfWt5daez@S3hWvBq{)YxDj~UrG~V(7r{KQ<>uc*-W9E_# zGWvO2vyn~NE*MAgz~&S?l&X$sY5q`x-!}lHtO_MC;zb98g;OUVde-d+-mCNeY(Zri zn+rtVvM`Khv|}xL$x=i&PersF`6DyMYN*(LB9q^RL%iX57&V=5pW?q0*j1CTa6EeC zkY%)EuBIjm&ab-nbKPZ%hO8(vy1OW<0pHFOjA~(uB_muo9r7kv{xb*X<~qn6la$#p z^2Nnd(hs1%{bgBB8WYE8$3$G_Hvcl6`A`q=t?MwtMZu|*&moq+4k%m0PFP%wbG3-3 zcDSCELV<^1H`=o@Ij5qn2UWfU83e@p7{axq>>_BRBJc$>e!Oyc3tGbwa}hojip!IB zv@}&<8N-JyyEf@$#s`_t<_bkjFwHX0V*%6#^5}=pU3kK&qiB z>i`<6))jC~3(g;U6x7$U_)%QA=v^_l^VwkbdqE|jDR~&};>xT2dp67Oyr(d{>xN-x z%=xZ`tW0V}kOGQ=+aku+xO^;P>_Z8wtP9=_kD?$3Sem=&Z9_5eb0yV-(i&JQGtP(D z&29LBac2in)dRDs!^juwnB5^&hRTW(`O9A|QB@F%2apA93L2H-+c3&Svsv5azx%!q z?@gjyQ)LLha_p3bogbG#&7_UMDJ^f5mVM9Sl!y-r4T>9m82#qEmT!*B@;qz}Q7k_Q z*Bq-cH74*=oNW0uBUNN~0LsNpoo7$abP8YLHY0l3hjBh1#^fGURQj-8J#4YKOGd{M z5h=WvzMa}1iPtdVMMaYxQl|1$@Qg>$5YX*TLm*|zF+M~;v7kqWQO}9&8r0cP=*(D# zsSvw((A!kwuGqyBUJPU?i)FF(^KmXJsqo}|if#MN_mjK*&GIm4ksiC%ocK(83de%Q z5_Zm$*%qR7U`7kX3Y&o4#nUJkwXcWHI}^)5N1W}10K-Q6&XTM2z}s!RD^{89>t0(PHWD?AvkFJw>Ww`alhke!9?i8NEeAT z0C3GNFbdre2D0^=sas0pD|lh?7X1$@t6dCQ2_~tFcTC0{R5`ZWl}j`VwAMxyj+e2r zck>lkQNyU=ID4m}_d`svD1acwtZ^FWG7IL`-f3GLbIuR0VGAAV5JQG(bjj4>4XSdK z2{7_GZq5@0e^T3}eO6R-bILI4c^{9mcO2Suh-!k7j!I>j83x`eiQ3JZ<)I1}-h#CE zm}#joahUTQ3iKjfC*5(DRH}~{bhR#EL-0VB!!#}sktqItP2q&PomzNR{4mNflRyJa zzEjI0ieXaAEDa}y$;iJJ7f?{&B}pQnl#4A(laf`wlTe7=YGwC zp%20y0yk#(S5edMgU~sYWYpu4#Kw5dm(z_}vE$H=BykOxk&h{B8i&Al32Fhg1Gxt& zf{b(7ZZT+nBRN)W-Y&Z#I4z?eb7GiV2&`wFuUC-U0szO3c2Sqe|B*NaXmyx4if ziiqA);)IS(QZ~u{i3ZQ65(#cC_=oOGMmcXrgZuy1a9q>q_W#K!QkGFJ=Dbj(n(Mfz zIxfx1XiuY%rZtAeHzP4boE;RLjEfx4Gdlb^q`1RHL~faD#E9`&&9He9#C%~T_dN?! z94w_W@_8NrmFl?N1zRbzZrnAJg~kBsdw9Gy=`3PEBXRE4;-^wZg@j=_4=CQ^H+#k$ z{u-kX&m>f!8WaiJR2Dk#m3ngF4~&jqWZrhOGoTQLan5<#y!hYREC)sEmC13>TXX^a zbO8VM#HiUJOi_l>&l5`ui?L7HqQD3RMT5WquLu@hO>Z9CtiE|4MmyGrY9a*wjL3Ib zkt0!R9!5Kdtb0AyVyu321_UJlm1j^DyEusbW)N=NDNKhZX~N zP4!{KKvkdLOt0W6#4v1Go(sp!)8^IxD|%e21>&$S;+3#hSQ6C|7Hr;M*A7Ji%`w_J ze1$A}Vs%J-XcU9hiB)1kwy7d$>UCUX@p?xYEu2@6!K@9XSAg=U5K8Ga!-}4n)A#ko zvtZurv?lYx$Ttt0eo(eusF}cIQPK-Bqg>nsT$!qW0fZGbT2;Cy06Wn}doL&oQ%JI# zQT#d9*+cOCIUo@Cg6ge7=piHBxV3LtXGN$aDcn@sH5?%p+h`#FMe!}ItuPGnJsi9J zVf=Riagm;HwGE@YW6{1wKAgr}Y=<<-0!XGr3;)R^$sm=c9=8@gq1b|v&#P{lO#I?D z+t*%k%q?{pAzXY}NyuAXHm;$PMDhW9t28+_komNjh+1#vvu-NMd^ zwwlB{y-+0P&CVr;&WnPX^UzJRbz`c>t^;~0k>WTBm$P?0#AEl)L7{--T3j?28mA?-Y{Lsr92cJiS)u8D$?v zIUi-`FwbLPRhmrjaxqy$WRallQz2wQ$$^eGU^+6&MePe6u|=AUhSwlXmJ%eS$wSI} zABoj&`lKOG8Z_tdMX=T1A`iO}VV7`IRnv^_j`_G6)3M+1hTV3N!ZbijjB-)_q6kn{ z_q|JrxQHb`DwB_*_ud%@wbY!Z(axcSL?c-*etF@^C-p7L!jfB#jsugw2*T1Yxd$#eCqCD}X#06YE&OPEm4(j6`4I_cKsK5KMq6)+htf&$x%PkZM z&X}AXMm$Hk!PNIdAu4aT!ApA647(rCcP(eZ=iRe--R(HGMc-ufGy_tRRUkVeW68`Alu2i)e118DWOEO07LjDJxf^7(=)jQh3m zu*tD#6BuXMa1#h~0fkl_Dn=3%HWo%ahY~U*`#A(s*DHp*5WJU+3;qJ&Hjo6WAXJ(z z_AHi>QCMwKe^|Fb%uMVdk&96->Z#=?!SJO@Q@o{G$kv*n>Cj`h?H4A$bsm?P!4eK5 zozJuSLKrnc*0yVHCs`OpttS&k)v;^0;%@2#zAk8psfs8(col2Y zepm)w7zx6N=Wr-e=x_Y|DpfGn8HQ?F%F!P)us662zBOAHurFFtVo{ryQT;_RKXYSJ?yhzbwfIf^_? zO9~>Io2O;!WpYiqrs;Fw&XA$m+qPJPQIYM{&Mwjc3?; zulw5~DnN%5qaCZcnA`NN_qoRf;4SkUr!p=GW>i7_jNkSl)#?~ImC?@mUOer&IH*@p zT2ao^sDX(GQ1XGh1g3e**7dN6V_dxBUla|VPm46D{UtG~JD&vc?HAJCXWQC!+=|>n ze|Vk{SmXjia9|x0hlG9FQY3d|S3}iETH7nCI|~VdjCiwcnUm@R*kLcQh*igKABvg< zPBnP;w}h9s16jwIgtgDVtWfK2Zd%WYWs!vize#Yyz=nESKIRR=;Aw=5YE%~s@c^-m zXGNJ=QL#9hP@&v~?@Wt_94f)|0&FS;*k%+7g#1ee(>e}Fe6<^Zirc`79d zMF9Aq6Bk~%**@)ulEwPA5+4~P&=~Xc|ZU z@@v;rh@D9B)%l0bGINf~sOPtjMJ4}Ip6w>DVItc%i4ko2PTdJrxC9oGgUV7heA)!Z zGMNo%U#M-hn>1EbdD_94WEoCPPchfLb#$PH(azgVK%zpM^akExG9sRpXG2t_S>dpk zROil%!x*Eshi)y5Qi+B_wL^oo5*d3@wf_~T@v!G5cQ^pTFxq*E2KePSVl=hKZ6%(Q zajsEkZp#lvi?qLO=WHy)kkrqq+xi*3Es|7QyI!PZGWt2Nobq$goE)rF9THmN;>=}R zc-L7t54YWdS+2u~=LH(N!Z9wHrY^=WvD^evf7L+4e6^+%v&!i0$hZI%!fpvxTtw%o zR$E5Z+*>xAA%{&d#Fxr#3t`PNSkns4G}Bt5T8>7Uqj$ z#BhGc2iSB*L<0k^m|5u(Tbu-~yB%6UHif8OTOm-9+6qmUg?LeT^oGt@4lBA5J2 za}hZwQWqH)yz&7cQkYOx3sVL{6;c5|BFHWl^6eH0G}nf4!P%#Y((ik3eO`;6f=bL7 z7mQ88|3Y%G*D~Tsyc`+z94myBTS)V1nNZ6*Ce83-{Pe1JtzK6O86Acw`CI4DF%Pr= zYCx60$$n^_#_hI9(p^SB$8H88%ooK@;mC?G*;VmY@siU^$Ieb<0N#BV{k(q7!_2Yt zB8BLzvGf@o!g(pT>v#;k>nfB{j`epMmBuhKFWT`CCviLA()il zCWmHT+~j3w+^@sJ4&feA@y00Uqo!nv5dRXtCF$qcrcu7Z4b)R;FEvrdBiv{zn2|1m z3&zmOEQ56m9dzHp&ngT}cT(Ni_pQCy%D|J1a&g}(DE?CL+nYASx1h!@S^q_niJx!8 z(3brT)ibdvL(~JOZr^iy{1-J=B@Fi(t7&?u%gaP}Q2b~EMk)5o_-9{H;rCijsP_dwjdT&2!&IIoe>W6c ziY9DpjEmM{M!<(_Iy^B&fYytQlFv5}eb6x-Zp%p%_)LcrMX4TEByjS$g}#Kkf&%mN z5&RIpr}P%T4!&yc)2PQ9z^Jl(B3YKOR6?hm_bTIJs+M`F&+_JT6oU|wfUOzPofmT{ zP$!kZ7*Xi+ZncmwBVf<;T7CfwlluOIi)JK$5gfBxzlPRU+tmJ8Qq(&(qh1_NP?h(2 z12CXR!4|Di;y2s7S)@#5KWr)FJTiK?aT|Y-K`MJi6{b(ZFv|G=KBvStG5d~W5Dp^& zz{oD1hiyF77oy~;_uK5@aI6c654ouT&cOkk*DlJ@?oxQSjG1 z)&8`wF(860`*vF!^FcDoc`uQ>e2jcTf`v*B6Q5lp%Ha=|`|!HrTZgN* z4C5wH6(~n&2VQA_Jkb7(UXpF4Zb3#DtJA7oXIpfh=Dmz`QLZ3ET>~kh!(^I7L#8Qi z%WfrOvp5#aTNiEyqxg&B3?Rnt7fLC4^@n|HgIUhvC`(-zFG>yw?%0x&keY+Hy!$WLvd&4UyC7U*iGYk=zA#ekHQvx?o3~Um7i)B5O`@`tr{EQMjvCgBh zAm(7#P6c4VQ%4xlAA&^SxHV`9$&7RnS-{q#rUYQ2G*FusAZHO{7GM=W zjCix4#Eqc?xiH{Js2r!%_8(F~FQM-om3q2i)N{G9001lav1whglZPwbBbLd#wy#)U zX-JM@QSZaJU~mmkaJeC047gsem}aaBtJFf`1Ku=e(G6Cd&XDbeSLPmOV*v8*s%2zh zP7@n`9xd5<)#d~P7!;%_3|g&Yx6E43UQ@}Cwk7+<36?vth>zxI+-}2QqQkg37^(1l z^L)DP*0P~CjOZ?)9dMR^j!l=x>mUWdDCe^`LJ)i^oY&_a!+k%Ea*=Y?Uuxy6YHgdD zz{1Js;bzyie^pg$Se7Gj`byQBFs>rg0myAj`j|IcNgPqM=)FHLsn-5Y-SpZ&)UzS> z!{`^No#uY1ZmymWoYRh0ABOkme9v@}CdeWQV@7p1ZtM4DyNU;y*>pzmW%Tn|{Giqiw;m`Cr*WD; z^f2N-ga!(Im{p6)nGU>!Of0&LH;+mjDivNfjbau1Gjk!GM2jLer=T9=V;4rC71Hps1sEA+52@_75#a2nbE_(zCj z1`}jsf^EHHs1?XhFw(`z2($w6i&4w9#GOBa=Es1?gM_^-!~wdhj#dPQ59hq)5#I98 z>A+oggLRwM9@ASTu)^3N7le#>jyXU|GHdh(j*tR>My`LZ=0SS~C!u>d zdW%Ch5_wYxNuxi$YRP2gOSV^983*7cH-)U3%a#F=xuWd0v%dk5U5s?zh96WYL3a=0 zM5;2{8O_~eE2|4wu*xJQSO!=mP-(_RGN6g&K4~}Y2^hVx&@CZi8p|KR8F=L8t_98^ z1tW~=&H+17P3XbiG>Da@0!hlbRUlXU9}SdB`&dRfAO9Cg(rh-R08I+brq+lTq6O(} z*>ye@W;UQ$E24xvuYOtX|AVOLD!MUF)uRw&h(Ml81x7OV!F!hM(U^6I_pG#0^s{r` zzost>oolLYGQ!1Y3ybR=y* zD??*NUKy@9Urw+vju9iOxV&vxd41LO`)6??G5H$IKzOopQDKO+`PeNSE0YT{WCv&{ z{t@|VSYe7BuOQWO4_n_T$zoiD#!(8P|6NaAqyGiu46%)ji<%pytnXo7x1ZH^4!Nj| z3k_{PT%t(pKM2ZS zmGV-N{nD4^`akDai2hsmWzp=EN)A}NjBo)?idsMePH0O-Q43J^8Yi4E5q>YHVxgZ# zKF6*W5J|$o;7&OswqY7 z9+P=%jif)9_%PZ<<`LQt{On8Kz)nxkY?ln7!jIkBStH09 zfrOiWVP?4w zBi%UlKa8H_{j3F4MIS~xpY)`>GDlA!NuLtdmak5HP-6_g?+**iAl6}AsCpvDlm{0I zLUP3o=9LCK)N)JYn)=iHFmGL;J{j%22M&(vSLveaJe7$)jDD`wN4Uo2J}|MNkYD;g zJLbEzZc2ySe_uR6Lo-8pGF0e1bz3H3hUc0gz=klRL;aaORK4kiC$C7V(d3ko`^A^7 zOxVq39Fn?Re*x&6+FH;Fkm+u>xrgzzcD0|A>qN1*e4!gwIL@KyliV`-a&gUqDgPpv zURh-Y5&*q{jChgCCie?n;N!MQxlu+s@6RGw*HkUAOd~tHKJAZ|`_N=-nNZ5TI3%E@ z2TM4NdJZLwgGNBPM;=2p(1SQH1>k^e+`rWesPro!9hGqbAd$ArCv*5>P2xhL{0KQT1NaOzflb*-o1hAsp3MY}`$A0y!}?G?nU zZ8Lcp_BzhPHrw_;G)dQK?0ZrTRfce#r*4tno5XGjd3O=9gaULFs>0-7p>ZY2q<>n6 zF4p<6n3vuQyu6i`I@p2`hTA0R!nV#QTe}gW7#Z>6>VdF4&37CH{%1nEBCE-SwC&6A ztYX`)1<(#gb>{$UkZhl6K-ylV?oecOX``HajX!WeJ|EU%2|&s+^2IU+P5xEkTZDZz z(AaZz82KErk6_MM&wYPaL>Xxn%BbheUuqA1c7y%)YCGA!2}W?|B%5I7eOn641H=Vf zUo-9WBZg?gepvgcbZTX!b54T@S9zK>)NbM55GEYpRQNd{aeBfh%T+vifsA^NA!O7! zhB;)@D)Cozw1jK6SJ%=%oGE!AC zZdMeiu`s0xOA#zFP?ZPeY+;+IuQpId!UlGH$Vl!S&Bvr$s}oJZD2cN_{$GQjudPikFcuay)waZcfs&ppb@u6%hjD%4;84#&R1% zvtv<)#m46^nG$85XH@rHEh_|dZ2cDM2#Qk|^cVUDUx`yO`o%>6Rt5oJBB6R`zjm`Z~9VvSa+of+$DdT2JnUWcO_dyC3L>x3zUG3Z563$L_&J2il&W|TRfES!3+AZbVbQDP9B7wAf6f>YGP?P1BF zBdf6|8Tlf~WB9Jl;ZEnmP%SO6oA9u`t0$&0gX}3ouy`Md$srj&d}X^0_W!|(!szFcAmB&BXqHCkVV%M!yVYQ{ z%i{KluLQoL8sw+Z+;Q<(1gYQRHfu>$p!%`ONEc}1L|Gy)29$zK8=RU_WDNnjCIaEz z$}?|j>&m#GU_@~CyIc|Xx3w?JC&j22XCnenY19oe#0>*IVi92)b&F2xt33}3zM~JL zoJZ!#l?7gmf))($VuNl<;Kk9AUKfESvoT3#nyJ=vCecI}FpaW78dBE0*{Iyn!pKtI z#d2U@_V_aVg_Z&*-?vEMzT&y4!co338LVX3VFhb;)NE##L4ZWbvr z!HjW1p)JZ#KOr-PyBbXZLoqdq!J8AruG}Vy z=f!Yl*DjhxVHoYa`7*?sKiGp7?Y-rJo-v|f#Pj%A8uN8b;?c26V;VwqDw@nz<7~ZR zTU;R5W#o%on)LlkwtG*B)rMO>EJi(_IuvJ*aD-qvhy`gI2F+&Fzt%_Pcz@RpWzaBg z#A)H``DP_d?QzT4$1vh~7aaDQ!E#AY$&Yaa+Zt47lcsjt9&@S8{E)TFi07=d33l?) z@sFCP6oSO^pEB6dW2R@YMt1FRAWkg9sOQMKWVg!a)YLjBEchn|sl!MYS9?IKXAUS^ zu3@QNXU-qNk7k!0?0D#0FSmi_tRF@`SLuV}<(qDDb<`xk$UBzN>iL$1oLr>NBcqkP z2*g1E44KOqM@Cp~Z5651X-2sy2r)tG<<%ymntF$0;XT(%L)^v7r6u9I=mPlFW* zSsR^BNpUGseSmT~94j%y8tE}#6pW?;*Y&Ye;V^X&=PHt86xf3{$H7Ymhn%Lo|^qn)z`!9oqlZHy8{ zxUxgsRx*4>5tIZp|Q@Ku$@m7FzleR@7EvAhGwrD z!4(;jsyKG*e<^)!x5=sWg;C;pgEmDeVNbWY_Hpz_N?*V_B%hZSv=00MP10c?CwlDG z*3g&}4u5de@JI6xmz}LGbP?mD>)ghTlV#)!q>iG9Z~m+8w%e-CWf3uP-B>>&l2GW^5l1v47Cihto(x zMvYgWFFkIHN>4H_7!(o+$UGT2BK-|1j9CcNhQgT8lZ#XUt%Z!Rgp7;Q7mS*vPkq>6 zX$*r8mS0lKEqR8^&-HFE7P7iww2SRSfIHIu$zk?yk!PRxoi$K*LS#*}P*JeR-)Eu)+_Oi|K}al(@9dApNn56rk+KqW}+a9_7f zrga}=1b?o1pHln*GqZ1kz*H&s9>z^wMzH%q5lg4GN_WrvK~73R#_piXQ?l(;Fg0Mc|3MR=cL+dh-wK;cNe(6lF&l@eHr;RG(CjEiC z*v(>}^WrUK1|3$fNR-@EW86<0(7kUmqQ5BQ3ROPqB#q>TN>HxM)&@k#LpF{KHBz*nqV8o1%Ec5>6<@$m2pA7JB9=>fC`+u zg*#zY-JE7hEg7IXta@&dz{z5i2Kf$g=`iB?gmeN`{waI!_JS(5dkRlmfQp{qL0Mw* zv+x#>rWm`1>M=y#+L}8&j})UU-ohB15~psViJqBl$-GhvYMcg&QWalcdYJ0~_y~|D zBq31Wjzz*Syr8ov5r92{Ld~p0xkVXE6N<-f z>ki>a&(jFu;v{nj8o_AWX`vo8jCMXpH53-V5UT5}u=6Y+`-uTJ%DLD6Lxp}cyMN}h#@;U2oxnmI00X_S9+iSpa4K%UGJ4Fr|`JAzc9qwY{f<=pd6 z3tLc{eQ9$>&7LEIEE5@$<}@O=PR3O2EfXeV8jNK*Ok=hd~K zm=}QPPR501Q4$yJ6brX&lyxk&fv6^YmgvZCz}OxpC#o_eJ$LLDYN#oV-YSPhp?={9 zHI&7u-0-W5Xx=Q}vcDPz+$+a!!K0QL&)5#F(&+QtY>F_l2JrShkj<;3T7nTSvP@<= z``kV*!$!vq+gjAoX#bvXygGV~IwbXN8S$b>!)SCEsORDs;tvQ(!-a1*t%Z|_hOY%x zARFe(Vx)5xlq9U)#EXW4%0SJ3L#MFPi>LA9S052?jciOtJ0HscD>_-b8GV6v1J-WT z-qnl`B$Ru0xQRc4ekKEn7raGjQh#-J{E&7%AMcoliNjCRfqrKVAyz;Zk4 z#9C^>Ox1LF6v`p&)zm`(jv?bFo33>Ya8XyJil_muoW}rHX&Px-Z`e{JASAPOHc$H$4IZh%c(9UD36_*XSjhQ7-fhkg!Li zX^g>l9t6M{OITymj43}!2%6p~$IG~o@JUTXyLwi8FqN{UYaq$gRtFu^UQRgyIgw$R z|M|8B=&S7`1;)uW9LVf}mqdy*ZJ!kd!X!V8dQQ{_x_atVbSP4jGM^0fhjc0uQbtcE zUBS}QO~fb{sIx{NZ5E;s_Y&&BA|xinn{HhG+j}`#G|nfNaY4Z)U7F8Xg}t0uZyJV$ zlHdaWMa}pNo%AHN^umc?Wt0ol0m$;tj_rQO&2|n)wv2c#j{&IqTT*SYFygJN_k$5G z5+5BhNf*2wIMR6hBQ7gQ5G!5YRa|B?QSp#*!85?v`6mhQ4rLhm>Xd^R!txh2H#qda zI2Cr$fa(!5k23nrY9jDY8x^ZRS}aqV8WME-`<_A+Cm~e?jN&dJzk=mz<0nES7jrCbT1qam6=zpLPTSMzVP zgP1S-|FOT3jB*ZVCs_HUV_%77caglk4%u9-~gO18P%XBzKpWn zB2Q6g0nz+rF9FJAX(>#({z3%3nN;b~)HNEru*J z>dl`0fx@n?M@4kk!n$Gf^Byf&H|8>QDoO#Iy%Q46rKs9pd1 zGH)2(UtD;B;>08!vlNP3-J1ad%VIc-p5H9x-ERE?C>Nu;^E^6338BgiwM;jt8pxwX zX$jSU0@<~YEy~MGieQv*j^1Y|{42X$YBrVyFrg5J(azh488GbFv|$1#?G=YoHF(PK z@Q^N_Zf$oV$~TO94u^tsarS7VL?*}VeFiV8*?Z04tilX61X?dL@&#xn6a0rUB9|jc zg&h@kZe<-6mJ#R<58JE#y=>*nxaj(8>LksfCS?9ZM@7UfR+N$}fn9#wmO=n2Bb+m4 zK&=?snx>5`tpGt`oP6Ohh`tU+OLgsB>chzAFf4A(Z-Ctzx#1sYI9M< z#U@Qa!#@MyZWoRr*0k$=8W%H7+$=*29e5pK{t!b4mL)NCM!Z&`4`;Cd4kMo9406;h zs*xs3CkaimF9?%@NLd8PT5)`)e@3&F*2h{aLu>>@8A_q8cX1`pRZ` zzm1jC4^BvV|J*r0({FhY~s#CN{uC z2`ln*Alu8;RDq0ePQ*n4^ZU41-_|pW7&)VdRnNIhvuMp`X|v_rq<_-kTT>srO0vkm z9V1vet#DB;2UuPv^%#ha4he7uqtCML-3z1Ix8uYhNSs!^s3F5w{&nNJ{lFd}bmym) zFHQ}x<=@P_Wjn6X6%7GnwR5DMlxGzv=f742*+b<3Flc9dq3ESPZo5;j9?QF%4@_b? z>$x-=lxG%^B?45Xb4>AQIks57))uGLFJk2^UO;_db5=E4W$`)TQu<3#*oOGHExg@n z#q(x7RG#1TK5KprcfA)u&awJ=n++UP9JgSk_5~+Ep=S&g4v8RDx~vJ4^hea2J>Xy-0L=V^9b*6ZwLKlj10yVTv4g?*ebLb@pdsEY=ostStbFr*k!xL;KRY5i>aBG| zBZZlLPUNyT63K~Vj%KaY-b69ZW1TmbXeJvqCG}aqdJBO!bGW&(KPw)Z{tUVl*!rFVX zlIPSS16A_?E8PU~_HI*~n9>|7iy0D7kRg_`*x^J7Que)M5uv^6J}gZj96L_m)xnqF z>Itx>)z8_@GtfUjBFmvtBS|R=&z##*J=hDY1PX|5TIHhE$?(J{tSGt1aTFt-EXv~N zjxD5faY0MD^c|xs(p9%DHKc6!*@0fW>MpX0_6WDdG@K2%Je@Qz^$T06tKpy8(ZlLn~?%FKcl0mq=?oFFb3)Q0=0q(UfnSc!7f zvE%s7ZIzxR+}u?l-NQ;ZjxExP^HyT8%Pu1rDJ+~Bk$__X=lVECma|RkrbmXN$0t$r zlZ96)Sl4M?Xgx8KQpBQ9vfnXL_ORf!{L6GV3P7>f6I%oy#QKGm&PUHO-|IujvHO=> z`?P*q@gl^t?f;3s*%%G3Mn?bow8}aA6P2XT)AG6fY2c4C3s%4Am05n4Rb~;Vq8Nh$ zWLHU{9;NyA=oOedvvp(0x`CxIyq4z!XU`c03SW_hx;ynD2{LEd$B_H9E?59_S8}hz z(k>d2^JtW%4}QL&mF6D5_PE@=vf4$vxyK(u_}2$U1yTWRL#yzjw?as&_ngg3Rw`(@ zs0t_|sSwb1$2&||IBE^DE(pHB4S(|cO5^lf}vGRFI zywEfgw%WpXP4)*)FjxqScO=5os^|Gbapeb9sPKH^OtE}f;r!q#!mxko zp)bNqxl3K|*Q^}Q6=Db0>vIzD?YIcWFRPw+hl~566u&E`cxzH85iBX3W6BG=N0in; zgW?q6ZI$6F2=|Ms5%KkjA)71H%I8pr0@yfAs6!5t#f22Hk~?-?iVA19;}Y#`iNgy1 zoW#3$v}R^D-U6*MyBX}p9osqDM~wgTs_kYNHxgDqhftELgpsS+lFA6rN|7s66+luO zpK&|(wzSG%HZZH5<711syGL~z_Cc`_SDskF>%`)2`}FYk{1Z82RyyY`FSd`0=3i*| zXZB~Qe+AxD1aEQ%`|B4HjLD*!-GFsa13I6nDt09NcEXY>7qdXiwwO#?Ik{Hm|B-+T@Zm4G30&_=7#jV=n77$4~rqI zbH_{wu072BD)Al~A(~N-QhamEbkS*6T(YIltavPs<32|} zgQC3im1PdHazuC?A}MEu|CnPI%%hI`@VOn#9dp~mYW^bD0_`5B&-$PhlR|4L$L68v)u+c9Nh1v*&$9I90WN1lBxC+SHbQxS?a5_GSUOlXhe z7*kzVJ=Y$EFCqvuOrb?F-cYKS99t3_UUx6IlxU|_E&`tT3te$~UUaohpcI^WEPu}5 zTP$|?q5RNaj`NT*$GQM|&}jGu#l1GM9o%WiOPN(K!gwLzCoDXb=F~Dxj<0TaqGiNl zcY1CJ(Cai9W%YBam?9ATXd(tLDv1K|cPnF1GsG9~gn1*C61)?up0j8{!kEg`+OtsB z{tAg1H%jFR)>)Ol%geFlrsGWm)@~PT>pMey4y|ZG0U8jp^39T_N$IAJZ?~hrN-Z*x zf!l*y7DITk%eCw+Ow6lY&DnZ$%iOT%E>8$i@TJ7dd=h+tra0yq5`r@75q6K-p za`yPXmSSylD`D019wJr!Z=`2_K5?VS=ZDoth3n99{bk^K2YC^ov`#Io3!0IVz-vu* zhTJEg7Qi&I@kPg#`80ccLTgsX2UfWV@?cx{vr3$5bOMka{MpzoG8qasJh#pv5_GMj$>*XDvE53GyXp(5_RK8i~PI)D4VNXG|V7ytqO?S6|r zw}ZZUSk2$O=Cr8Z;RK>{LpQujSCUv7PTU8)WXD$uVj7UuE@Ek+;{SW5vWLelA~SAU z7ZOkwC;p%e@!U#wf~7tjBj0uoKPn+!P=O zRGV5_snnFvPxI28WFT9U$@_V$w^T`zA6VtQEsl`z7vss3liD+)6h5sB91m26LFgTL&=-*1)}-ItE}mB`WM*uM%LiWO#^}(gJ!h@Zzopi8IQI=W_tUYJBab z$1S(C>fu=Fd>|ZR`IyUk-Y@_yu*r!>D0a<*Jz-_*ZNSyBg1o48IC#)oGbvh%l z!Z~7^Ce|D;^%Sxg63dVbM1^;5w9B5tbZ12?ip8quC_rg<^&vyj#w5Poi;f`-dOhCG zrdKb`4wXJ?!dUT~-hgp~FRIw5kk(7kCm2>fXGf=1m%;+nCX_qj>FWfzs1^;LLZ4oa z+o)4A(|WUmIh(3qsFv15m*gwQHSz|zNo!%P=pc;803*2UE=c=mSbnpW?+RXEs4B!| z<%@12C=#_$^6un0vz&!rpdZce&KNZBGk?= zw|xY$viil9)P5P44*NaR_E$4pRy*evQVFgP>ZT%|c+Z%05)KZ2BMPR^^V-3T-t4ey zJ--VZN7mFsA-4v2Z+Rt^}+33tWjE zjyX<1OHU-3nX(qOmc$c_dU#i)gO?P*w79y?9oKILfE`x`Z~sO&FIK!@w^L#A^AqQn z<2J}~WVLf?)uPViM};;%UpQMrF77$3a*_O#V3tt|*IlO~fLG8F5tNXk#q)vf@@G-V zV!-6wFY#ksJ!w*X!pVvfGgu%oMJZgE_%Sh6gzzNpNgUn?!X(&G z-5Q?zSz|ArpUeu|ORr;yh4? z8OEv20B7z>4zwAEb)gsx9Ot_izRM25j_9IT2&;y3#Zz>WvYIR~XE`V@bAd;`suxao z@;#eQIifk&rWMYw2ce=qv|;-5g+VnjA0{iDgAPQc^HCVyQ%fOqd-1+ZE1b8Ks*B%s z!?yQPbdY2FX~px#4*XTV58>@PhBvr+dmEQi5gIEze!g!UFUD!X>0WF%0 zLY*az6Eo%N9=}LmmuaQ*tAU{c<^9>xLij6eaY2~DUxPN!YXm>o>u^1|VR?66B(2;n zeOwEjK}J;@yc!uGmSFnp?d7(4#W`3PQ>B%|u+DoQQu;yhmmL%1a1RK%8}?$38T7Op z)=ev#O62Et^vn%~Sc(YUhn3DFJBaT;*`Z&Dm1XKd)3aF7Uz{3nx({e4b5S6MfObYr z*ARm!4c@KjkO0rNHmu;!i?eVFeM@uhno^*B7L=}F<%}-$Yn8emE>q6DNaula2Rs-#d zb`jtWWlWZvr1p;AlX^RTTID>}(ahN_R(A0#a(wivmL8=J`~FXel|zeF!>(BUyk)2) zuMU29HfC4RJqWv*{_H+d*tqu+6g*iIOjz}te!K#FSLY6O%nWH~k|1}J76p?d|MQ+R zBF!S5$GRB)tE|{LDs7*an^AJJ_6iyO8|BFOcB_t(tP2%M1~fmb@8Q`=*%p0Qr~^&4 zKM&psTE9k?H~yY;1MJna8)F7Bj&q9I2d}^l zjezp_t(uM>R=l|X0l|M#pzkSKd%1D2ieU8%X%#a4Z?sT){E}t(X~pwCM-}J$ob0e9 zZ~)K(%yYsIMHTipUnwa{)(E_;az1WQhdlFtZsDhK7c9sL`k%GhT{_5Ic-=40RO3F@SK%sZE2)d zRyv;vt3LqXpWD9!s#W5Tb-_nFZsYB_#XO0LOe1zKdgE#He7{& z|L>{YTDIHf#GEs%cHT{@8a$iwixoz{L5>1@qwOc(#wg{AW+@+flwM>7e?ECvfxr93 z81C|*+;>Sy%p>8juEH2%jN-nP70#Ot=<$6uW*@#`^OQmmaT-=G=NE(E?{(qsDXV7~ zo*@#0E;VRsW4DB3v=Flh^k|kXg!2>2mTpx%Yq1RkQ_=otQ5H3{ia>ei$lPt6h@xBP zIk7^x2;hOgFC>~*i42vDEZ#+)n91!YLBm~AVNX^+@4f3ntpgifiyttsTJ>K{OwYV+~!{PCFdz%GzNx zbHYw)rn34u9E^?fjYHeWyVyVpw`oOx4(b3b!W73y!CeUAbA;elFy$17T++S{kqOYw zmDSH%;I!qw8cNSC44g_=psWk7QWO9QO0|)kT7kBIn(E_V9ZABdI&H`F3R;_1ya+oe zZp2yZD4i;n=I-I^(%ii#!hNoPI2A=BElW}7spGhihIShUdafW1q3w_^v1UrPdM)l^ zQ{zn51*2ruY5b+^utz##htyMCz*zlU=T!VrUlJM*CJd#<1Y&+z`JC!d^cWwZ*{&)w~*p95k|!)wlJO-$+(N>1)H^K z@FjH+xDuHZBV(j~^zWgfQRM|{pkeiMydlI8GmM97XGHZDbuk%E7#{>YbZ^IHRIITs zqz;G_qnlm$G4>Dvg=;9U{<)$etuJrKx{t7Gyy)-<4D|sE3+`Fd6%t-ItnAN6hHBef zG}*#RI+$?LWY@B|XrhQTcD!X*v!|&wt$u;u8K|%S9IxD{gCxdI&BSAsi_K&i!1qAO z=5@kd@EWPbiWkjr@D!gshyHodkXeh;8!KO=rj7cbsyy|tQ@OD}f+Dh|T$$?_uRLwX z)U#5XR=KzmDaZ=$fM3zufOZ(*N#N3>arXF)E|QhS>G!`1`luVNYQv>3I9)Ehh=@dx9r`0YBdE5k_*v?&jNUY@XbsS7q;o?9_C(=DD~ZmTj4hD8{|sSzh)ELh0w{OVpTis|{n z&GHpu09hAe5UQQ4mco8j?pg!L2#3!_!oHVYm z;zg1OIeeU`7L*gkU)6KfTox@w|5orwzC!6#rj;)skK&N{K=Atgz`+OZjA2=vavt(f z8vUg24*Qr6!TyP8am=!HaQwi{JrjqvO`;#4T0Lh@uj<}|{|N$1VfAFCb87e|D#v*t z2GLXy>L6@Icw2(x5T8?;X+Md>$ZF>mCc60FfT{d)+@ip{vM%O#=uLiSF3&C|`jRlO zta6TeXrj9t4DGp4EfanS%^2Z_Qh$R>EEZ@%?>8x&KhGbUa z&u1sgCt6n&ADK))uRb(K*?&@Z)xd~MsN|pmTvYeo4{RZP(p@BLXb&7ZPCpC) zJn0gB9?c`l>g~dD{^fSq_hF{>!%bzDcmAB|2+EW1F7f8j!d-`BY*_Ui0@x(H<7YF^ z^&!n}sR`k2`=fzX-YIeJxkT|?V&(JV11uvHpu}G} z=zhzHin92I70>%TO^Em}VETT~78ke?!kgv8#VIYe+b`DNXFXT+S=_YHmOgh}z7@RF zR5-@1Giawz`D?P5*Yj= zBi?;+ixv7TDx1~aIq`psKh)wk)FX8Op7M*8&Z~Hml=%p0{T7u<9a;w=jz`+HtGp}Z%& zg{*pWaP%KoG&a6869PgrKCE^QY!NS19rv&;BjUBHNpaTCpF*jJY&fG)PwQ4z4Cml9 z@RfOh)5Mcvxqj{_X?96!Tdqcevc-SRU9Uvjvc_!uspGI3#CBlB1{mH>EJ!=mAhrW4 zyiUsOL^2qrb)jX|K*fKtq;0lR+8tfg%d*PF%1WR(XMeazXS!Wi+-f)Ln#r&ZiV(2*GfpT%Ks zAx0KLOFC_KN>c!C|Km8eEFvnb;?5bR8xGQB(L^>naXlbPHU_qXB+GYr2i%}}5*b

|O99qb$Jhh0*BpBY|Kr!LL509lS@7pHT1^rAtfg68oJB+jEV&IeURC*a)?&AY zKo-*~7gb9N=q@b$=LPWu!(o^3^Tgh+ ze!^$07|v&D2`XZr17eIzCH7H|Ou9rk(gh^lh0+XttB^FZ+Brg;5F*4`{cmIZo}xd5 z-mq#~CQPApZ(tA@<5Gg%+nqBkH|ZM8nl$QiL1WkF&uv;Xw7gYDcX z10s)gL6#=UqA~!5KzhG+a0*`R!VHFMtif)FGSc1c*G@Ar*vh)eSn6V>>5NB(Iq{&n z78i5pCfMYxcpF_bS@~iM+a{b-ycOx$ramPJX9JB#@hHCfhUPBYUo%eYrbSyhlKcpG z91U*!n2lb-^#2O$8W#(w5t5ex==`IKd{0-DhC<1?j+)Tta6e33#&QW zvzB+)QK#%f-rhcN5DCI|+neAB!>Sh*_{JRgWNC2~R8+J}v9ejfhzF{fkIGTDyT6dT z4J%%xEQ*-(a9kTaz68+d`2qqA0ebC+YQfGai=;VCWVMS+Sfud(tq1qyN*Of=y=bfp zrC~TRlb>gFRDCK@ri6XX-Z*2z{hb?H6dMtKmX*Q<#6rpECpp}{9Be%YZE9KNBA&G? z^*exnQvX~bW?a^V;va>fIcwQK`cWwc#6ru8S;jkW`ohY-Ql(szJYNPUM`-V$25^a9_(wCctA(c9|%+x=(9 zU{vov@t>skU&qi}eH?>+sxW%&>B z4@oh_S_0ZW$Ag#SX2JH@M_BEAIrII(D0d)F&fOlMNLSKmXLQMf%K35JV^ARtE7ju- z45V@P;KQF8Uiw*Mr*6S? zoK`$1Tk7IC=wnga60T~lfJM^n1fVg$>*1{g@gfY1lEtxOu<(NuCrOUR4$By`9?Jd+ zC(Dzhp?fK|ZCU+%s)X_GPn6|T3`Z1^&oZnF4LtfsaiA!n2^iGXZ zEWrE6j@!hBQS9%~(q^qFJ^}J&LP~AAREsh#_*5c}bupt2F!+bk(#vtq8bp)T&p~No zSNw$GJ&l&0Ae8UZ%ICs=C>y6Zd(wd5gtM^!V$)!0Xi~b}Fgyf#lEj{6iSX&vF$M5B z!)p=c0KwVX8Z?Bpfjn!^o9=X@%e3Of=|OBWX0$XwYxh0e5{z}cxFz z=PWy2lQN5VNk9>F;i`y@{<2?+77()|mD~gr( z{9*#}?q)lD+<#G$)+4k`k($QNN@*ny!0>1iUql{2(0y6;jxt2UY`+jRHWiBftBQxR zMiNF*j~+JUa9q5)2D<%A*rp>P>&LX-R zR=L5+$)L4J#*&7% zh%VE!xa{vq1h2X%sL$>(YHo5fYXr3d`uw}NHq!V&hWsbcNxUiwxW{c!$eSr+gEv&04;n7gX~jjVnl5Z99$gbKE*%i@3k z3rV!ZPQ?fYTen+it?4ddWq&^4(e36D)tvptd*aomFz-^d0H1b zEz}k!qc)R=WF#xofpjbU2xoLY)=_FI`|cbDuCv6s)g@bTB{#9=KrQ9Zhdg_Bi);x{c2QZ6f)A=k_Nu$;Y0o)L zElbK0SQh1-ziQFM|F@EdMFHDy3!M}KD9~oq3>v(GQB#bi&|695;&pn!ZrXL0 zniVdFOZ!6;|9>y)C#)?L9bBDOxoCR85fb1470G*Lq+3S_QXj`{C_7@Mi&+||bUsH~o~#A3c1dZ!xu@RdOZ|mLcg*wkH>5nC+rAY%+BIc6pT5lk?1sZG3olBL(BGjR2D2N z#q(ntQTFU6_z=w}&JIZ8b#^#0I)}$Em?7SQtb7ibwhj4RO?%Q|+uEt6X=Q(LNQ2sm z6U5WSZ-XSAPDJ|)z-tiSB_4{i!Y#|X5PImG4Ig9a&m4Z~&AV9Lw8}YNx4$>aJ58@gsK?C1dhfhMkKi8j8Ju@~oK zo>n{`TPE%NraaiiG)pOv4hhq`sl{{UPdy&8Q1Qa{jzT;Md39>@m+cpXEk}l|em+jq z6%ALC7A88opp-njD5pHc8eRRE4Nj}Jwi2U*va&lT0qS~y0U|;O#f`76a5{0Kgcs{E z{5w(eS+eTI&BUNX@~c@3qS3ywCH+Ha+7_Fxp}HM+bW8fMd_3oA>C*1}k^z1e7wTog z)XKV$Q(v{W)BoF>+} zzrn`vM0w^d7hOiO@Ezi@Y&2vEw;2ZT9ui)@;{mB?x$5%2c&6>m5wRX z%&|S0WPpTo%)l>LWPLn3VU?;%%W>w&k`kx-F2@;DcLI=%JsgKJDXNyDa3F7C{9z-e znCx)kW|gJZ>8V?)T4VYE5_G{l0D49tTf0OkpARe{h`y|JESe_L!tAC@9D7pY4$Pb@ zVXM;IdIcTemSLopmCjR#?$k~CfB?Mw2K$TX?7-^BA$+G&w1J)$Bd0E)XKIr8LStG* zo*h>f0%;yoRyb~4cBj6{2S(h#{MIrec&vD=PT!&4nFu0hTbNl&5JXPg6-3k|HP0k3 z?yANes%D9A-gN)O06fWIsodH{77BLf&kH7gjHX%Y%P516$SR38+gw#jPGLv0)upPb zaar{ks?||co>Y8xP>|}1iqC<;gNiTrkrzFVv&FW4T2kgabu8rdjCO($tF!`CkGA}H zGFNQB%mC<3W2NIN9tE34iAxYmpb90f2K}JKtv-ZzjmOT&?8f-ES@F2k(oyXmOS&@3 zThsw4Q(OGcz9t`W&uUweRI^xgv5Gs+SIjTRT^aD9I5_?7F93uanR*r5_PXlP)y%;x zs~undl5_kf;eDd_Zf|64V6$v#U3}mALwL6jjt-%ugj=x6aUI_Lwr@$ieR4FImlfj3 z>c`oc`6bZ~y9^IbojDWMGbmGar=P3A+~pejvhu|S9@UDGHxxJY=)5}o?ayLm``w?n zAvB;GCYJZdV_Jh8>TBR}C&6}bTkad&w9Z91xPj;6|Ij z>>=Uuix43Be_hj-ktc>eqz4A2>@U>ptE2Y#4gsRQXYozTI-l_nh?NyQ2;w!RYe7$d zVa&9=S5Cbl$(~13oi?tx6;#EKB6tkW!rTw2k7y zTa(1Lta^;Z>u{cCKlwD9*u=BtEz$9b;RR^Q|DQJv9K+{nox_$oGRNN;#Kvj!v`sTq zvf@Pz4@CSo-_l;xXt@bLgmpm?-+=({*)%4o>zGXgQlQzi^grrhE!#?_yEv?T+-m6v z?G(Qx!~+w7#Zo1^vi=`wXO<*6k|WXYxQvVK%l$7lcnTxwIU-Z^G3%c|R#zp0q%Bw! zs&-cZVX834+%=v7U3pcchjkM85Z7o?mya#(qNx(VZUM@P&NS6cd@!KzL~|UgC>-7P zN(X5bONWS??OJFF@`r@*kgCJq@7Ycm)#$PEw#vfK)wI{^Y@4?4Y_o(3D$7Q8$^w31WA{7tig9zZ0@D@(n+PZSYCxxKB zsJTE{^JEXBL7!Jd9q8uw%pSIju)+N#p8s2X*e>5(qV5N*yv_75RRUB+ync|$iV6j6 zEoZW~%yi4RUvonsR>39KJSb{4M4T=fKuYU8F5?VM0sRog=WS_r0W4+ZgHBpQ`ff?n*P*~} z*v4%l2l~t+0k|ioZ3s{4ZqQ)uLEh4+cefR3F$^vAorFQ`@JiE#hVE;)RT=0m5PkN{anU)av9ws>)d#j8l<*zMb@v|>_?<)4TL z)}i6wxLe$?&5JXUo-cL5X{VjQ5I=KPWznWZ7(2fM4_j=M;FmQIqG`^%?y5&AXyDJ% zq@cgMKqX@L@!bx`nMyQn?W?7lTMM+}(hswkHmJn|t+W#_H>en&`yZMf;aFsigSw?X zYFD;o89yYb4dzfNy$grdECTgBCE^(tVo6p#h~YuRx5aDOCFlq#egjbq#MB?}mRkU* zTvEQQeL>twpFP(_1l;NU3P#LM#W4|V{cd_#?3t9h$!go8Db93M(?W<_Uf&2jC_#|8(9jREI0rJYaWzaR4`F64QR(+fJU=EjM`DRw%c){ZW3>q z33|#w^?zAMpP6SW>eV87tDdP{w}swTN7ebyi->wR_Kd}87k9mlAF2*s5GN5G!m*BV z66f^!3sK5+m)Rm(P~(=YZZl}j04w|}orD*YxGB46^D~v`eV6fl2raJn%KVNkCyN92 zNtMi_o%wwY7y|x@J{m-pln}t{BEee^2^SiPLxB@--(|k&6e+gXCTh@`n7#*!UBv^Q z*QccMZ$U_dgJ*whqHg!f;FQ-6K}gsRz6SPd|NOHR+Ld@EfKQ~h-4d@(LEn~9E>eYc z{nh%%eLnOfA6(}G-cD7hSTs=)WAI80+{t{(vL13G=LDHj4hMx^GWXX;(e++omQ56B zbKeF#ixsyyuN_c2&=Yo@ga|uWWwWq7SAK`f#t=L~()JMUbj{G$G)nIxxBb!=&44P z1(*kwA|Ugim6P;3?cf9#O(6qp2jy!X&|rUSfQnEn`gIYvTG$ao9 z#lZ(90BT-jvcD0@tHHh^H>RPL*mW&04mb}!T_N$HfvXS(35 z_=H|L>gU{tvT92A^+B)LON_8m(YE|}KTCmL?+s!x((Q5zU0RWqK6tmNDJ-mTrt-+* zL7QW$01#C*3fC&KH(QfHadGa4(g=-s{%McJRC!VU86k_ZfB}pLOzr)4>Qm{hAO^ed z)Lx!*3{Kc9>+~l=h5JdVXNg>>*ZszkT5#Q| zNt??BLQp1lCgNSm&|F`%Ti!Bs1&(-d7{#B0qU$-~OV#vs%LidRfKhl09NTA!FC>zm zA>J)J@}1IpaldlK#>!>R&;99obDDlpGR&9LZ23jj&#~Wwq`_9>s=BfwCr=7NLZ#0P zwBKI%TwzK=`8@g0x{p$&X7PRmwsr2N6guP*_H*pZ%$n0*2Km>~~z(y-U*C-8I~*Syw|h5AW@Uk!2U{WDOw@>fmj ztD=xB`G#zeIBlCIak3qk?ntwxDy*?Y>=DSmbw{q(TdKt@x_qORn-#b(Iu-8%I+UXOcwQd4c;&l&oCzZB{~kHhM2BM#g5^?v{`9BgthH7 zy-!u8bqEqwAg0XEx-IE8>7~A_BivO@q&9%`4T|~u>xj~5UUF_}GJ0D?>YhYiUq%%7 zcD$X6z?h#06Fz)H+O(?C=e+nehWQjj5l>vMMjKA;46I~S3`FeTF+9;LXU$bDVkm(S zg`cf%SEwus`5PK^g=Hd>PmE4Cl{$5{uMGMog>^R6Sm2q^&$$nv(!tYK@5R1g6RM{N z=wRU`nhlIpUaz;p%VeiBKl`>=ojINF6~~b;pEJR5$ths%s>De(B&K6A|08Lg;yd>8kSWnvQU;sqM z&wVw%37zgcWl4!w5xLmK=0E3tFFcA{`6UCN{4Co9aOTspwZ1t1EB!Hg0ttC&>HVZcMtC&`7?34w;%D9;S^ip-6Mwi-8t?q(#N9vYV!5XrJ9%_QU{ee+$ zoqy2iQY7Q&ILJzYc)w1Fl(k8j&H(i@AZys~;6)LhFVqqEsU%c4_!_ot6wYgnwVBgO zEq~}|-4^1U;)s1Io?o2_6b>oD@Ut8ofPlJvaNj;;MT)vvY+^}g|7#X^)(#x9*2^hG zvROa#KD3Gr;wSyIuDm*cN#pol6)651xiq+)BO+FI^xr!^BG zwawrY5Euv3H4II^>&D&{`;bPF@&QIZxV{^>|Kef2MfH{1E4dUF>RO2tsNFR z{{wT|2dy>!Q=zB?qT-wdd`MDC9}_Lxrw)Feg2We^hDOtNZm!T$P#N9YR5sRIw z`n*<)YI(qouTaVI(gKr2yI-(Hh|)d+gqOCdk0;FKL)4`dI7U-54Pq;MR*R7edgV_& z8zE|+w!i?Jx$U<8z%SMASKQe=$&G#Sa&wFL%%XZgI$EWp7Laqa@F7)_w>680Tl>9& zXE*gg_Fz)MX?>{=RERRTSla}u(xA7(NFm>DTlP`4VPVz5l|wIh_=3_f%Jbh|Q zE#h!L?4&a_WsH*m*uvNA^A9)b!3ovDt;Q95 zm!{UhhXyoaL?6Z(IEHQv2}Gr00*0sb;L}n?C{7m&LPuc#JUwywpzd>zISRQFmwI{^ zIDFr$<)?Gy$cPw;9VMX&s%eL!qDa0`I?S&RH%i>+IE-AVmr5!zlYpjCRahtp63;fT zhfVzR(A}5^g%3L>>R1XXc0zK`4ir*Q|0~iA&0lv9L{8Fq!q`{OK=b1jF?iL_Xrl&6 zNSeU~zwgwNxwLQqcF%~R?SnjqXtOPP3*jq*vVV0TEg~Zyv`o56DmoT}uVU!JOVvGV ziJng&U0zG~mbn>oU(Ip)VEszbZSxFq8ABhSSyC~PJejNIlr1DLMBDXrPyJ zY~+61Mfl|*uI>zCQ=72cuB7iqxp^y5oFtGRh5bSID313;c)PWuP_q>n`@(+ameVQeS&7YyC_0?tXfm_Hp-}G+YpYs_WQ=kEM({Iy`bIc5pMnHR z;4v4J|PJVgx;qr`&%3RJhpGJ#1edaViR^XxEHyWWKyzuellA5?hFXh3DTQTJnV=+ti+&Q^04n;lzqcuLYOxw#sHK#x%XcVp~x=>hJ}7inS4wYnCSs!;Iv z3?>PmnMKRKXf4Z#2QV9EFjjNWHmmMEnu8XGHXY1C&5jEm0sPpGCQOqHbUqhjzOfKAR$IKe^DX6n%sIs1d&P_vtp~7}GU|RA6 zi7^(9q+sOzxB^myIu~nBi%^tK8y7KJ76Sx!^2k0i^(YIdk zJ?S`DUE)D94?$p6O2co~yJA4{y!)_u$`7!E#y*e?EkrsRcxna!@ z6d}`KeQ2n;+znwkwMufTOQx#!&!=>OoGd0+0td!P9V8^wqXM_P%QVO=Lvf?*gBg+? zsP9bI7fKnLn4x$LV_$d)mHQuB5%r!BDXyU-qwW*r^D^JbdB5C>Ld=bE5V@uD3yEpH z+>Vea&0*wp5JCaypDTolxkMFjBULqN5ZXJ9Pc)O1jpk(>kUc5GakqBSRan$)CB;a| z-uAD>8B>6ZYY-=a%`R?~eXFvtCn>x*Tqz>1##>B=z96W9X#Wb~}GSqW5d^DCdl(wHtH4CZsl?>J`I2 zBviEwTTK}0n3kDMHT&z+X7Idx+6m5^u>v|8C5QhCJOt`7uo>paBx=S_D&9eRW?(tMOY6RbDv*8d(%sdP|q?)Y*)O6 z$xV%>k)eutZXeoA$UR`xus@@iv|O*sX3oBPmyALC&=46ne}kpCNxN9aICbFFE)KyrN&@sFZULJ{uXIkVZn0(#YqA!3+ar*=Ap)dmOnBL;RT;58{pdAL15 z>KyDuqEIel93)!|v5LYmBE-hLdm&1M_@HDaP$_#}(?Qvs*`d+h7$>h7_{8d5hS9uc zV8KxrBGz^g_>^$X6-PKSvvQWv!$FqE$&eRq7@=S!fbsS$Wz`W?b9>y*MwBX}?PFKC zyHi?jr@dOb1i&W6p8T=9+#dVtm}W-cl2S4=+Ch@X4xCFs+4c&2TK^OP~nzQ_vh{Ce*7@Bbe)WdkI}Z4Q4Y#bDmTRiO)7AK zG(vNZ>DpkLrEOa8cib&}p36Akdq@(Pc6c4M?#Zd4m8(Jx-KBc>IGsbUxTCUi@T~Pc zUc5^4bj6u+cH>~yIkg`+Qm!E_N+Pgu$rx#Wss~zwq+%+NXMmhOxDLOv=76LzONFjihwxt z$zF@bmf$A1cR@>$Sf!Q7l~)O~K|B$Ds9c2Bw8GAv60ALBrLN+eD16cFup z+bYOv87=MKcmg%Q)JI0Vz1m?c5mqzCIQX(um_*jnfKymX-sQC};pwg^+HkuaP3?M& zx{twv+~|E6$-f;>Ec5E3ZB@$%X!lgu*hpJ(W z;yDD2v9#~(vI^!r+*lJ_dv4i+3nyx8q)GJ|Od8HFZQ=A++k za7R&x~|%RtQo4l7o!%aSlcN^TCS*F(o04Y>`_r2yni1eL6416t+K3%k|3hau==JRLV_j%my>_XLCM&1{%&fyoK-}}>A zNS;)9L%`xdt|r@pdF2y}S1&yGZczpKB}U&T_X5n3=AsxV)ZbO7(e#$B=w5U^-HqB# zdNijSeLuehB??r;C(#G|MYS<)FBmimK~=+`%kAL5Aoszj`~5s})Y2EOuM;8DmbUw^ z`Hc|NE4;rgluY2R1p+%5dqFsGMHZIC!_J_{qSGNKvIr7*yT~%kTdOEO$~eIF*(>{j zxw7AG!I&dlYDPX_re{Loeb)2&wiYx}wwEyvu04XnH(cLE_iD~y)0J0qdvIDnRGaE5 zy$O7ZqHyKlLQ%L%akky>xJHe7VzdLOTc)!3+L#`<*9tMc8-2fWoq?5yxdsAj9ioAr zQp%=sE#mR#{;@RI(m@u~h#?-FQS=1!>P(w|4rqE3wWzUYhsHm|?E^%3Np6(=@+N~i z?+Od|VZkm2)q+vu{_rqk;fz2!8n*)mK(j;GSDIZ?W4lN5GQxc7aAM5;N(l(acQMdA zeq)@X(?e&(;eb~G^~I*9DYPen)+9pBk(xoP9L-7U6}MYJV8spLgLmE5*I|%;-L=y$ zShZO(+Ci*J;HhVY8nvn_J!!m5wQ7<4{!-6iCIhgj8)?6N2@A>(P={;#kd`z60vKbT zAR27JI~MCMAzM}-khGLB4z2+jm2ZkZ?Qv>{#E{`bPn%BZK{%{KiV{KU1NI(;sk8`v zlrIKu^EOebGsFJXcyK~V)8>WZ{2DOLvs(y7SbI~92^vqd08WuBLLQfJ*dOu zWAU;5&3!({VgVbBK7ovO@{WPb`@_y40Ypo^ngCBI7lT)sk5j1Snj2|fkAOQi1|6Dctl+o=2hTNM5-GzS6H=3j{ z%i2?NW9|>$BiHmsv3a*apiIh;v&%SWzA$%K#1t!1TIA&HgHrV$1m|$Nm52Jvyjl22 z+#bb9e(;Lx#pEz3j-Y#yY#mFdN#H0y5tdtvHfm+9VT}FO0CR^$bpvJ6@HQ0c1{1!4 z4C##~LdxwHt(xdY-Dir0g1Xd8MLkN*qcRd=*IA(eC|QqN9wsqR)R$5Bn?6~^yX^Va z5XV9$&8s9;6o-nCz}L};tKN8oe)g=90|OR58Q3~r2l+SW{6;HCd^5BX3{w=5vI(f094xgx65yc04DSw*$u zzoYY1LGuI4y0g5JkX=R{E+I|a_wRw4A2>-5>m0VTk~#IbS|WEJ5wKqY2#!(H!GT2b)pbVjiH$6)%FkC=Y zHDtzzrKFV4UUU1t<%ymc7c^src(8$5Trz?~YEnXqI%oqyztS|1ekDJ4Z@`Y|M%gEV zR1-2M?VqNS5c+mfA%kuQ9KhZEw`j&L3JQc6X@6*d7x)ga$hX^;CGsbu9Yo0R#l5mf zT-X`&)}p9LF;I@%cKeHp!hOYOi#T)--8C>j5Obujps`q>p5;}7Nc(4$sLHdKgaR!NVBS$A9Q6ZX!&m(a<>N|KUq(4- zUyAn7DL#=9l?o;!2}uD)87cf-NJjHzXUWWNw1d7H(1Nnq?yTw%lM`nm_95Azk zFn%9dyV%OjTeUP~$dG!2`!A zd@3+*vl{{7(*QmafsicWwrc_gWPfOF8S}(#{9yy#E7`Il$Z%xDlMor+jkxewr8`dQ zgXVJ36+gsocEP|ZjTtKWGU`G1pG@|3xaks?O~e4Kag0{?&&DArj0YAW5Fus}r58mQ zvFfhB;IS3NCJ-SR2ZCmF`QLz1x4vxROV92`&-+Idb+o>w6(YC_QZ5v8r;4ftWy5?8 z2Aa1rC!@(WTR8MHWj58BybbF?#N-YI~j`nVGRrC~!oSM=0MF#Txfr8~?R;c#JE*W1) z^iHZI_LY9XV)ff?5{H(Iy3e~0GO0U}9ato8v0m+@fLpa&%vj-|yj4NWTQ2m6WsHO5 zl5jVy!Zoa{T|y3t)Da;Eq3Z5ZR28iSn-*gnBwT>Y)3uDNfQq0>=oc_QFb6=%s|j!W z)zUmJfdUe5f0~z)v1_0Vh94!P_L;7Tk?aoWnu)$27P;+$R|@9)^HfxETV7;=lvJg) zXxBP|Ybu=d@2jWqJq4&Wqa6T7?K?FohJursm@R&C07z=ll;9L!u^SqYF8E!UTR3>y z@i!Gj@kJAjmkG?An(DChGAg}%+#(tphZ|*IlMp=Q4?}DBX#wX<>u$9D09hkwX$|{~ z$)QgWV>yooVY;xC-%mT$c)@6*&fRqzZx$mv@9K0GqcIkXk(31P`yC)20j7)tkpaNB zmc;l%4wa*+R-Vy*69yBV@BV^$1A-tcz`xk?GE4>#KWTzU~J>f1oo zby!%w(<(6(#@q+TQU+P-P@MW~Vo;*h{^#mYv41Ce74G3#+{pW=gA&>gq?hS=+5y1Z zje4?7dSay2R5r5a9- ziuumRcoA)aU6r7ljJ}UiEugE@(nHLveZ}mjFm0%yl<~cc8IwMJSZ2 z4^m}B#zivYjCtwPt5)(w=!2-5at;}JU(%rbfGEFuJ(jamy;w%xZ~1Ey;hkpSaXW`1 zHjD!}2PxuvDtpN=O!$_g%=hAE33H< z#8FxR`yr$5$KtS{&>U7lGt@qPbeB;CbrEZ8=>h73>gPPt)MTxWeGYHnsjxR#M1ESzTeL} z=q)uj>OQF(A>tb%_NmJcx>@eE#{<6OLV4ho?>OJDc-Rp#n;Ub#)dNJNc{93L?9!8@ zoRMCU{5!nHAiS?TU{Wb2fyNm71*jrUs8`{~dAkMF*xYFQg2UpesebiX{+PsV0B%m) z1{Jc{zY8x@r@)5UjRTcqovg30<4e$>qS#2dETivN<>6*6zGXY5fu_LUma}Fn~p`C_7xRt2qzbXE0 z=k$#FfQ-J6`(ovkwlrc#VvSOW5hfRuXwxj!U6HY4(vrL4#yE(^)scHG1l=#0_9A?R z7-gS#671zWopqd#+c}X@pCg8Juz~DKf2S|H%LNF4fl|UK>ELKAMA)km6g3xR306-q z`qcD6nhTuF3K^T7)JQM7adPREiy{h^+Tq=Y*whWCHsZHKC!?Z9}9oGh6P#|MOC;LRGZ?am2ohq zrmX)33N`KzYg@R-;08sKZKq7ZIkU8-Jwr3nBaq{AQi45t#?)x7RS?25`oRH3St4HO zU&#@n3za|&S$r`o>+PPQvTa(KO>kozM2xg;-cE|UI06ON;Lee8z?K2LI{Vxs2ZI>* zq1T)e$Fles;iwzG*f=ktSjHIPU_D7JU`48Siy`A8-MFs$!4z8YCh2IJ&9S>mM&743 zU@9WlHAcmyt%R$yaMXqAMRECcFeZeg8STY5pf-^7;VVhU1vqQ=%8{aU<3Q_05A!nO zlkaD>*UEs3jC>GQfX0|h!w39-SIF9hh_qeX;o!WR5G~oIF)X;nC}Cf+yKuF=;z#D~ z)$;a|-8h&U7VY@EV)y-FExQAwWCoK02WJKK|EUzj;x=kL*@Bv&iZJc1`UR~sXPpwC z8+jjWhLrnzWoAXk(nf+qTSho2x%=!E%?J5LqN)pN0E06E8=*ift$od!nP*FqFY(JOh;h5KqCuviW< z4zwc}Hhfk8E%&D#F@~{>a?k?@X8cN$ey2Y04v#iu%&?EGE8@g>n*zCXi&_nKey1U0 z98k@O9OosRxq3d08a8E58F_!GRiuY6(-;@uSYtjQSk^8h9RxGd@_iXRxliNT>>L&W zjTz;jy~U~-YdEekX~&gA-(N%>Rb0a{TvuN01u(Q5U?;cTjwM7gd7sIJNapk`&wTPS zu3<5tBQUPGF%Ax6#&lmGxK~T9HN?R!z?9Jr&cqSk8Bm_ovN3H58V#fEV;4b-z0auK zrxTxEueib7dr+5Q-0#A16lDMC8(KIhMto)>$`_$q1E~Uum5h4O0w+%&OGB=~y}~l) zFNc0cfRg;^WWeegfU(Lb`;3T%wfMGY@6FSO-9f~Q82uoR*4*Tqa74OSlsvPW&%wwSwvYGFXgCsRWf zBiq(xeCp~&*o|KkW4#!e4ZiI*{lG?Y0XodvX!N3FwEdBYGVdfWtLEfMUMCA9$&-ZB z-KK3q8`#p8QTF)|8Lj?V7^)4Xr%0s7ltS&k*ZRYV&Hb?I39Bb#7sdfoAHdA+!+t_{iK>Rt}Er|X7s}`nm=Rj$e(b>zT zE8JAaD-G#k;)Ee=tm)8&pgFIWt0Z~SM zn9Bce#{GG(C^WYS%AqL>`_tgmB8r1`?1meRu#~zUwj^!_V#f<^0BK!EAVvnLziqea zuliNnKCJ@rsBy)NkYd3e{am%?&CW56!oZ8TAG}$vcFkIb4~no!vz8I<%uM4{L^JJv zTIgW~%Wbe?ZtovK>0SkdE?L43JN;~3#z^~|tyM4c4LN^}cy6!X4L1w$fN2>p3G^TkO27h~oVx9P$@cL< z2Vvy6e-l)K!@2mOnsOZw^No2mN;AX9?$?oQhc{}|$&I=XJEKtegMi)jv?CbHm0+lNGH*!!)&74HvQku=S290YG*ky2VId`%+R zOfbm}Eobxx%MGnCXOQ$I89nXGRR9kBA%nk;#bozf1jCO}_H$_@FG^ixN$?3LXTTa! zw0RbvbN4(4#fSq=ZH#%q(NraG{Mv!P*D(}#q@HH9gDIQpL;H?j0j?)1csmZFvylwW zl6$hW+g8nxqRTjt>VxrW1v!;#zDih!crdAEf6U^QQPb#sUu@< zX}DjxbZ32`VI|{$^^3roYJn3MjpBTW1%)+ECq|HP!_%pt^qUpLFIrd;`{EodOn@mOPbO$ z%Dyy5h0O6)6*rg1Z9_dy#sU7Til=<(Hx!^`0zAYfN^diKYu@{ZPF`>$A1Jy30LMT$ zzm6;pvSWG{1#MfvWS3Q3fhc!>A5kFAZ3W60`@or+>r!-6^ujJKUN;v-u4S%T$=ALu zDJF)hWwd?17l~0UIm8eGxeQz=MQuDNpX<0M5UBzNUXP4}>0L1L$!}Wf1w_M^6xcEg z-kPvX`b#GkZ)32I%}_3~?RNYS&OEP}X$%XCW%Ps0hrH?yD|)Xd=9H^@wg2egf@gDd z|FE!#YP2+1#FBL{P!|94YEh09T+OHLZuZy$!cl%RG=& z#pq!lnnXPOF1d15R67Jeh#<(IFSPBJ+h!r6>|*iDr;1IFhRoCra|eu7x6W|mK*_oa zRQ{6r+{nHTu!2BQ#*te#r^l&w1`nlq(ZxQhMaM`+-Ce}qfPdK+l`;0~xKKM+VK!-k zvpkvG>Pgcr^)obsf6pNz{8Eu}m67+0&rY&=E@zUa9@&GE{2BZWk-p1J6-C2_}0F@YaAMBSa z2>V_!^jE~#Y}rFkE2Hgq5h>TLqBRc-VJk&z#z$3H4an`>V0L7RKt;Q8fWoR=sNHFc z7BCdRKA5MdGMGBX>GoP8XQqs?Pa+4c$7;R+>K@ShqTfI;PV>b>?{d5Ck<&{?JCM_< zY8$={dtQ`z<_%Wb;>JA4w2^5fd!L29^|PKJtEAd-<$&8D+lUG036bK~hrK~RR$0N|+b_30bjIY|nEMcVSbSPtFyIXF6*^x9bpzpn3%6pu#y#zt zO={fB===S=DvZ2S!4F#}#reCT`egS4-Mqj_ody%Xg^Z(RJb&ncT*yiKx1GsW8D*cz z0qID%C3#dhfwF|;Y9IpsWXU(p$0zN!?nXa|$Khd0E01^H^FkB+=jM5Q zlKF+?#yDtzwDAMO^7Do*xwhOy#t0|p#JnVY+Q%-EJ|*FUjIm~J0{Re7Kt3$}`Pe2RC*4VdIS~D9fw*_olV*#xj%O#@Htcr^b?;w!&U5Q_36>r8BgETHi=4pT}!u z_Q#F1Kb2Q05WZ+6je9i}yP8^)p@VbVDP6+6wrn8^FX)DUK^B$U7T$tNitK`u%=d%f+}9Wt4+uJo2L1Cp6BnG^g3OnAmCd#gE+|xAqH7H|BwC zw*AhFOqv>0hG$c3(#aEB>L8rCw_DU-;&kKWTvR;z-<+vqMHK{ziTPa&5KQ|{?L?ZZ zG9QA)xMqWuHDy^NDWDuD8`ns}*+XssZ-+eCH`J$!hOQ05K9 zR&nEixTwy|bgEY=S_f?03VfdYbI=|AoA=8ytf_XRjB(Ji6rb*N2#MY4P=rEXM+j;8 zbo6ROYnNMl9W=INjDyUQBI2t|>lMoki&v%eB?EQwZMW^0{>Sx_Eg~0jwu}Q(9ZtE| zC^gbIRooF&@_9f71e;`R9J1UZz zGUk3YsIhKb$Y6e^jt;weMx#|%fNH87adq*AJ6lHCCr)hve$CY=oe7y`l$<*-G<)n= zri&z8ZgWg_9l6o=6Ob0tJ7zy!4S(}i#O*I*?#niSIu;!cj`P=$_p& zXZ98>p~XmX|2%FYiI}UyG^C+}kOA!nOK8EC^`|sH5`+dE6&QWLXwamy_{MQ|^(;r~ zOkp$`CGHoip{jlxL7bOUSSlb*k{kU_nEL-{Qq!6;f?+3 zM%`~&GEey~&)09aGj(2sjDvwo>3*n|N`M%t4q5C3iH$O82*BopBpm2R&o*S#v|mo8 zC-=H(uP@s&#ocA(eV9Ru^@oOky4|*}lBA4ruxYu---shFP93{|2ki9Qj3+f47MveQBBoQgTAV{u;+Te61 zC6rP2Q%m3!tt=fv&`q5LBuE~IO+@$ip>wm(St8IW83%nlAb}~bb1^3lcoHD!fmA6$ z2>h1Yg8C%Dr7olI1EBx{_P7oTJE*z~Pm#p^HP7Cu2KC!5BxqemO#2G04Xt(MAMDux z|5qjdpzuidvJ0AYH9&?%uU!HFW{j{ectT+RPKS8$Z{ckM9FcKAhiKW$4`ahu2LyO% z&G!Cfw0)R?esw|XpsL7>Z4H!rg3@I>J;ZrwjjfevJaYUkd(hdov##xVc`PK zMaDs0li9;6K@QI;VT>-HK}g8SXh9so!^N|~9~w@#+Yul@mXQy7v<)zMyK&BNVu61`=*3>P9S0Ihz4xqz6QBoW zw1aF5lDxd6#UM7(I5>%J*H8vrOi#6fk@v)SfQ)jmifOf!rB>JTfCi&*A2b!+3WJ=_ zou^(Uqy88gx!rba30A$hMCs2FR-k(Ysf2A_l_W0o;*5~jjVz<4gCHtH*k61_QJMiU zio~Ulm{!-Bx<*eXX>=2Xk{NS<`n`cBe=WMTdb^zyfX;+)Chb#UvEvtJCVwn;q!N`r z_GKY(f>Ih*i@U@)nNPR$Lq-bwC=x=bcN9s!pLSX}!Fh~P501w2%OQ1NdX%9^ie&VI z%!g`7oBnO>!~+rAKCr#((wnIWr5G-^HHs=xM%$+`6*ynzV`yos>wwIZ9EBA!N8^Pf zoT=G`XTh6{u|I^aE^PLKY8tC0Z3!z?Z~|3G0Iw|1d<_MYG7i{|(Zzmmf?T1SEv2Es zXc?L|+I8E081YQ^a+*PmI5I{)c*Xq(Wxk6#b)sVgC``tI_%5<=B`?-Ia{+9Usb%Wm z#ddK@-^dDk^gwf1#s~-1W7w#RBfmx!G6c!5QJUvMf)reBf5~xB(|28teGGdO4TckN zSxlNmf@tT36dt8G_BD|QM=u--ZnT4HMU6ku=3T_8G}$!IDkF!3hfPZa7qYq{2AvPW zW(reN05^E&?Sdkkv)lmUk=i;%H+DQ!Vv1|a{8PT;Vz2SYzNz2rK8GXO5o?`oo`Z9(?K6c$g zX0|%;_QnBP*t-oZGE(ZvRg>=BLs64hQih0Jciqkh!e}vIP!$(pgDwbT*HFuatN`&4 zfgQ_e`_17dl5*#-E1m01q#&Xsf)r#-yUgqDbZBk@qa29M(~f%|7Q4n>fJPU}@-o^! zPezl7@)|H6a^1=3j zqr6?+;ig_*qn;b|*cS5ZAi6G}I&x7eURQy8|>_BSo4#j#?j64X`WvH5HT zt~IUbJBF&XhzQ9sPFmscExPd5wA)9FO&uwCI70&|Euy1FfGBx=X~uq{OUMP#G{KB}f_%v-i~QA2U0 z*&+{au;EI5a-i>-thO(?Cg;m2% z6Z|i0Sk#%|CN-#hO$^T-k&d2jlzrw$Qt@{V#`NV@I7b=v;50^+=L6eaW z8a`_5tdbjTS1~k|yh15h*W-g>WZV#zayL#6W8wba_>SxSj_m~Ho{&-Y@$>k3XR^L1 zfMJEV+jzK94vG~>%ql2Hfr_x7Ot=y8n@h>>x&^1VAnz77SpU*`gx-0LQ0m0hnMn8y-$9U(IzJm(tBZ#KU==&22>KMKbM%*1A*o0{Q$v9x& zY66a=g_)s?nIimZAgr7S{)=QeB3Bwj`6i3b^0r^5rGjTZtjtU*OKnSwpJe$#nK9n6CUjL6J`X$v!%}I6mV8LK{-ib*sdKraUs7)wVe-4af_k+_E~zi!{#m@&wtp>C|Q|EB5Ex*jmZ zAn>SClndgcErK16r>}^&0bA{|4kko;NUvbD>vk|_P)3Qn3ag*IXUpW}7IKU8NbS0wxq ze>c?|v8{6hxYhP~N;>(gg7(Y=8Cm^=J&<2#SY|W{^==G=xl0!9kfO=z`%rfUqc1ax zUv5i@>Z`~a`$Dc=Br{$NY>_%m6ew+~OJiHquFCPe=3*H(J5Sc!&lYI17l~B?#BMYr zN`$RZ`iT%e5WKp5@OE8Zax%AFX(nk8aCzK%28J)iYTK8u3J= zDX)6^&?o`)JK|BK`WnDz)aN~0ZY&^=tg$a0)w#z#(MQgxNHs&LzE8fOwhB-p&ihp( zv7zd+th`Ux*eNIri^mDsyze(=*X)tzU)z%qB602NJZ{Z>kO1UD@0gQ#2h*1Qr@;4@ zmG|*emeKxDE_=Q*{SC3j2NC1!mn1=(mvk4AP(?2YY$v3!C-ZLgpLnOUmpr2|>i`iB zU+cRLTe@!tJ3W%RWU>w_NnOn5Z>k#oaoiYP%x`%GDB%0EKzC>5XObj~@p5OGUvF5>vnJ#Wl`hF}H zadXZPotu+J`z@Pd-ck!yu{74)Pt-us6S66^oYEt0P2D*py+1?(oLhHHJF0E^(cH2N zbpQOYOT4(^kwx(>M25%-Zkq#P0x`nfyP*?UQdWkDbuh>X8(fp)q=^;Acjz<&46vvg zl9=?AM{#GnxQ=DD{Rs;Wp*7e6|-&CgM$iA^Cn{6nKZiT10WfemzSJk%HHD z3GlQ9SR;PRpG27V74$Hh>QxV{gHk`^zvZGB0WIMI!eYfhKzNQE9z2)1gTa%~NLJo2 z38NoEpIjMnh*dB}vZSgB*#t4s-%TYP?fN%onsmTw`x9tg^CK^$PtTgRyT3$nk;uyX z!<3pzdEte)z^;*5gsOi>R^Oj$R6_Vh5_-v!M!$~YW!3#@i=NXDxQYC{XFH=c{D;*J zfVSwpz887!Xv_X*>7>sonN<%iM0P`0LCq4;6h-IJsi^7GH>iVz_`Hax%uj+=EV(t~ zeu=oNxA8{GdLb1fS}L)4Kxh!X#_-n+RvTqpw7o{4b{aN%o+#j3-jKuvfSx*OxtvdOP|4nw9jnZfvvxn z5Xa-#HqpGS0}2H)k*ST$xttjLn`~qN6axl3QIcOHmbmLRhFiZYnRP5Qs zsQ|LLta?ylD&-=M$Y|J9G2l`!7j1Un#{FkiOGY3p>wsIcixWNQb|PxktZ)cW07}G% z4&i8DZj%bfvV;fNb=%gcKh!6~5wQ@TtJ?&KB7fCPBMgW>m4G!4HZce7ywJ{GX@|iy zL`mC37WZF&_OK=D(wdWXASK<)c*oa`=kwat-xS+n&4U_oVQluAyRX#V8}iOT-QZ~mEUo~Z=C(g6;sx=>qF>4$or}Y;G zm?xyRY&iv?p0V;lD9;V(R3VjDZJQ{M544(^6SOmef^_(S^pErff;|Fbm*pp$90>8;xv1Q4Gv(sK3=hFtEXif9l+UoBD{5B0Kosz`vh1no^r{2r&qou<~8 zHTGpcyRy+YWKFtLrrJWBLjIYBP~^Vj`9n7T<(Iye`?W1_a2JcCsd}7e+Y{zK1R5E7 z?h`htZ-!S0n7S@(x5hqS3*uK?Y`Tl91d~va9a-lY!?*MopE$3M99^Ug>wx>TLm>D% zk$S^Ds7Vj8vC7H^C$)WEMmba(4ytza3S~sCt2r%qBEq zPoURe{ZK*NtdS0SdXx}e@Bm-uWz!_bSk?jiUGG0IT0O}rEVEraa9DF3EUo?nBiwT( z!fYHg1ch}{a6th_z-4x^_`aL{28?(C{Y*{y>W%4%F2oa;RSuG-KHn!)=e?Iez^ZpH zYwk;Iz-s#ry{z{q9&qNXMvavZ+Ae}TX7A{wnSs<+iih1H>Xxv6@y(h$s5=#MU>)eH zcR}J8+Qj@;)rpHn%1Z~+OjK|K5hI+HLBl#?uiPh<@8gzBw!6P`LsHBe;8!W;@%HUy zl*e(d;%|_3z#}Hy^`eA;IHU;qU~z?xkuYg$-UKpu>lRcFw`@lptgX5R+q>;0XfbtO z6QgUcU6)?CV-GY2f>12dX``EWZOK=snHPRb7RhZyUrN+(ps28o$j78M*oJwe95b3@!;7l^Gs zg{*ndjGvcijokwFH#!fJtzzfeve1sm`i38vyXh4kS!rL&9=xazKS&jVn2zZOsE53e zSylNcx8sPW;$@xOgcda3+_%Z)X3NK7^SrokHPMm29NWPy8E3P)%GbM&%|Tu*4_i@H zK=D{a@^4?g62RSE;smN#lv7wa?o)Aern2gqueTg%F&bAsdrq3N`R;h&u0jJPtHph? zZ1AK%5HdZEE#p_`Qq~E+b>2WzM7EM}rvTKe15K%0e#IPuoCxzMtL;zhGU1&1Qu$30 zd8-7-g&`KgE!q&bP!QhcAbEDH?CT;?G)t?uG@QkGP(nlA#)6*$-}8fCPG}5xoeim# z1O4+6t{4kEYiHJ(7^@LE5@Xph!qo2bz;;P#%2Za_ADtTE7r54QP^ZpVL|azfzn16; z$L3{Pi!h``0&%wx9v|vumMA@^<>Y@tyao%%_Q&3bsMz}&ZW+{f>W%q2(2c6jlrew-StQ9?`=2To+5C5D8*Q zob9_nD|adf%c=*L10QfMEM8f%PRY$aS&O*ClBFy;%+e^>s?kmhwPGgip#R1!@F zq`3t6^ZvvgU=Oi~Su>=4{^x`5_zEq%NLiX&mM$Im?XSRt zyY!zVSw5#*`Q-XfKTsm4dqT}#IwV8v^j=^#c`-8f95l z*`Gm#PT&WG$9)aM(dD!%SZ%)q5WSU$B0Wdw_4n%NgjaWU-%5~Hku{gL>qBgZ68=7 zJkCp?HJ+!P!8<#$#y(n_a$I-NLHoeE1dHtlKFH2>jOqcW*uAhOB#lp)J+STLik3+CwMp1vy;^hDlH)5U%Am&;4v1T)YDhAb5mPQ&U7tmON8L^?Ber z=)f;)>`%A?x_U>5-Qh>pqSF(@mvGQF9X@0D_n!=@cl2T2T9$sLtOJIPVJAly3$5M9 znP!#!kwe4&$_^I-i2a)hQ0|JRw6JP8xE8D3{GqwyA$WQZz^A9MabwGz`&Wfad z{Jsth%q7K-5$P5o72vz+qa4UCa!c zqVknA-h0zrK*r>a7FqS+ptc}@&FENw3@2!YK8End4$fMecuT_VI9dD~(y|T)#Rj+9 zbdeQ1ka(}`AsF5XHd`PF2+wA+WQ}nNS@}S6k(lnan3uw{wvrtg0ybmy{m}=gOMajQ zd_J+g-XiT8thP^bIRM7L4akrA<+o|_P*y)UsNslvec<>ktwOL9+*+XCO~>_BR^VYG zz?*ZQ$(jd2wZ*bUv>pW2mG+!PclNlnalyq)7oOJj%_<8A(P&*tu5vrRRoDrP_CZ>`VMx<$8TxV@8S;5ct4T{7vC4} zBW#4iTv)~;r0pkVae3YKt?Wgfw5)Pa!R+b65GQq}i!j6?TNqXuLu{I9>R*nhVr;Xh z2^~DK?HYjrXfrjji4Qxm)rF|cKPpXpjt@&A`K8>d2kj5g$`|ufnDsh8#G>(>ANMyV zf>%XGRy_#iEtF;GUtI_bWn$7yZA0ZAO2i1U%LC}ic3z2bTh=%j2OOQE{0ahkhHS#l z4;Wi?ezYp#xaW#sdYm~Nw^}-I+^;cpyNnyEE{v(G3}K54kaYN7T+nb;rHNPvAmYIk zNmy0e(y0nSDL&$=8$%p^YrM%@9&!0Cai1IzHL>F9DMQOaf3#RWG<9#gg^>Ac01{wg z5GYPo-A6#uj;>*0m@G>~G}cRr8l;Ax{Y%@_+)>g~6kry}+I`3I2W{Xd3IOOK2)C@X zKkZ>r`ybbjvrTl}g|r4LL$?K-Tz=Gr%$r>)Qn8R#_K}xVzu!x1Pbi;fDQc6*I*>yK zI`JCzgfG7q+jYHYkahb5OoKf1m5?Yuey3w1WF4@m!HD)M&GL0zmSDFCa7$TZfAoPl z$M^U$KYs1gYlrU z@Ujm4!k7KDmaXll9^wnag0llZou0JBD@ zuHv%#e(?h`4=1jdjtMO1WNC>+0lq*{1jV~gPJe*v$FjzLWQ(TMn%`pH1I9kk@ftTI z5~(_xo+3mAji}lw)Ve|{cKADsuss}yKe1(QaX)>T8Zrq!b7HS9YK}ON6Y;8R7F7DFC7L_STe@3C)Z4p` z(fJDw9CL&obSfe&v6z$Y-B&x&vbdn}Ev$GjfjPm+|E#+%cg=hASao06L^7eTsN(h< zAC~>A$S14pgNoFXY(79uEp$k-E(M{s?Mq9(xIE`2b7Uzk>mZb$0?NO@x1SDq9ReXN ztDG#X_Cp~tmoLYq^t`OTU!-P27|sc$Yhw`I^}fpT9sPOXS89GC=U5rP69@ioF{){iJ#M=rVPzeN z=7|3F6?OW2;ihdpmemiUt(4z4@vVvgEU$!lS$SU!kuksG1zT}l1*QL%tJ&S2Ep=&u zs@jA4u+-mvmAS0CkIqS$%&fL8SaI%2(q)J35;>T~i`ij2_9ZHala2~d;h^JFj#%R+(IMtRYLCRt92y2HSpWf@IJU4 zL?EA63qtWtPM_STW-l}xsfn7~ahX!!bn5_IGeOh5_CB6li7^}@sb$T54Obel+yEaZ z_NaCq^~$TZoz&x}Hi1!|oVYh6M#Hk&KBw5c+2cF4%jyEtscHuDL%Whx?2h7j6V3;T zb-;8*FXx>}^|^?<-M#uDsFB6myPo(j_p?Sj&j3M-;Su^Z2A*sso3S)Yz#3S?`)uYBL2gfC+gtH-7 z{@c3i$HC2_sM_M}^v~%rAi~s)DAs|fID9N=C5X(Fs<>lWlw}AU*o({aK0H`h!*M<- z<&$$7-i3f)JFB{rh$4?NoOYkf`aP9=5;petQc-{^584 z7*wfa45C@kTpdRDCZ@0FZQF?v)Puk(`$OFGCkFWkxi#!DMMj2I4wU4k2!Yo`WGy6a ziKvH4DxllqQlihRu0$VwS^1z&3`KojCv_2A#tvwhEQfNKr0gv{`xw4BW#d?FpP2|X zmiIyZ`Zxv(sD=S*Uk9@4R4acNJ9&1L-HF{D!vTFzf3S5~Rrp9qoYFY1CAWRH*H=>|ymF?CwpPh9FY!f+Qpn)!ceL z_5~=X#bu3y`xvsCS81gD?YK|XFU=Zhe^_6kTvRwOCKHV`+cvV_z|{}5u&I9ZFW96qEk>s3-?qkFHBblmix#4R!zgs$1!?7d0FM4eagOhCHr`Q z#c-htKrO2uq->3*;X*+)4dWvu-@sW`8n~GN@TutGZu*+;W1Qqpjf`O(T_X$p00~th zNwwT!2nF%<=9!cQ_2bq_#iw5tE`V{Cg?WWbtsp8~1I@9ozAZB&vF2r!eegIM8b6Rw zJx^@krq5;BQrwT}#VH{kN@`5Wnd2(dU!p(&a|^rMqwZ=kZOMXX$SMczd74(QbAsvd zYb%{pPFCG#&p|A`rnRmq5oS&<`zP6_GLojIZlWUS*SH&(RSzoFb`A}(s{%t{XwCj; z(NCoO)nI8RelO|EaTPHNR*MIohF_UKp}aLUEjJ+I7P95bF^V#AS=w5=j^_`vpygRy zC{csEkd+St0r5$AXAfFyPG7q6c5v9PvV{~LbyxY4IHRn2(46Oze`!V7|Nr>4n5!=f z)xv$h>4yQ-`t_PE_z<@a)*SnX$M}Vsxu-A3L$Gx$Seo}8GoH9qzbuYHP1YWibU_hG zq#_Z&Ke2_MvoEV2;2;LY`MI#vf%L62w;tg;v3C%JZ7pApds4p_E64qbedwg#Pp!Mq zRYJ>CfF4<8pQ#uK`g;%cuH6>PsKw4$eGfj)5AO`}< zLJgN#J`Zu~iTdHoaTm@=RzE0!0GEGllb7dB4*=BeIC(U->o~sBU({z4TUOeaTYD*K z|8}tBuxK2UCPXSy#QMNMHJB6V&g=h=<0+V}thNsMrm6PM8vmFD+&@U}L1I90aR6m|3TqVA zlBU;XmEF0uB;9FuY$v0tze13+!^|%YC|lx>TdHbvE-UYne&II0L#S>#h61;UX69v; zT?7?=(XU_Q#gjQ!GDS$Cghqg0K7W<-3U!GZ$Fllv9TCU*wa)Ws$uYOpeJE77(r(8G zzm{{?#eOB`bPf)&0dsKJbBi1D*}(Q?HLH)6!)~b<$MuyEdh{>1z4W%McCxU3kr})1 ze*1NjkPou9RT*6lvDO7Bu9?$`s!|WG2{l|gHh(z=1`yn;+bo4R=D!j9|^8a$&>w498$n0KAI5tmZ zvFBMrn#7z>J+%L|!1O-d#P;>7C-B#0<=weN9Op~sbV49Il4MSWm`CPR^qdbzvL&jP zFH@11Rd$0*9G5@lgH(DbaN&@jS>6OqLARSp2Uo3+<5md3W!1b(&Wz)_syrMV6~bq# zJe5H$WE!G+v+dc*P;uqFtiFrwNrJ1UdMRPIhFo8@lcTvZ)bJu^{(9o6a-UmecfJ_M z{TDdGv#L9?s%2T*m{S~&A4GJX1R@S7x%0BN+2n9Me*h)M{^huc6H8Xv&D6}Xpz?23 zfc$JH%MVj3%PM1kJAt@(xN|+ zC3~7^R*Ac1036S2O$Yevo5tiqsZCtiwz8y3G`}2I%|Xg)yNES&jLg{L!nTWWC@V$0 zP|-YZwS1|6Kok^*6i`rPPrDpN__c^GI^MO-Foo-lKpn-x;j@S3dC~R>L=}WJp?=%; zi|W{_A=+_7MIJ&3NTQ29aQRo=-Q2A17U&Qgi=>L5cYR!mOKx?i^t=*(mZ#og>=geF6Y-nxFsxD;-=*WTCGd$>Dk4 zfuiwP*4!;3;yC>v(eSj1&E2SeXqlzn{H|k?#JKQ?k=w68nHR(##Jd-mQ8CNO2qUA-h6=N}3XPus;J9(1IZwT;@sad{VcdA@KL zk6ldE-Pq#;^{;em-HOPJbT`IN!u?{yUGt{wXjQyfaCW65qXhBGBr=P z;yhSdeL;FA2c=)Ej!8&Hhf^n>R46V^7sT z!6yE<>|wjDD+QNT4k}ElGBnK>n~$Vm3$os#W~O9yzYa?jiPf74Nta`Gj#}B+0PfL#y zlyrNrTG(Yr#PR%Ll>4bqH_GD5U9h$%KNww7Q$>p!pj6WZtiG*%^b!A6YPJ>K9J?$l z9~63kS`4SZ9IiQzBo~kwTUzK&eb0^&XpN{>fVBY^T+~p|5 zasB~4{jBLuf+i#aR^3I{;+X%GV~ePk%uS-BKwJis)$vR8+`?EdgG2?i;pB1QG8?Lx z+ATv81B9A3H1dT*dY=!@v}Z)evRml{51{U3cfVbl)0X;ory#VmQX4pYJ@53nURmj& zjHd@%ZI6(6bJQynQ$|Tu2(a7FvO+7{*Rx90`zMy2g!KJY#p^Tbvi~@hUY`ie5z;>J z)?RzloCsFWyJHAG^Vs_mOteeDZr`rF)M5hamX0KS;vM9^s^EcG{h%{G-XU8t+$SZ> z{+hv*mFxbS=4h(EvH(;>C8M*7klO+u(YD`2E(N9wZ)|C-|DYD{{SuBWP$g+N+rWo8 zZJtyz+0^tNWUamFUe(aV8oQ|NqywNh>89nOlgZA)d5tg!+5tsS!}PptJ1hNqz{X;7we{cu2ciu+EwRP{Tnq=%E8=$B)-3oI8Hq~c_Ey7}*t(_3y-1=F ztA>Lz-WWe{_4RvQjY9n{x>eH2;W3%(^y|NgO+VYU(9}x}pvTKM5oAG9V5;;m;9)pO z#Gz6T*HEBFiL#3DpkBKD6H$;p0S|l3G22-EAix70|Aqtjn#>#2{(WtkwN3SjV;Hwq z2_UBw)U0hp>N=eXwHQovp#I1vWugv1&(Sg24ryWY%&AdcpshV*YZR zRiBkL4qAv1KY3A{P9-fwTg%{@I-l51vG&d83JFJ){J5;T3sT2%{UvL8j*nsSi95DD zG4ATC;JCd?L_d0`1ue{`@}X2Q4^VmY7wMh{>oFKH)BeIL2j?Y^_*&$7o_N|nP$5QE zJBYU6lJ}Wn#vPCXWu~~1Zj-;XDyZ@u*V<`P6k}o4?b#X&h(q|HWcrM`PVm#|vJM*Z z8pex@bIY=lCb19u5sE`FsdRmHiNQ??M=$FjBaU|TIFLw#z4j0S59L<*R>L6!h7pn2VAr^xXuKzSU(5kc1k-vbNRUaoqljOEbWADL^&S3?Sev;%lM1 z^2Fn~)6ZL0-%rLPbVRRw(B2Sp5LxDy`91_`}np1|#V+ zR#+N4HZ^n}Y(ARw!2>QR*xGiYh^W*Lqb|=jhJe*i>X}^P|aq&MivlWa4i zN7*_uF{j4qtv+sBD+^Wc)8Sv-e;1}{>K2UHQ@+Xzid`tHi(u0xb1YaGZCWZNd0F`& z%R}SR^sv(30YGrlBYWvi9v)3KX)o)m@VqYNFr(K&D+3*zV)PsSp6Gk%p${ z^9~SVWm)CmlmUF{;RJ~lG5ZXhJFLE~_TNbx%(ej*Rc z6|;t0uu9k;SBJZ#q)F+X2kqaI#GWsarerzF8vy~e$e6F1&dfeApTG0B3dREU6ee&4 zj+52)$38^|`=KsBo)>M)fl(m0(n0A#O!7Z-^%imD^=n#nSB(P4<-7E-x?AQAVw*9o zdXO$zQc60i3P7c11c>QE(1X0mHmtzR&nC9}G5cQ1OkD3D(=f?@GcY`k3pl>Ztq}H` z)Ch`xA6xn5IHoL-Qmnd<%L_j-$*0G0E%7S1#b0mNalL*(F+Z6p*8`-HvPL{em?~7> z$rp8n%Ok-uib%GF^LBixG5p+2c4>-SRF?h*yMAfuOzIc}fz*|crTZd7(!9URJOP&V zG99OI5Y*OR=mG0Vx?nW-VC!2lU? z7xka=2RBZ9Ul36vpUtfkR8L?Q?wax{BlGzRO1_lMa;2}=-lEiO;-TE%tfEQTZO0%W zZUXy($&~uViCN$mtMM&KS)yf1rQO!H_$QA0_b~IKo`l;gi$4~tg#Ec5nA@V0T_D{9 zfd-fwyLCjJOL{V1@M#FZqs9|tjeTUk7#F|EF5=^u=IU+reUOXYca{n+t{ix@EHmV6 zf=QP$F{FKqWy3xO;J7fYwohG08j!`PrpT7t*aFOcHRvbo47Kzvzu-hgYdTJ=9l$RM zkH4|`t2thv-vo5!RytVJmU{h=jgQB1%UP0dSZ!Bn9mk;Lm+p9zER;{}T3j$Xm*cCZ zmMtJjqFBSK2N89vx2%ihERk9!vMvSCFtRSfqS(J(j)A91rvdAvTFcFv{P?iFp;!Yr zg8KY_!7j=20DH|DS$LloRAk$3EtHLO6I;|ywKjr~1Ak7N6;p-rnEv_1ep zeY9NKx|i(YC{bi%SY>}&-QL!}5+~ZDT+u-upvA{10)A?d<5i2`tN&_qTArb41I~64hx^M1}#CBDR+PQ@YGrQPr)u zt(1&kRjKYB>~pn~70wRnM4&&`iIuBuEZ;|FwOw*?+~$8>U4Y1K&jWPY0LYj(T57}T z+8)Q0q|>y@0alEluFuOMJ0O7uNP_gD5CHV>&Ji=i7oocqPpab3X*pd@M(D%2r_mlA z8l-|U_TNK@Sn|lFrRY|@c15^x+mYwFq-A2(dre;FBxD!1~s`~-eU7s9MQ z*mBKe4*?kuvIjKG7I2v87esC3$8XHiki#n10g7l)*qW>W78+M! z4~s^&X`e>jx{Fq2<$qi)D+3ne0`=-|~9ZYr+QP zYs~({W*r36dRZUMt%ZK%GVG#Rm(})b4;(z-K(VKyrf~&95X?%~ev?V$^dGD-PppNk zm=12NvMoP_TMjMPm2cufB4sGd_u#*Z88^NBf_SWMwQHZ3SQAs9_y2=lf`L&Qvqd@S zes(BnzHhy){Bqo`a9i8z6F6?a5KcU2N41kw1w^d4ALGUA7lpCw`Nj<)rfXVdpEZV# z!~a3?6L(3-B3XT(+ao$qwE9%>XcKAw$ACrER55o(d@)ZJVp+)rW5sR#Z+w#^PD!Q$ zCyOVgq$Lcl1!l{`q9!b@1G-7m8v8v6%P?&n&0(h4Va&B2OD7B-@;&|I( zA9z$dk2DA%ss%Fi3w7`ZA79YiQXDO-?h3l$xc{)1o&d932#DOAEK8gAqaO0^&(_D& zWkNDRGitI9Xqcj=JSLV1bfbnot^|%nMbl>Yz|&Uib&#e_tMAVRlBgkVuCT{K4STPZ z-mQ`*CmSJdUk^OcywWbliU+3_B*>p+n@=2I?y9GWgBsKRmCFN9Rak6{!{v} zJE4kx0jq_B^Ml+(`bZTfvEY=ZdIB!yKZeeHtDN#8B{RLjma?}Hnof294x@|p6!b#wN0@Or~#rv=+6m= z{5UQ_$^fzs23@K2ej`3#XNTzguW9vtK%iH-Jt?+CEUM#@oD?wr6&J}_1RvDNoA9Nw z+Wy!U3Pj%%a;xA{ktC5u09Fk9*jl)d<{q{rSSJO0*di+5!*=<%7v{4iBfG{5=He&ux+(z)r0FH{hv@< z=5F{vh^(|+F`xSX+3GC$c#yGv$i;|W_U?@T(y)DwV@~r8aog+uq zNgPk3GWx|-#3YI4Rh5X@U~Ok4)*iPs&y!pA+E?olUG|s0>1#n-Kq4$LRtN`Mm}>B6 zd3s4-RT|TY2A`~Qu#+H=|D5<(#mfrOHsE%*PGVYh$o_XzEiRmT4Wq)ZIjw$B%!7I{ zWxt5wT^0djZq(Vpad&d&#lKL&z#`$~Ry+tT!N=e8VodThpBF1Iok}!NBNFQiTT0hd zUBc=owLGGTmb9ephyZe7F;^I(rLzYwL_CjQxR;v>%VJ^PXJQn1L9!-v&|G%t5A1YR z>~$rJhWgsUmLD}*B5sX+v?tK$=1o)7R3M;gmW|R_uq%O4Or2P3K?Cc~QkTbS2We^f z1!kI_CkA*(e2-PHlPAu%{AK$?gRcuuo5V=n0YRqzf*_c?nqv>ss{0LjI*9G&+C&xb z;teC_+5XjGn_0D%rSyfnk*+bVauCyU%{K27TRxJcIu#tIoYk@Juj+J#Es1sDR^4yN zQ_)C$f-Y(0UAp$eaQ$u4!~6>3E5n&VhZa`e@8w0wA5Ur39_=XP@DQVvm^NSvd_f-| z*e*G?X`O_Y(8tGlTE+%l4^rnDg5rQcGO&sT*sAdI3N0Zk@3UP|(E5f>*O%kbG*c_< zPCr;?<|DmDBwy+@ zNjZ1T64#RL$f7=s)x$m$L1erlI}Wfl=mD6^W5!kp%&V#%x-O+sH6%W*dQew_Hchub z{f%z1Dl=Pl``e9?p}qnq5SGF@bn(N(9jud#g)Qqun^{<1ja`gR2LPhYEQP5j&T1Bk zwpgb%4k{kCJ#h!9u&B6Wh-`vDtH!s~Ms1}xkv?MelhmR1U!?0+vea5kNw^oRdT?0Q z@eAg1z3P71aVF>hR^11CMxgP@bCx!kr35|={SuL7FG+o_@%U}E>CD0!``DJqpZg_h zvPwMFK58zy9I)EH?j^h|pHybg@B<ewgv8S-2k8R@@?T`zuTMOBlVq)|eo)2h zamE0UT@DFR2#9BY7h-@ede}vBVeUrMkgKe*FF~!S>I;6b=BLS(qGr@&^@F};|Ao(V zaS>VUW$$2&X&q=HFr^yRA_l)SkarTm_HvwS>l8(vT8o{KY7e+|K!QM-X2KpiIZD?+ zevOQS0eiR#?Y0Hjs&<@QNv8+a*dG;B82Pn{pTTXYORf$uT_h$at!c|jzZHVk6E}E_ zDIU93PaH2I<_gy~Vy6sDk@_>NW^c2+=BFEz8k$j)b&?W~>t7Rbi-c4-v)lDo>C-W? zm2H{7ucihTMm=I#Cn*H11E0b*`FY}q26S+%9!&L;AtV*lVE0T#W6id>hz&sJm8RNC zeH_CydAZdOki_;#_GH7`Jd_6`4{8A`7?<#8!Fqgas#vBJeb5stg#D3EJ8b_&m)qd# zr79Rz{I^3iRwYgKm93dOdq4ehtE2-6vn`_G*cLditG()B?_98i&R~{dJhdWb0Q zW1M)jm)|5UE?McI06_$+{t|rrNf< zzp$BH(Hp>+1)%m&{n^D0gvT|lzE9tl>;U*KUapcF?$GRUt6%#?CQtxBfQg@P+=et8 z+&Y-*g-ZRa1M#{O1FaUk$vPO32l$wzUD$mD zB~bX|VXAl_TXFpE#FjT|U{BTo;U(AU z>_J?Al%~B05wnj4!Yysr^E#=aZLL?F)&XZ-0v-R6pN{8oEs<>gfd`19?GS+6x{P@< zUFb@Jw2X~5QHm>cgKz_Y2#9epozTTY39swMsjdjCmR^LRKFa|3wb9rsuvnq%=cbJ zFoQ*7(vU|G&_Y((uY2I&2kqwH>R4qN>rYQJ6;d01lXip*|l#C+Q^S-$gK+tn`l zFdE~^@Bb>{?Z4+17QpsAHV9w9T&_iMsOMew&{i zEeIL1?Kl1_aS?kV*-?mm$jNhug^4^Sz8={7GH&(#;Rgj$6B%dep)xQFbFwsm{z`W5t@tI(aJBe(APG=C;(0g5&0QHx zm$`L7l7lwTcR4LS*U~_wcUt2*IJH>BUqmMFH%&9SO{?r{UU4i(tt{C28pjZWE&=^N zGV&DPg1weAg6195f2eTet z7Il@44wa+=JYskc@HB52UJndZ-yhh5&i%f)GzdNkdgHUQ>~PgxBr6@n9Y7sES+?V| zvh2D*4%Mx+&-#!A3ig$ieJ%(Tk){k21h%4yfBcq~#Lp`$?~iPAz<+ZfK9N?UdFe|F zpvOU-#qQJ}3OwtSw*6bA;DS{T2B#?Q#Nc!ycK13(KEpiP%q0y^4_`#LOmqePdmNDb`4Oha*FrIuRW~buCm%b2~tv3>|@5XJ#G;TxUGB;b=Y>KLG362 z^{S%zM9YoCN?8Y?Y!4byYJ>p-Fgp@p+WM(c)G z>Eu>9klM5;?q3vX3nQgMiub=U;28#r*e+=B|}i z_XEiIYr^7+=7OQu7|BDBj@sk90Z`Dj)8T=Y4~nJYK$WlvQV-c>tTV&-BqtX{IcPIJ zN{p>&Vk%DSK;bJ9R(&u{yl`Tr(e$LI#`k?*7_;CHl zaT{)>>wvwLlnf}?pEFu8O4Se);c&8T+#oHr+iD$Lg&B1P)L8vsT{A-abHh|@B4bQz z98}^Vqxob)e)ch}2bC_GtiC_eD}dS8l3tTFaKx3MA^=w2$7%r(3&Qi-;aDYhOyWeW zi+@ooJ)hU!L(O{6SO>hG^p2uXXgb& z2vT$9%z{mYP~a8h*%fWkw>!3bX`lW;LRw!ffcku4OZVAtwTn_EkIJQZP-^MrmjR|{McZQcNDJ#gh#An;cfoY2^tIY9&C|J+ z5B4xT3!gdh>xmn^)Hto9C+?ql%L5*=t1*gf2`hzzCXa=)pG~b-ztr4yAzox1K$jD- z@|XVe^}J_`t}nlo7!0ZVTNqgU=Tyz>>=?z{1F}vMQ<291Zvp71^3Z_p=!~X8eSl3* zBi)>Q330&5$=CZR&dC>@yyJ1)t0qgZT0A(T$1lWM59G0#ABKHp!K}6K7`g{>0g;Yo zW&`sdh2ku_hb;M;2R>x((opEdXiJRyXNSsV8oRWJJys2`UMM3v~mI+hN&6`CuQ_QbTA>s-4uN70h6k%$fKEJnXLI3Aa1<7M@I z<$9`1Lq|0OONn4|M1&CSZFUPUoj>KdBjCE$JRp|+-@y~dANWL{xf z%eRKx^*Amr)hw&+bH>_VdzR$wXdaadkCJ=?YiGAbEa|^!E#3f?R=4VY-_+vrdrZx8 zmkL=gV`?D))wi!6T%zv%#FeU)TY#Ll9ZR>I10+irkcLWTDp4n~{X3|%$Ge4T9-FE# zvid#>fxI`WIF1xyWm%z)Xhsl8v3fcW3W0*DVA`_!e(N-=>8|`GlOU=sYL+Eq00T0A z2hPa&gg=cJqfUfb;ec5jkY|@`nrZ@o*&Z&PP_C14(J`!UV0Fq1G7S!|Gj?-t7`e04q6L;7aEE{=W$OYJi&wau+jnbj2OLkgo zf-40?1TAY{jx8`6O3KX&VP6vgZO_m7siz8IOT7%GY%Kb;-%TX>{iH&O42EIi`^2>1>V><5F z0Y4zs%Krl;GVZdt#bo7urcJ6XV8Fe|1xLCBWZ{t&Jpql<7i}%7_CBdDE06s&C2`L7bslgn9$x)vPu((_r)UQNtHTJcsU--ySioR#(`tY8QVSkSt$x+ zdJ*(iNggk{Z!tXI*uu=F3<_)PkJ#8d{g;G;6gQzgGF{^W0}vr6{eQsB>sCbNqX^rJ z)ed574t$qmpyg4CD;WpSE~-R+R2&u=GxMG;5HiU+fNw#K^24ml+Q%bumDFj~efXBz zbKOxzkZdW`YDuGpMO+*0eSR=2c?sf<757opC=`D~UDwhYc>oZZR@!H-0~9#R5s7Qj zDdZ5SsVYYl!Ny*WYm80JTdc7UX95zPuBp5kB@$?kdzbim`)l--{yhZa=FS42(x-L6 zdJVsE*S#3&bHVK1?Osd}CG|^qruc55B7Y**e5`&To<|DSe99K8Tt>%R`2*nz2<8u& z?eUInMU<=59IG81n8_k4jego2wzIJ7iS6E@w01$?OBMI^jghKSG>?_{2gexk%y-&` zPD+QrCDOGcovJhr-{oqi2Ng@p%KP*HoQGfVp7>O&M@PFdx)sC0ZbA_8vuXTV)S5a? zZuM{w1rW=L2b$y|>7RJcOPwx^^1hh{+9SP9tL#HCGHJsXymt+|bo&yQVt83?zgJBY zFveNzpR|cT*}vCu{p?Uv{cmS_%KmrlDbD~|oM z5~O@>el3ws2rXuZCh8DT2sQ%O$8nu<+*tKMax0@^_Swu#&*4GCfNd=+=l%N-q`ZJ~ z6iaF3+8J5x0CotuWOUQ@dSFl{)3O9&|F8rp|5>+PXjgOBEXQs+Ty+>XXYV`*X#RrcDhQbPyRMM?=Owqb9geceCeR zNrWeEl&9ETKXNt&C{EX#c=>FAtCz4cZTUQit31;bdYP) zH2Fe0`h^Eu4TG-y&qVp@#qLP3E~npi!+-8j1TumATf> z+pYKM(DE$%3Jn&AgSXoLC8f30dJ`4c1fMf9pp-zHSflUN+5_-Oe(FA!5n-}#(%bnV zk;{;pA+i|MP4*AF_7ffHaypvR3o%Q$ ze|Or7srkM;Ej!e-)nG1@OB(@}g}LI0g#g!o>puP{3)enBXzC7gr%jL~pwy^m{+n~6 zI7?NHK#P;FgRHs1FVpWH805a0p+4B6IB$z!s2=$;m1E(93ufiG4{3v>=^MjW?<3#|CD;0Q;Sk~MG!;3CGDT@(r5m{l%;!@!f~pu^5v8#yH4A`F2!UzY=eWM zUqGwCnbp4w%*ic#&IML_q3UM8BkiAnfNZ=90>($8O%`P~pm~&YoA}+!a%vYr_Fo}6 zcAbtNhW5hk)K>G5N*VKd`&*_%C>m#bEh5!i%qXH6tGaIhpxjQgOO7KpavhYYY2t-R zj@&zeYhlC}N*+kgs-R+?D4NrX>RH!sJJ_e4d_PTW@enfeqO#SdOp=rV?ky875K=A7 ze%rw}?IbD_cM+LGBX3a)97=}joX_cgy#QQjJKAqLD8vI;50l@c7J4uCdOa`AP0Kjn zgvdCxGl2rG{nmrj5El2ZP|U~1@i_zt<+to(O(j40DdV2+Puc-G6#dqN^npgOpwn>D zz?p`SdWPvzLh71RUJp7_qz1%qIk?#RFA}Py-%d+}xYvHu0mTGw*1nHd?Cid7U|jz! zzpNS<2M{%G7#>c$BoO&c`*aI={37X9;_cKD@ZrDZ0QUzfJB{65+U^Wy_3KBf(rk8v> zZKI4!zx|-nOuTthqgtHJ881Z(^!FM(hlE4%UPc-8oqoZ9?K^EhQ10BxnkCy!frb61 z{jmn{Jf8yT{r;qO)ff8z_S+85KusrpQ2br@b2eK*nvYAd?~||=(Xih$g&Dv{K^u(j zP=RJxLzegTo#^<1Pq*I#0ycoAKTP(Q<+N*;+HcusUm*sJ&I!hps5rtqeHw=DE%?l- zE?z$vaqXP0S-%JOcMtWpR)KE;gUeLB!I=V8aNy>#$dEoJjW z#twxBM;CWXfJ`aFEd)X7$|>iz zcnbrD!IO#>>5C<)q}yo{NRi)@Pa5J6G`px@1W8lI+ueNp1*uO6T z^zFAEu(@-V{m@BVPAQiS{T{vE@~?WDXh~BBodw^ueap(n4H{ltQEv&YL_KLM9A(>1 zIZ&fVgQJnpTa*$-$xJ6CNOS3q?~5IduzuQax%R7N_ILh)r8nQ53AC_t*KgU!mI8PB zZo}VkZ^;y#n|=?3wm`bMQzfTW#a1q`=BZ6#J}cgD*Y*^+?vkBAaMve;_|+K!gL4|f zE0!e+{Ab%E#+As}iFn!HhTo9(wWe%6{A;eu6OgE@{NrC2D7Z4wBYmfJ99h!g2bd-P zegEA`YT$oAXKQzN%k~JfAMhRQ&na0T_Akac4__eW(D^$A<{Q-TdAIX^sdn%Y^YVK@ z;Gr^wb|}Q?**!5laJkTeI>7UD){p`!6#Vx64i~b6o(j`=VVGaJaMGfz6mwK(rQziB@cCf)NEJCYUtPrwNjy37vysJBad zwQ>og(RRjPG;ch-w$Tbu!XD7Q>rttH*KxBxDC)G#%vAngw+lywxxG()pF2V^XO;2- zp=a2aZ{Q67zPGP_I~}%i>G|7R-l1#uTJZHP(K|0izB=CR50GfFa0g6BI;>spc^D zMRT;?PMNz&`aOEP?UAX5IJme>wNx9Re(y0nr%|(@c)$=E1>4_u+J7KSzH4OQ1DPJ> zR{-H%r{f1s+dI;2)pBnNhW6X`2Qq2<{=n@LZs3Mx#}NDsj;sTxVQT2mLTq9PB<7T^ zibW8_UUi0lc3f3xhWRZAXMJ9kBioy0&O(yXi15n-Aka2(+-Q*$G;U4ga1b%%^qnyE z`9V>Xr-8_C+n;nTJkV#hA7=#E$y2lc_Wg+qfOjd)8)j4lG*Y4kWNRc{6a&He+$DQ- zW`~B^uM<`gfeXKmz?GzR_yEV?w_N+Ube|;jVVZQgKr7G~rDo9Q6EiHAU9?O59uSH# z;n?zo>{!k=cpPFla~6upo+&`KGVe}qV6NPjvtF-w(s zF4!8nARpsb9F&_*Aqy#UO8c_tBav-e2s$Ld3=%Ou{SaiIJ+#J12QOG{vMMmNJ#j%dS!E#`k&(AQ%x2kTDKIUy5*_pZ31U z1CSaC)M6YA85S^zZ63mnPy}x|(TIWAGwVZ^8=*|KlptM3--kY--I4R;hrJ>^OPRtE zQE#@FTqOf@Ln?yUB!FXM)Ppk-*vt2z-`cj_E3z``K3uuj_i4^}NVki&OzZS+?JYnR zA4J4fAGf`B!1fmsg!^dTQtACq+{$GElin?`VrY5nC11Hd%?dk%OOT)>M&Acz7Il5R z5pREmC~CM44x~_HXKCS{es4NL$+ITnV9E zq6Rl39O!iwsL7p3z(Vs3b%Hd8pbC@55Z$Y_p6uTbP0L`^eTpnpPi9N30m0Qj{#lUI zd^kv_$6atTXXBDS8%ExTWx+J|EiZ7lku8uza;mw}>VaEkOU4YO3QPv#Q)GuwxQ*@M zG)`gWz4-~bd#(Z2u^_=_{OrTig}9w z>}8a=PqRkhBj$ z)Q32c?lP)j$Nw7A(CnTUO{@sgM7p>i`A&aHi zjJ99!1BM0;OLu_XclO4s-LIua05-znq}Lq)NLL&x7=3?gzh2+{yJs0&0&I&byK%6d z>ZQ3&QMVy+(nSJsQIvs$k2_x!_o3gp4-~>WNHE5JrCtMZpC!Nbz~*g8kQJluAB_O{ z<29?uc5bxn%@}p?+Fz-XQCW4>ie|3>LV*nQ;AutL_0MU{T%nglFNjq{{7V1Y;+=@d z1_U?ye&LM+mn7a*H`8USv}hI)FjC^MWS7Ri+`^O}+$j5GKq^0rK9wLwNjdlz(?} z2vc?tt+T>{@=Iq$ zLHS{SAyXpwp4wOo8I4>*YK(&(CKIeg4|0p_p9&SVNRqh%+9N=}*3*J=yP_LuznRD# z{;i|3D##TgO9DPK%7JbS8|6D4xLg0B!6-}e(bPNLzkw*9%^Y4}OV8n@ljb=*M?zm- zIV6S~b$=wMLP+|J^}i1(J3MNT)U_FTA4tN*HIsM?O)JGslK9w|&dGFTxXR1p7ICZY z#?fijFV#sfg_fmCZ)pfA36`%)8~#3| zI_JMgw-b~O2X22Tm_O7qy)Y*q-B1T?*DV`mOxW$kp3ET4V0tC(^L|TOPitvf6h|ri zC;QD)lJXShAvJ&iG0oPYO9k;3bXv6auqZrJGr%~|IS^HW@Z0ULX&My#c2T>I?Q_{8 zzv)kct#1lLGIH3jGg=tNO!marsak`cMQ*`QW*`W!3Uar+M1$)XZ69R}1xFDj6M^w1 zb}hSfGmO8P>TcKA_RDP(-xfwa$htWAzsIlcBMP2_&bu|ET>IStfmgoDLN`NO7(RkcvnW=mldiCJN-0fZFarvNaq+X)<#EW zMT|ndAWic3L=Su@mr+jR?I(kHWWYefy|tgISdH>9{0F`tOOi1TEWgW8Pd@uxEB z&=efw`4U^Fd73pBmmZ$6(I{@qNC!8bK;>hiHxsH6um~j-%J_?Tv+zdG+ZsqME8jKa zV3v{6=6Ah(EvSfk5S3SqcCw)Ch*G>5sZ*d#RFKl4PhO~iiDrKB7$rzOAX&yZDduLt z^5MRFKvgErs!84ib5VJUxzS?v!5fj0_j_Cwtju?DbEY6Mv)@W_BOfGO&|qosL|Si5 z5HLejDN-edV?{Q5&-E|?%!q=F68Gn(s`MylP;Oh%J~PM;Q3r$U$bqiJBIC-jNmowB z0Wy~h+_PFhg!-binW#m8zP@w~)W>U20Jdb5gA9aKDTJ&JWYvP~)t1l{I+h%jZ{GWd zPDoWz!NS!8N-hcmUA0`0-I*Y&H;O`bwe)EJMjhe1ZOVAqaA33P*Mf5kSXXpx_r5fYFi!Lli3>l4C~q2N%kN4>nL@^aIwG~{i4|q?Fz6pG z*=rVomiz}uslAvkEmlt*Uha&P%0a1|q|WC_%U_bz0Q008ZnrNyC(`b|bVPr>>r`a= zaDTY7)?Z5HH%Efy&WM?GH%`(mGUqm#J?W+msUt>V3N!MmqVFrqEmLw$MmW&fsDhS% zU3e={Ez!alp!FE-AW&tlI!$UjOGPq}Z$dYF$TG;NHJrCzGSL;}US`-O!m2JOLGAd83#am-7|tH z@olf@1%t|E%hTFvRbF*B3#~>3dnTjrD+frUEXi-S^CAiyW4CN=Qiin$hFe69m+84O zeThyXhQ`TuJug{vJ0BAa>Fl8zyM{mE1h236Z1-$yeHsUBC&0jd7+$-U+ejDQjk2#o zAznA1m~Ixhb%x3kQ=kl~NQRI^{vLG&SDr;sg3%8er>G8=S-M6x6Tuq0=`UqtD2j#f zidQR9P>M28xZHO;?p8G%7mRTb zB@=0XDe>jCjO|cVDvU7>kWp}lf3j4@wP_h4Cd{fJJNJi}DP?_wl%A)pSECaqqwY_m zpc(!?oh)N?QJcdKLSlVoDe(CT8JyPd?q5cD zf-hQ|7~ud2rW*BE;!rIm@a;Nk}udoR&=EK_XwhRfo+v&?0jz0 zQo?Ba0w@)V%sxZ&(zt3U9lI`V`LjIddLauzibf^*7zZrWTyo!n4lC`lO-qr{jdp;H zvg@V_V!Ie0UV|(AOYkMf@VKQNAp>R7eYfF< zm%MtI4OV7VSm>|qPgSW1@pb8~hwbo_NbESEXR>|!2*_O>P)~79%F!w5^`*a}6}Nze z^aN1+btCWR@lDlxu1yPWn>_>lR}w*TyLOGd}_ksJ2QAuS)&WE(A3z3hk3c~e z;{Z-iKKw(Q_&yo!5FS)EW%T_vF|k9um9QTj-yS)zNVMhg3IgB3nfrSm?aThuZ zgs4PS_KZOr7MM2~FO#raUj8gIxCcun-a1q4# z1Lw{2X&dA`#f_8g6Mra1EyWb`mXI2EBOTm7k-TGa-asvOi7N^^Pa+HS-17UdXb7Ga zHx6{NEHVB!ge@eYjMV?eMG4p5K&L|i;Nj6u9<;@W#to8aPq*D7&@^c~E|v3a0o(e$ zgfy?gIl9_%oBO3YtQiMdq97|cnH-eWq*Fs30d==C7so7GS`PZlrwzPIzZinlW+| zCoYsI^%69VjO0CWYTlAm+-0PF`ZG=a7oCnkfUEaD?08I*6_U|>(uCIoH=(Fxq=V=@ z{eX~qY3ju=Xxz&0PB z_T`9_m4B)V#&uM{C`FD0Mk5~NKlz72z2`KpO%xUwBOcUMLE~!F2*hS#WVfT71E8*} zIZyR1uXl{jtXPoDDEs6>O{2m8TNksB$7y8bK*p#CZW|2KYa(IQohpQ;|`+x8{;&7c(0B9X2Qkn`lZvfn`#= zR)A3kkpT=;q26vsaKJLgfz$zmK0l03-!D19!AJE7qwa%N8zUEK2CAraYjnA0KslgG z;5D%SRF+$~uA__*_q(U9IHxi@NLp>eY+R@avAQlxGc|wp1gn9HH)|PV?2`nyatoOA zz_x}(xppO{Jf&bRY~5XNRMit^f+SY)gIpf4d5^2iDG~%rg_xwx(2QS_AXwtl%&tMQ zh;g7TMx2|{yl?YGkk5&gi%!8mi-dJx+~-sP9+smU2b0Xyy1ol0EBy(h%yw!S>n5(z#QMN=3Dtgfv_B*XrRtRy9NafK)n$Vs)Wo777y zYY(9pTBmXHZOOB~XF#8)9qsaptfgHCRo(i_LA4ak?JJ8#5TnI|lt2PaU#zZWosS9O zFE?7;CxE7WTEncb3jWWdK)5tPmn0k2y7VJjfM{%C_TX0;MRcdz`6JwVal+72t~E_# z9MpB~f7(08RAOS`LUf`30W&v)%7yBRH)1IPfNT1?%v&AAtj=Yw2S(t>2LuQtr?3JL zY_6KVUUeB=bt#N-a0|5?%_*tCZZ|(@&P@Ia_RodSZWxcn)m`-t8RG!h(#j7tle7-V z2CH9pqaI{Jt^QIDTTg4duIs9AfFSozDhgnqB9Ko!)$CMM7-vR3*+%^qHAcK@KsBy0 zc{)*c9cJO+p3ARUl7}mpmXr%Wj-NwCu0`E#kK}P`nTq>~7?Pvi&cJ^LS5eq-du}rzIAVT{x&s zk$HTS64v%HUmXHTn62ZeozpjE7~Sh zw`J&LEoAHpcYq38+LND)KH55xvKB_#AChOT=1X)qJm1w)kpY@2GGBa<(A(+MMA1Tp zQG|VM(5tph)u6Xk4e2H#FmI*6xFjPVoKP11BbK5`#ZJmcz~~ZHc4m+Sw5KzlxF0}h z$!I4}3z{y(Rb%lceq9-Df843r@)+W1foEC5j&SULad#!`EvKh!{?>nV1HOW#MWeLuH+m7&bmA?)> z^8@uTZ^9wCkq%&$176eW@f)k9LvxDKU4;ICPIi9iLlSUG!U>FV9aJvtNlTn11UqPH zkYii`w=AyWUB2Q9GTKY(Ji=A(ujBE{eDNweMkHH8bR+Mxk~JaAKQ*nxnw?e&A_=Eeq7s(YdK%D5$!qQh7cIyB6r)LM_+*LEv@Dpl z`HvFQd)$_k+-=d|`nFrdiiS$(#k+Z|VhS-q5M$X061u694Mi6kY!)Y{Nwqs zUC9v!ba(q+2}@^8ZYvhKiDD;}1bHmwytruM&5>`f*RG-1WI&C%?>2u+Ft1BMUE#hp`=C1g>tRlg-mV-|@}lWWMZtV8>#l{WGyc6qP0&KoAc}vJ=Dqz5N@con8S{ z3U=Q}gf=j{zrTt}u5OktAo|5=3x#ondRp^|^>I6zYu}pD_i2VGjsL(~bsrT8@Gfv4 zj04rGu6r%{eHS$=M%n}49cd4g`SsQ9qWj0tij2Gue^U_pLFLpRr$p_=jkw=E?e_Pb z1O#w*q%1vVOMjXZ5L`Ycy}m3U012I&G4}N#nLzjyED7tRNOp48;6~X8xcBf&{Ir5p zu#{07F3~>SKPf;Ne8$G(4%_S-WHl}@`ia~A3n~A#+(t`4nv9bfHs;WN*tE-S=>@K8 z8Dqb~*rO%PLSGXwiF>CNpl`OeTA*WF`m2m<-UhrmGI;E5x8a9GdbLjNoeRY(qaUnf zHLbp|7SBtjC8M}P148@TmfYzR^j*{ARueih+CGM})0vyBWLc#Aln;_*dGQ*>v$j5M z3&Hmf<>meET1UP0yHET)Y=%|Ojdl=M&@=o*mgIFdwi?M~W#oNcGJ@S0XJi4J4*y7p zKrGD`y5{!IEk$uU-S)B1UBz_C_ljCo+=NWbmEGtk+jjh`aaKv9&c;gTk{(52K(fEt z@yRF&X=KE3;5J>8qS&6%j#(v@wqCgTp*NC{-2xbZG6K-Tb0Q~Bw# zq;iM^8_vK*uLp}gl~y+n)V(_(^Eknypb#|H6=Kp|_lJg2c_o+G4hZ!T&FI&`?y-pU zJ9fM0#m!qOpxtGZ{en=pRodcI;T)pBX~O5)&ZymXk6^er5e*l622~^@?W4>=*;!113(+q;Htg+CDj;Wq!GFAOcN;|8wN%X-(Ua3H6N|Z67HsaN<`#BD}l~E(RHC ze<+{t^gZ#q8Uxu*5ujKY>Dm_u>j+hSvSO~*CEQtqjy1}dai3+C9`pCpE(DroAx(EJ z#z7rdDe=dr?aOJs2D}|I`aUkW+fkU)9HDL*3OK|a!1eRcXc6>>B{JnffxgIS*S?Sw z&Cgn9fNWdU0@PZdnnSHIph2Kvqxl?NcNL5!^Vb&j>y6 zr7FIlQFiwLW^^O(!`@(sXiD`+V>?{?4W0#9N-X&)Rc(-)xHqA*Kz%{RNuebFp8%ZZ z&F^@OzE4$8?fF|R>-n}8MALMXanQU}y7r;=^S~TRf*CEjaUg!c<>L5FGzS9Sz;7ZM zBCua~Ie;74#>(cE1nCikfP*Ep7_$GF}SuGOW#7s`hs0ZH`Qu8*! zj6uT@kXcw3Kg6hO@!Iu@Er@7TF~=we*Iu>#c}+M;t<+f?gem-ywt>j{$hYq$RqbM6 zY+6P=h%F=sHt(O2)%GH66N!ZRcj)Fil54smv8{}Qks|~HhuZKAFv9?B|Hu%K-4Fxu z9pu9-np|$P*!eN+ve?fEh=wlRdlnKS-=U^3FmqQGw-b{h)iaN2cl?Fgm5hFn6o51T zhREJq7n(LFAxBwdpLC&vGyhahTtn2hk~Bjh<3I_AbLd+iIjxsm?NTIA#yBbIw(Ez2 z$vPivqsW-u82fabol4~#0DC}$zf=zrxe>#|rE1?FwO1ys)>^hR8R|b7WgpCsKufrE z_a)kvn(VrY)C>79c0!6**Zv;MGo^!R9LR*B{P@k}Q6IM!*AcUtk-|Qcly0!E3Di5Q zw!|R-KbCPo^w5Pd?{{;8Vs@rEBJy}bX73WLOQ<8{5#2Z`CAazmqtmKNHT(FHlnX0UxLc@Uk|pEDO)|Ii+07p6sL@_4{h(Q|Ih)to~LDRyW4Tn%WU7| z2aD*Tfpe+BjdpM%gVDLATBz1bmAQ3?STH`W^J6`0XwkoH;E>wivz;)ePbei^i9|KF zShK{S0cyU)pzVu;yUA{xT)3Tr%oK}kv}38ybV;HyMi2#BS=mU7oM_RFlZyb-={|RD zzL0kUk{iJ4XR6DpWv-TDgCT|7%ZwZk&|v+C-d-NdD-%vbhWKi>y_WAddDTlGnH6)0 z85Ys(pHOzDPV%>EUXgl*{7soxrV%uB{XGxc#Xcb8V1$j~{`(SuMcyv~pOCjppf`u= z-(GXi5f}(Y-XE<3xsb%UVBRdbB@`Wh)J?@xJe<;Gg;D0Mh?55+ACwUIp9<^U7+V9q z5-o~SN!&hcRF!Rw>sgLnl>lKJaCjhL;KRKP2bMH^xVJ#V0(Djh?cIoJ%+rzFVjK{- zLv0q6iP-8HY+35ZO$_RGWCV5o!tz=HtwlEu#!g|<2vW0c;FGc#7m&B+4z&vxIn))& zv}#cu^+1et&^omYCsDcRwZGW5SNYm<_rUb8jDv}VK7OFNd);{5 z5_l*)Fi!R?0P`=|>y?6Z%c5PSB(UkxLM{h~SF zr>fOO4jWKKuCVMe3RkMaWDd^z%7da_Knsim=#Jv~FNukTxU;(mF>@I)?caE8oe2hu zsC>65Fc_?e4h9nu{sMz_Den|F%6?&JEJkyC#NK?)CsiRX5=>UqncH$Y_@Hj&eKtQy zx#jFlm|&k+Lvp!EAsWm%&7pDc*@18sF$G52*BzBCZ*ufA;~xBzic(c~K&PbsavDdL zhCNW#{i5oC*C0*|{}7K3d;^KU3<*ING1V%n4uVU-9T;^#AlLB6xIxz;1xG}6NnTcN z1=iQSh6gu0R7e=0AGf{sZ}zn{vo-?diOY=xa+Cp~_h;_Dngb)+mmSfKzTcA=u$en( z6hUuWqPVs6n5f&*>MN*RzMeM0D<0e!`x6Vy?|+V>JpCp?96+dH9F(D8`~5+%pDftzqlQb|w`>FdlryHBp5igC9_49O&Qh zNZ;VIHK#o+Z72XrF#0~B5mY*p!J^TGh{Z+xhA!~Gp43oU)LcM^q}n13QQtqIq$=|@ z+;rE;^99qJT~!$NH`{;OpSaBLY)kayn;?h)6_jmK#r;NRUL&UORW$mlpm-XCuQS{-wp6*pdJRFU50-(XP9PiC2+ zvtyrQ^t8|aVsXO1?()+}N`TVs2s9!U)99dz9r_NU%p3R4aHAf4*%bZ{vLTuLmOdN? zMfH8R@n2Qpn4Wt>K%+AG146jwKh!qM6INu)H0>M?Zp8g|k6@?Ykn8(EhDa(QUV~Bg z%U@K6zl#<3U^*ONQu)CcaUc7v>A$Fy)=omZQN(LtNv%cQJmy6jhREo(7Bj*FfQT{1 ze)9!S<&+P#+9!j$b31P2GCT`AuLGRDoF3U>GSWW11G(b2c>D^dLY01%8wVl;6XX0pE9TFY zYt9(ScO&nk+wt=Qv}3*F+9OPdGV*?lcmOna{7j-pjQV!{i-|unOW8@ee0bcZQkxt7 zAX3id2cd_)?gLbJ+9jjL{o*y}V7i}{=wWDp+OmPHxz|wO$a+o-`^5@hNYOiPB_)=UZCgH zS47o%CHa@pPR@(*!&)vcw+srp(GEf?HMZLX3;~wp2`pS~lS0n!L=?O76W;V(DSl$K z>)-<;KHMj^J}_@Dkrr2lEOt^eYCP6`Kcf1GGEQ<5u!O2!B(aG%{_(E{3LFmZqmCqaKuq;OzLO5WL?p4MmX}VjO7NjslO|BsOYEL!nvf%!%emMuhGaLW+=_ z7(bJN#)AqGv2&gypgZ+PV(kn_nW^nM_jZ#(_NM5ZwIooBq0h8#hvUC{}9$ zcg|eJx`iwcszqg4BDsBWS%&N9Bms<{g#G}alLWb;b$8kNu-w{0%H5525I>e*&Z)Lu zats;P91IGv`)uUzQ)uX_W@yGZ&C!2dp~Uo*)s-=zKRPeJ!oh`WFZMf@H&GVy#myg+CxE1H@u+N=FQ$d zl}C(|=$vZqXHEHrE9I1+BTa4`u;6GkFwF^?#bfOyv`eZ}YK3_E3D+98Np-Nx{ zV;poTm>lyi1*!*}&i0Ml5FDYQj>eI2t^HGw>?$%^I5;g@|Gyl`O#IN)kWu!LjYEa$ zJd4T#tDBDFLDefU0QiRm zMYH|OpvLPZw?w~M#(}Es5b6Ba#6-Iuw;4u#47(fm4=E8wd`Sndu1tasElxuy_+7X5 zXXH84+$HOmaa&YHrB6Zvo7drJSxCC3Q4XqbcE8TR(GCZt0tAls;le9$j4!uI!=q-< z#@%=Ot+cl?k&N6rw_c_;j#4L*w~p7_7qv&1pi!`dAv;vC2q;z4R_4>iKn>atxF z8`ZZQW{%lJlo-QWQK3a>u`$xMPcbpZFIvSbdQ*vnJ&V!zSr>*#Z9bKm+j48yVvla* zgQ5jx($7BIYT)9HS|3Ka_L*TAas2`R&>y#rISUL(nfKjNH=mJt6>CW;(5cs|x;YSf z+gfY?#FA7k!Pw6+ZS&FIEAwasX~wZp68c?KrUX)YN}T4+Mbj|a_Dfbn#3#lHjWxPXhM9<16lGhn3SE*T zZX0YZFPMp?w28)#jIs?Q4dSax>fLezH_-qj@LHk@03FbD13&K>-b5F?3pKf z2vv!j%Oj8tS$b)IG;s$dY(arnvpN?`iRc<(v~6sEP_6n4+rP3~;C^aOVC(~S!zE(# z>Rv4q0puC~;8m|)URG5xuZzCIdfnaFhnNJAI+Ken+pE1SI);la0BErr-@*?z@IrMW z<^=vlM&9m;1jJarufCgOJOe{V7+l7F3>O$N5?iDt00SBl+eHaU;lf2ol(sy!kj1lG zXc}+NG6xZ|kGXXcLaJT{D~#r?GT3U#mjQEcl5qgx3G}v-pi&6PyW|U4o+_x?A5mI+ zW;WO`wuqY>Qi|Ahi>P|@8O0Fj!*(bwK*;riGUi+5F57a8svcnM>%IjzI~Iw1viBB5 z;@(41^{>{oXw4=IPcRs!Wqwj)DCXc=B%~v9C&V&%eh*#a;KkD37<(N8PT|AiW%Mz>qz1|_LN-4Tg4z>@d^D!F}Fcml5 zI2XLU&>U4=@6Yz(#v%RT-Gf5dc1t6Cjy#2aWv{s`MBD!d353;!v2WkOLt>1$O+paV!28bQ z?_kD4D;1tGLfqyU3Kyd=LXc|2HwQf=_~Ry|Nuk!Zrp7HewLlS!J;pw!(%gn0$VXR! z6KH8tagqkkLBI$A>J#9xLW{=i9@0}S`DDko+w{XU+XAklL&K>igGh7RZT^AjJFTa! zbZaj+>UPz_+?H?Js(T%`*2PGU5w3&Fhr7+O!Qqdg30FYKO%)OVE`(?|!7JW`7M76? zcCA>=zs4h1cG+7kXfnvC+x-0I_80bp)p8mP;?RyC8dup5EYkQvFJ)yu1JF>MM&8D8 z5)}O#ZSrYYIMx9LAbkL*qDIKM+Ey4fEG2c95cJ_H z)>}>))jXBaws}0vtt8JBzC}=8s+UN(1S*6MOV^F>FkiXY-@}cxErB4VO&GC6zb2Up zrek7~0s-^-=A%7NY7aW5akQKoi`17BY#J)&Mn|@HU>WN z$Wk#ZYOQKHnUS_fo{)z87u3PDodVAoZ0nXME5Ao6Ar=f|tP*x*LqMn4A#0l)b)ZZf|TAl-@0jk?`7 z4RE`CQWW2kB?UrC#_42?ZD5CjuaqajM7vbz%QIR;`Yx(!u)eIFN+pQ{&y0GqpeU4= z3EGLFYN)HYTPVI6Em*~h5=I$a@7QklYr9(;fGa>Rqo>U|K~kAHAEThTZL$r_2&%*j z`19pP+QyRv$OOLAt##eSi`Z$n(YKL>`m6uI;_n|jCw;}*C1PCC=Ks#;Ut^FAy zb+volvSWs;$SFa47hBS{xa-?3TpF2`oC)9$o)%G#sVd8;?Vw6-_mM6`h*tTt?+O^+ znkX|d>NbGJ`PGV3S0yDRf!e%SG85DmEStI(a%Ldqa$_IuKmhTHD7o_wyNR0!>Sgq8 zCgyNydO64`B3zoS4MSWRwr67)FM)6F{|X+WgW%Xc>q3lnCohCogREVM(JJkb^|U<=x)(CW!2#8NQ7O*rfMT>--?oET-j8S6 zFBDRFT|VILZAZz-C*QVy!*Z9<1K#YlCpX46`KP&Mkn`?vU63Z((*}qjA%C!If$rJO zUs&k8shgUZpWY_S3IO<=Q5?6!+k1Z~W=%@*OtIo_{1@gjAezIlBxL`PB3vO^|D*0? zk?SQOz#lrNq_wntDBr|YCb3Xe`ZqGtHnATh-4h#y^Z|19K%;V%{I?k7uLs1!ENtV$ z%NW~3rvcjPBL1qVIT)^+hBBEK-l}xqRs+Vo*^LDHJt6LXa9~&n(-fOiU9{IGVax)} zr|4R8m%i-tv?DUrfsx`ty{~hdR&Rya0&S3tS|-wxBAU)+{-Es&x>X`Vm4MYY=sEzx zEO9c%_nH-(*>&H*91h`22-4Tn+ESMOh8cr`-L~8Ee^5^(*DEkXV<^epc3b~J->%Ur z`}^CPwrvB*t3W(t!4j348|0@HlLS!4*cKZyx9tazUw+(LP!TRS;x&r<%`yxxyiuEY4KSNG zV13z*vfuefsBl48>_(?cP3urKsrXmRC6bb`+_sBIUPjtK6oV)?Cnn00$sq>N5r{jzBBSs3ngW=)&q>Ht zDXI2ywURORHJJmWO0mt(nqAmYfbz(A09O!j9PK)RRxk z0oW$UJHe`F=OH{amzo7lO|CK*a=j9y8O4pUAIv~y{>{^PvkuftDgJO{U*g;TSN!pD z25wF5hrifk^%yG95Lr;H8alcK#f`KdE|TZOJjLz$aAt3&xCD5(qDH1~{0bS5WC>)X zgSaA$AF7OZ)>C8b3H3}2=rFh4#_I>-!n~dqekUlFFxvJMejqFUR-dlpcH4*jPlg+L zzxy9VCGKb)5-GGbC}20m$*qer_70+|MKDt4l+m^)#I;PLH%%dU%SBKJ+m75m1+Mz| zIvFjtxf+2EMi2Yh7D%J-Z0kN58HP#PJ{WPEp(F@G{xvkcHmx0Ikc7BV4{rD?hU|^$7lAGDBBStbw0&f3 zpskhWUCUs2mJC1;tpuM|Bo=q{RujC`Wg2~(;742V8?%$wLZ$&@i%>@12dS#MBG%7N zRNTC6sg@q$oGqO2udOd@=~fUu4SCntf5qvSD%2g7S4Jn8E0D3T_Y=UI{-7A&Z@1At zHS>HJ`vh}=Nzt4puERDWy(c6?Xa`talbI2FDvZ_sK4PH2up8vyY40NnpjoUshWVbu zPbdbJ`+8Q(ap?@ps0Zm5ItJ?eQ(&`jSTv(>`ba~>?(jF?4dN)BOi)JJACN$GEL88p z=cp?iQ457fw!&)F-E;4q3iG8cKN;i1E2^Kqci?|%(o3;7%$$v-LTr_#ux-vpZ3J#r zELHm<6tME(Rq|RPY-uI_&p|HF0D0jP@P#d2J6 zliUOrmOaxi&2F^);(W+INWzT!4fkXhz%`9{5XsP#{6bgU!)jG*#BCaVzo8cLFQ?O; zN8>ZPTQm06lmh)$SJbn^X%y9d;Eru#P%izPk$KB#~mFFXIkdY2T#ca`2oFmJqX$r?tQuPVBl$aM^Gh^nhK~Lqz zKGA1D#q7I;yMnf1VHHzUGU7okRgiLr9y8*h1`i4|I*NmzLD%wX37-C-iK-Ka(Vx!VD4K)>n_loaK-ieU^4I0L z!#UGr)Pn&oDnPOL)L2T~G*NV>m)Ia%Q5o!c-eK1UC@M3!Y4^SUf-9dJs9iu4!ZgbM zh-m;%J(rJpt1$k%(Y7g&HKY4Y zVRYZ{<_NmcY4n3nTYo7+jkRe3g^l3GzPw#vGU0AVry;DX-9D%eJC>wrV4&V!Av={< zGseM!0_x?w{|IFXLVclN0a;MB)3`7dP}ZjO8b#Dn+HwmF*p19Y z-?rNq+Q5S0A~ikRB;My5n)rM!pMY$o{r_OVkhtxZ8rM9K?SuBBi9B1s$=8_h9=E_x zvppUe)|U~tB?Oh(aIJa5#VnqJn0ombWTURODkR_tC6?iU!h?$zR7Um^E;}?TK8LX3 z-;}ZCf$l3WS_s4Zgp9b))WpXD1mnlCMGX3|NMfq*L+H@|-4yK&J|oJFGV;Nm1wipt zu3mv#wT6U*3FPzwC%$t7LupGB=hfC|UxB(SlPF1g#K<_(gl=te)lkbHV#<;xUavS(hzf3ugI6rdgpb2w^?O=^ zcLmfrMmZ=Q^jDqS7R&HDd9j76I(ZKQ6+UjGW?^KE{rN{b;ck^vgh-@JrCLxAQaSD7 z&bzy`4Sr1$Zj5p5Bg#QFO#ZL*XCE2LOG|lZBWc>S3JG*~1wdFAU&m&Q18fEI)}P|4 z_rMK!?hCFZ3=63C&t%)C-De{}L{U=hwtpal0?0m@q_4iVtsTVl{$!MW!VJ5tf2sK0 zxt<-P7g?x`c7UH$jn69<16d@2-lVK*e-8_F*thZV+6qCBjDC=YaGBI8JHyy=ry4>smmJB*9Z!w{;fx4G7LSB^D}s;8P(ZNj_N7u4ow?1jE?x3=IL0If>vhSefuvA& z}kR zqwsgT$(#+1ZOdpU`=|dR&3M0KXa~1n#@8|fyU(*UtTph zC?oAR!_k3FV^Y%dtjHQc(A$OWE4t*C5SV!bMU~yi`{;^zfjF4NNp|ZEFB&wsEkPU< z*YS(XZStxrM&D<8j-oETpElCx;*w2BC(;cWev^;ow%Uf0TcjPfKdsQj`IZQgh*PnL zY;fQ($Q2vWY<|8i?TF$=*&nyzLlt4IDT9Gxpu%WR9i`u7i6r-5Uf(u3`LT?&f7y!h zet4FNN^Mfom4lMKzmhM(p6^{-n1ZJsh0*rW*36iED%$n+itY3dg3@pebv*+iorM`GL0Ye%fjQIpdfz4zeGh@DovJSDw>SfheT>^8e3owOYGfMp;G*`y6Y8 zE#Jb7x0+C+e+i+FjI^KqPy$M6GRh&b1@-gah19e9#m(8c?x*Eq2V;rR5BirHU=6co z0TmzY1DsHHU*(=V1So6izz)Wi3u8M{E60x6* zgDx@1h0jj>Jr-_@i<)Y5qaIv6{OL~FMCgM043L>lmJOv{)8TjXVwtycp>`o7?nC=1 zS|=}ABqjwUM8=p=)$B`8${|yDxn)FAM%{-+aTLcmr;CDPcA`C`IIk=jy83_Dlck$> z#kx`U6TKMM5f#yX0n%Yd6zP;t2bS>+wlY1X5+FuASy150zu}Yjr|sQQtTOU`HH!Be z(`4ha@Q4E|LEI;bj=!MUo146%A+SJMMMl{da)?aU#7R#DJ5`r{#MPXhJzs*euiEvn za2hn#cnls87_&8N(M4A^n2T0e_&yG%9{fk;*i`(`y6`oe1^u0XuG4a1qE0r=%)8V;L4x9 zasj9vhFyyoNL=r`?f<%{`vhSG)Y3B#dC?PKsw%#Cd6D|*)PH3hP~F5RN@a74D3xS> zp*P6T3lKyBzFxy1I2&qBV~l-Lk|-9CDJmBl16!7X*upBJl9(j8Wvye|t&nrdI6!!F zPI!3CS%C(w;^XWrU4QlkRj%ld+Y$9?&BzD$dy-~?-Z7&O+0#8(m>GtrZ+BNVyXBr1 zFb6l%K4DWND^1R^#`)l!xYdbdz&?wSG2dQeP_05nYx_43Q-z-zg*QohXEct3QbyfJ zP!bqd)l)h8Nt5j#0a$=ojA(ww`jAUAp#gP-8wb)wF|7~^k(VBnzIPGS5<*46eeY4} z4y_bOAsOi)-{RDtJSbJ8=H|>cqYsGN8Nvd)apjONi~R;89yBDlc0!*WuF7}@Q19l2 zkw0{m<5RPya9@xr!Km>df=c7XssNrqtO`2cfj$7$d>~+5^r?17V&sG22xbs-ne;0V zM~lxV_Jn+B_-oSDUh!g&5NNmIMn2fI^d|rJL9t55=8MZUxiJnlj~%|>V~At9MVG_A zh>Qa{AEh}T>*?-=cMCuw1nDvk2-2hL8h?yrjOEp$wv=UrgPuSn0FOTIUlRBq%K~7* z<-Pt{DlPQ!dchXG5Px9gu+QZa34lK#c6TYYr>hhIR5I%R=p!rw<(|&2D5`Oz6VD`p z-FmrROo4c7&AtdmzYYR&BJfXIo$|P?1xgZ(dL5Ky=u|16jl@q-FEz_&RqL$7LJQrz z?d2Bj88_NN5vu&s%3IqfK^1Q)mW;gL3y&rIz@>eo_nFwz{1iq!0NH`i`PL1OYbEQ# zyJYl}yN82(%w+2d0OW-hMK@e%QAv2F^|Xa{a+DFn!D#`lNt#-wwmE2@BJ?7CJk(f5 zenG(SX2I!@QI4Lr%t`5i)+JfBMZ^QxCM`XfPo6S4&ISk{8EJnQ9bTO;eyF-WY=O}_ zxsmqgd>BzE&a;W8jwq)9KhucKP)79_|MOujzYB89Eat(p_KBef7~0f!u-Lq0$IxG} zj^1Nqw#uNmYcfhaI2SnxKMNIUt)|{H_-+|(pU5GKru*yixf$KMkh3w!5K+yx+c0H| zpdk#dw$gMO*wJAzGA+vSIPEBQ$%y;iXzG$N&bF{ESa6Jycijaqx0qF<(9g4WbZOnF z2gT}|zOn4hP&5z@+j4@Ay%g#Mmo`xq3FU%!;|&Q9H|l;992`!r zbLzgjRCT3V9fbl*wn4|!?CErF8(Y?la_tY(5^BbJtAY%jidCAEYQIxzgeO)b`WaMNC;zf5J zVEMaj#j_>nnuX?35HB)DkmU=P1mR9eOhdW=+cQfa+%`;V_yBh}#|Q?7i!B)>#j7yx z)7ETovoZTt5YL@KhILyT;IAl;<4hw6v1-*`GCO(1VjE)vsQ3q5b8QPs{` zl&PRcjEwzsS=?Rb)dEcv!p$nG>IK>fYQH_mqz0KP+2+)S*1*NG%%G>lGy6Q|mkhvj zlbLo8Y9yw$Y?V}?f_P4+VuzZ!Y85@ZC|7k&mX&|G|UlbRiR9bl}2n-L=Vhp$YZ zX8_--Rd}Em6_ktZ0>2fJAUS4366@rXJIwqhkzR1ft5pJ2l($X61uam><=5V(->cHK z7(qN&?Gt7Al{;3~vQ~v4tO3--T^IqQFO}nDBPO1t^!K3zP+xMAf3a#?!`w5EVDKkT zmn}bt`aG^L4Hi|Cp1HlsH@gM)%56%7q$KHo&b^`&g4;g2iO;gV1)xw0`nlOmXlO}> zk<%o{Bqrm9VlNe`oSag>1|bdNJ+AEp?c$V2_@qp@j_X5njTe}!#YYK_!~^PRJtUO^ z3fegvQFNV>^!b3`ltxIB_&wx>7BoU#i#Geznu6fYDFZlgg*bH)qX2^F$R)_}oW5yr zv7fWHGkaqA(g9^(jA=Vkn{|A&cAU^&qEI|9df!$UeV(CO+9Hrnwb06GdRrZF?vb`(-d_N>- zR=s=a3xz$D#>pT6IwXkUocqFdJ50FnxG8lEFHubxCR|weY#$T~6^GWHf^?Cq;t}EI z8|CaMuQIRe__5ooWu=BR*xX(=FrHFy!H)>?Px$YTcE83PJ{YxI5HEZ(06T{|yHU3D z7fC0f$f6g^?y&qY*Rr+)r|d>h&t=EZBuc{^q9yOWB@`$Gg z2tYGDYhoB~TXz?r0Gv ziBk9BtDPD*k1wHrR;^WjQ3}$z_X!;xKEEM4)R3JNq z<7MNdTdLp?1PNSh7<5ZvxED#S#}pz4mP0eG|30s(DHE0^c0+3F#jJY^Ahp+o=on>_Kz)w zlQb5$Sc<8Z)d*GmG|4*+D$JY|#B-_`4a>>P#z&wE0DxCsjN)Ynux0yL&j}NnFoJ$A zm4U?URI(0K0D~%A9SKIXk0(2T&|y8=W`8xSy9la3PsIVG|KKd}TrDRO%}xcXNlurQ zk;^#QhnN>{RufGBgL@p$aLSv(SGp3q5)S@f>a( z1Mt)EuuA14WCd-ALxtXMe*9uQT8RT@GAKy?ynGfnEKR*6E8&~QXjNiJI94RN1Fd5g zgD)D}3N8d{qeOq-XeUo?*P%@_=Twj{5-2pvdmh^{o2=w*vZfQr>qNAi_p`Nvt^g=i zP|t0WNb#H6nW4*v7YV9Q#`{t4R-?7H)JW`A^Qa+@;DQqo*>}rqwjosE9)5CD*DZQM zMb=G@J<%mlkj^!Ps7s4@Cp0fBCYnV?<=9|IC6VUs(=O;WMRAxFg!2(?RCnu5;N}_Q zby|&u!kwU-p%)>UbLd%38NYb6wwk3HeFW_Soyu;Io@Wc-RicD7 zH;lC7XRy>)Yq3M{%(j0ksOOSncqqK0W*$3Fd#`b}WM=s}N&u#>h`np(%wv1Mx6y0o$xXr(|z4jXg4x9a$ zpoNQzr9IHc_hTDHQ@6kpQ8~bTC}DYiYgu5hJ}Ma61Eq<$SOuPV^{3>}ng7oq*35dO6HP?30dbhSxh-xZFoj&Xps;&QIa5@L{)& zL-?ypq6E1nS=c@KjGZ_P4@XeWb&CXBOrxXOGTKm-9$h17JNpm^S@r@Qe?}-(1kqiz zG}&b))Hypx86jReWR<- z*j-kw z$kqgv?V|BDJ1_kxyqvWEu2b_v4T}*(kT43;^M8vI z0+qmbhT{JrQ`~ISNBBpd7?Q@4u9lU85CGv$p{^jYSyit`x2&U0E zV$_D~Z$bwlIe{HZlGJ8iFLf$n+s^31%?V&-)lm$%(Qa-}1R7h^|GJ`LhJ#&%H}`EghYCE?KN zrLScZCOCOU@glncY+GoMWJRNWb&Q9-z+s+ zqy<5gFW%_J826DwkQgKIen<1y3MOYckpIp+7&)q|s3>1lYVC&xR!MtZ848XlyPGHc zi=BGgua+>|eMaE|mcjcuT{&qAMi~@15eOq<8zB2vrj@I`byS6l`pvSm+2?o+8v+Rg zNKsWiv@STv16J@<-o7 zQ0cEdk6QP__Vnu$)r&DGxb){4w*qt_6(;OW;?#Byb2s~b#)*kQA5r!<<hTLD}&V z%0ew63Bbxg6yfo&WpgRgmr~R&>S4HTubXAq3m00^bw=@AdLznN=|zHX_ge6flsJzf zwPsG&wM|KqAJVgjfm~=11D>;tt1FfMO0-G`I@xB_FZ!kSZZwIa1{^x+j<#%%dU(Uy z6_auKy6$v!5T)~s!o}DO9@MLGz}`J7*1X!NiSl{>kXaqQGu>(z=o=O%D?Sf-s1{i* zwXzqcKb~e(`tcR>LjS;)T`!k>Yvj2_ly0sVsQPpp@wtg2_Mt9NTdRSq`u>`b(pRHI zQ8^zzC(gb$2U(*3YQMA$P7_&>wQkD^s4bl1c)2Xf=M|zV!9In>EXWehvBQd)R)%z* z+;_jlzTB*ql%jHuF{9r$1A|&&E|NMR=Q0Js&J3c1Bf*bPyxH zoCuIqIE4t1RArD~3!?&)@{IC%+k-l@i3?}xUD7nKl@IE#!O}{Q)ir(ZT$SNSeWGv< zmVuo71~+bd*w2b~ZASH+xJx!YJ9!>JcNKXF zr&MJju?d~JyYUSt+o1={Jo;Su5z@tbx3;*w@BopHsGh3`aUQ;@iS~6OHe^%d6J2zt z6XH{GG{qT&duiTxdwXaWqkZ|sQqXF(t1E6%^XCv2$xr<%6Nrtp?@s+gqHx}uhWq!% z$;(o`zvR zV5BF<71J8;=T~fB&iiSY_7z*@FQT}ja?ayT61gga+L{=2OXa!7k<~H?cH1wO9YP3%F0w?%`qo z?RF`K=7WwybhBfH^rV(D2?R`Osby($mUvRj{e-QMslxM!CE_oR;qVx=W2g-$S>`qs zNDl_>MJ`ft^|g9r=n-d>&oyf$jq$Qs_Lb3gwhU2$h~haXF#*Er6J?0FzP@2AU%EIG zrO2E-b_n(BW2R5D4#P4sH&UxEX!V9PNbFin&NCB!S*VX zfXVkE-1kW@cro>)n0DmUQ;`q`x)EDQOA?Ds9#j!=?4Xd zuM4)cWAah4!a2v&pkp1we8jDzw!~CPdb;)vqqCj9@HC#@bsaPri~2?LFbTDyL@O7# z3k+Sn0LkG)-z+cXdXJB0_4$d?xfUs2;&{L;$U~DD4^&j z&5oKZyS=de z?UX_jrHd8-3~O~Bu>WbmzwFW4o&rV;LmFdta>$XMp)y=s3Y zO&@OiZW*Q}QLaTDO<>f%>VJ+&J37LQ+Brasaaa3ti9#D^JOpGTyJCH zCMUh)g~_$1(p3UeNUqfq^L^wZB-6cIdRVTfR>rOF`KC@oe*9gsZS5Y(9;~oSirU3Y ztE3;`7Hg)(Xr?hG8Bsl#GUJU-qhNwK3(ymZ-`)f~K^h!Ws@;6BqbQEgiReNc9A?fd zmS+Jy?1Q!=L;JKvE%@`381_t?njDTyRZ<`or2;s+maKmXpLkE&8FexdU3i8jiLk$z zovc2d&p0*cMrUk;&MnZHJihX=7Yfi;If%SJN0>r6c=xJXU~ON>;FVok6vDY}9Q}hg=+ajTP;3Kts#b_DC?<*VJZy%_8$o8K-AB9_o+Uuc(CXU6x51` z;I3AD6RL6_OeNUKF&A#lU9@VkAb%+Eb`I38Z5rl-w(0hd4!kXAHS|!VBD(Op7xY@q zY1Fr5r`12952P*nYT55$3ru_!cOxnnNnS-YLC@C#qQI@LV3||V#o}h9y=Dwf`xQ~V zn6pSp`OPC^;j~$a!!53I&7gDny)TpoDe;~iv;f*4Hi+fQj)T8(V6b$F?Wdg zsCJna<|uZ0CbdO8WlwoP!uz?f<-Zq`>HdQS^Tq%)2f#AT=%%>@VL~&23SOE9ogEVe zfgCg#0;7rD4{sXIwh^TZ)hu*5UU#g8|Fb=uad?s_~^heXZwIj1S|uw zJi6!a)39ao*fgUHhe*+7av5FP?9|N>eOEIrnuzJE25-2`&g*U7pBo=AcpnfR#>19q zO4uTUvI7y2hvLuzmikuwC?$xxKi{!3c=$L8)3`}Db?#D5sKOlNRww{DkoUvTOFoPmlm+W#}U&XWdt9|ICm(uqgR+ARa;_ z?;g5)nr1sBc(f7S_}yjgg)^B(MJn@7MYc_L>lE=L`T|>Y+&|nCm2-hXFxRh2Kufcd zGpH7G^l;&W1YKUD^0CQlg=!G}YI41fX`)6@5ARpeOK zq6-uca;jzAXr`ksY4VRquxI9h3|slq#bF-ZhR|PEH|F>_1bG(9gn48u45T>QI{gmL z!+@K{(&^N4y^kwKKkQ~<%VEPzX|WTL^BkJ}RUeb<%-i$xG2tQKN_nDwZrYOZ-ANCr zwnU*muoeNr>^X@8y3lJ~&`PwW6_xYa0m|$Y#*Pw(PMUO71_KCVcL0_4&OZx7(pKi7 zsGk?6FzP2_$`1S%Mwu3|(-2~+s(lpp!qLhKAtH$4Ir=a&T**&PI|!ICv>0Y2Oj#v* zx9HjuN_R?=h~oJKfEMICIPFm#^paYWY?-vr+&RZ|&T#%SnO;f{q74dTDIT9YPo}e! z-o0`jJbNJwO9Dv(6CiBAgt@)&sM7gYRL^tTEUouxMIqNJa8fM{)mwV}UsfvM91_Hn z8MSj5PnN~`K*YBpXoZ3%=nW}oiZ8rQr2vqr=z59T#i=Aj{D1doS8izsgQY_LiPCxZ zKeOLX)KVO}>rlnD>j%knf4@~Bw(&wJYUjMejNCw&)=T#9iRyq`iphRLdq-TqH7d1p z&`PxSL>Jsroa58@d;xU6<&H1yABgq`*A!gU^o0Ifh$zn0N9 zEO67Ou=?{me=enws$ ziPLra4_*yvKVf?q!_-zU8eExg|-#dUIMZ2CPlia+lh;#)oSB`nG4)en7%LROEygd3)dWi5<;diOIb=d-0OMEv-eXrM(M z!!3z__W?>#cFWQZK^I^pj;NjE@R&-LFl)3JY2>t2}2WG=^L{n657Do2g&l*i^8as%=Gs=ZACyfg8*TVMsxhHDpj>A;aIn3|}w3nM5| zXOlW7NMgjN>xLhA4|#va z_7+I5S5ZF~5E)bE%+7@vjU51_P{??eK_vZv*-BrOd|T1#8KE$UE~HbD`G5DU-5;_g ze>2_fy~LZhD^D~YZJq{*h~p6FN0~48Val^ou3|-aRZ>mV&viAkfbsKt0<~22J%wC^ zjJJK9uXX`FL$Q-fcveOI93&=E{p2s(_Q7lc{<4d4@Rx^-<~p59EMB~6Me$tV5`We= z-t<@1RGLd-7AeXXnI07Uw;j`}i)Uf-o=&0_aAOYV!&*Jb*-ztucdC|r7o){qa&_zX z1Fn8Z+KlKzIt|{&JHT{7Y6I3_;zJVEoAE=T9q&iyl2Mv`F}>jMIPgSO`{8S0jEUQf z+Bt?e516WefL4!-fc241_#aYnh4%CAP1E>L?W*VkoQ@vXyJYL4P1E_Xk~obhUg$k% zHQTG+EH5K1Iy|1^76P{g97F39rb{mv9#Qreg|Tf(lj|87>%etk+CgVnTun9<2zk8oh3f;><}koPQebWSR0Y;{_9U&W*mv6MxUp#wU9ej-sQ5CK;sAR}ZqX82 z5xGAYCYJAX%hEh2$1X+bT)zaw-;^QjAN=m>kRgP{gA8GiH9_7BTfXm<1Q3Ob>V+}G zJcvv9;{kGR=Erfr(&g0Ll`=$ov@Ivwm!Om}8 z>{xYcE~kLSAR;`iN$&8&fFo_)gU~TZNg5957Kqc`+9550^=)6 z7Y$SUe=VZZlGvaQ%6hJ$4MtyWwCZ+KoO7b2Cu$eT-A^*{t6>_QLsufsC|>MXVB))< z9gir9yv`>)Xr8t(5Z2Y>vA-jSRvyvl_M9%99#aiZj|clMCbmGhFx4okT$UQ2WmZAm z2}SV+xMZhM(-N8Ae++2YOU=Im#*^9DVrVXfOz)Cf`0%^^(B;^lPMry=vhAn7tiHys|kp+&L> z_9EG*L>i0i0j&Lptm$ zMiWVDS48=o6rTamj5e)(OBL~GxjfM4iV2>YfLeQD+c{KJD9Y!)rCIf?EJTqG300h6 zv_tafWZ7vfm{9*(8$x~^QTFHlcv*n(H%?yO3wPN}&M02w@t{dwCoXG_$Z|OhRf5jc z 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 literal 0 HcmV?d00001 diff --git a/tests/data/plots/bbad85f21962bb8d972444f7f9a3a932_chrombins.pdf b/tests/data/plots/bbad85f21962bb8d972444f7f9a3a932_chrombins.pdf new file mode 100644 index 0000000000000000000000000000000000000000..aacf018f8652e82665b05262d2964e6383b4c08f GIT binary patch literal 18712 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�L;YJyV*qMkoZGnWsQZuymrsu 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�ROb_Bi4_^_`*uQ|nPFzIQcqhumh2I* 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%0AR-}dA#{^V15yB=7prP!M}=_2=oa|QBdzwV5m@b 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 LCq#^2?D; Date: Fri, 22 Mar 2024 15:08:11 +0100 Subject: [PATCH 26/61] added title to files --- bbconf/db_utils.py | 1 + bbconf/models/base_models.py | 5 +++-- bbconf/models/bed_models.py | 2 ++ bbconf/modules/bedfiles.py | 13 ++----------- bbconf/modules/bedsets.py | 5 +++-- requirements/requirements-all.txt | 4 ++-- 6 files changed, 13 insertions(+), 17 deletions(-) diff --git a/bbconf/db_utils.py b/bbconf/db_utils.py index c04678be..98836552 100644 --- a/bbconf/db_utils.py +++ b/bbconf/db_utils.py @@ -138,6 +138,7 @@ class Files(Base): name: Mapped[str] = mapped_column( nullable=False, comment="Name of the file, e.g. bed, bigBed" ) + title: Mapped[Optional[str]] type: Mapped[str] = mapped_column( default="file", comment="Type of the object, e.g. file, plot, ..." ) diff --git a/bbconf/models/base_models.py b/bbconf/models/base_models.py index 63d38068..85ed64a6 100644 --- a/bbconf/models/base_models.py +++ b/bbconf/models/base_models.py @@ -3,13 +3,14 @@ class FileModel(BaseModel): - name: str = Field(alias="title") + name: str + title: Optional[str] = None path: str path_thumbnail: Optional[Union[str, None]] = Field(None, alias="thumbnail_path") description: Optional[str] = None size: Optional[int] = None - model_config = ConfigDict(populate_by_name=True) + model_config = ConfigDict(populate_by_name=True, extra="ignore") class StatsReturn(BaseModel): diff --git a/bbconf/models/bed_models.py b/bbconf/models/bed_models.py index b20a9e6c..9d6c6b68 100644 --- a/bbconf/models/bed_models.py +++ b/bbconf/models/bed_models.py @@ -94,6 +94,8 @@ class BedPEPHub(BaseModel): global_experiment_id: str = Field("", description="Global experiment identifier") description: str = Field("", description="Description of the sample") + model_config = ConfigDict(extra="allow", populate_by_name=True) + class BedMetadata(BaseModel): id: str diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index a3446c15..92218f67 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -188,12 +188,7 @@ def get_plots(self, identifier: str) -> BedPlots: setattr( bed_plots, result.name, - FileModel( - name=result.name, - path=result.path, - path_thumbnail=result.path_thumbnail, - description=result.description, - ), + FileModel(**result.__dict__), ) return bed_plots @@ -216,11 +211,7 @@ def get_files(self, identifier: str) -> BedFiles: setattr( bed_files, result.name, - FileModel( - name=result.name, - path=result.path, - description=result.description, - ), + FileModel(**result.__dict__), ) return bed_files diff --git a/bbconf/modules/bedsets.py b/bbconf/modules/bedsets.py index 970e21d5..f2f55555 100644 --- a/bbconf/modules/bedsets.py +++ b/bbconf/modules/bedsets.py @@ -4,6 +4,8 @@ from sqlalchemy import select, func, Numeric, Float, or_ from sqlalchemy.orm import Session +from geniml.io.utils import compute_md5sum_bedset + from bbconf.config_parser import BedBaseConfig from bbconf.db_utils import BedFileBedSetRelation, Bed, BedSets @@ -117,9 +119,8 @@ def create( description=description, bedset_means=stats.mean.model_dump() if stats else None, bedset_standard_deviation=stats.sd.model_dump() if stats else None, - md5sum=md5(";".join(sorted(bedid_list)).encode("utf-8")).hexdigest(), + md5sum=compute_md5sum_bedset(bedid_list), ) - # TODO: use md5sum from geniml.io # TODO: upload plots! We don't have them now diff --git a/requirements/requirements-all.txt b/requirements/requirements-all.txt index 5bb49842..d261e982 100644 --- a/requirements/requirements-all.txt +++ b/requirements/requirements-all.txt @@ -4,5 +4,5 @@ geniml>=0.2.0 psycopg>=3.1.15 colorlogs pydantic>=2.6.4 -boto3 -botocore \ No newline at end of file +botocore >= 1.34.54 +boto3 >= 1.34.54 \ No newline at end of file From 392545562c74376b1fba1c544829e8e6f14c84ed Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Fri, 22 Mar 2024 18:37:30 +0100 Subject: [PATCH 27/61] added uploading bedset files Resturctured uploading files --- bbconf/config_parser/bedbaseconfig.py | 100 +++++++++++++++++- bbconf/config_parser/const.py | 5 + bbconf/config_parser/models.py | 2 +- bbconf/db_utils.py | 20 ++-- bbconf/helpers.py | 16 ++- bbconf/models/bedset_models.py | 10 +- bbconf/modules/bedfiles.py | 140 ++------------------------ bbconf/modules/bedsets.py | 24 ++++- 8 files changed, 167 insertions(+), 150 deletions(-) diff --git a/bbconf/config_parser/bedbaseconfig.py b/bbconf/config_parser/bedbaseconfig.py index 54c64473..e7ba49ed 100644 --- a/bbconf/config_parser/bedbaseconfig.py +++ b/bbconf/config_parser/bedbaseconfig.py @@ -7,7 +7,8 @@ from geniml.text2bednn import text2bednn from fastembed.embedding import FlagEmbedding from geniml.region2vec import Region2VecExModel -from geniml.io import RegionSet +import warnings +import os from pephubclient import PEPHubClient import boto3 @@ -17,8 +18,17 @@ from bbconf.const import ( PKG_NAME, ) -from bbconf.helpers import get_bedbase_cfg +from bbconf.models.bed_models import BedFiles, BedPlots +from bbconf.models.bedset_models import BedSetPlots +from bbconf.helpers import get_bedbase_cfg, get_absolute_path from bbconf.config_parser.models import ConfigFile +from bbconf.config_parser.const import ( + S3_FILE_PATH_FOLDER, + S3_PLOTS_PATH_FOLDER, + S3_BEDSET_PATH_FOLDER, +) +from bbconf.exceptions import BedbaseS3ConnectionError, BedBaseConfError + _LOGGER = logging.getLogger(PKG_NAME) @@ -148,6 +158,9 @@ def _init_qdrant_backend(self) -> QdrantBackend: ) except qdrant_client.http.exceptions.ResponseHandlingException as err: _LOGGER.error(f"error in Connection to qdrant! skipping... Error: {err}") + warnings.warn( + f"error in Connection to qdrant! skipping... Error: {err}", UserWarning + ) def _init_t2bsi_object(self) -> Union[text2bednn.Text2BEDSearchInterface, None]: """ @@ -166,10 +179,14 @@ def _init_t2bsi_object(self) -> Union[text2bednn.Text2BEDSearchInterface, None]: ) except Exception as e: _LOGGER.error("Error in creating Text2BEDSearchInterface object: " + str(e)) + warnings.warn( + "Error in creating Text2BEDSearchInterface object: " + str(e), + UserWarning, + ) return None @staticmethod - def _init_pephubclient() -> PEPHubClient: + def _init_pephubclient() -> Union[PEPHubClient, None]: """ Create Pephub client object using credentials provided in config file @@ -179,6 +196,7 @@ def _init_pephubclient() -> PEPHubClient: return PEPHubClient() except Exception as e: _LOGGER.error(f"Error in creating PephubClient object: {e}") + warnings.warn(f"Error in creating PephubClient object: {e}", UserWarning) return None def _init_boto3_client( @@ -198,6 +216,7 @@ def _init_boto3_client( ) except Exception as e: _LOGGER.error(f"Error in creating boto3 client object: {e}") + warnings.warn(f"Error in creating boto3 client object: {e}", UserWarning) return None def _init_r2v_object(self) -> Region2VecExModel: @@ -205,3 +224,78 @@ def _init_r2v_object(self) -> Region2VecExModel: Create Region2VecExModel object using credentials provided in config file """ return Region2VecExModel(self.config.path.region2vec) + + def upload_s3(self, file_path: str, s3_path: Union[Path, str]) -> None: + """ + Upload file to s3. + + :param file_path: local path to the file + :param s3_path: path to the file in s3 with file name + :return: None + """ + if not self._boto3_client: + _LOGGER.warning( + f"Could not upload file to s3. Connection to s3 not established. Skipping.." + ) + raise BedbaseS3ConnectionError( + "Could not upload file to s3. Connection error." + ) + return self._boto3_client.upload_file(file_path, self.config.s3.bucket, s3_path) + + def upload_files_s3( + self, + identifier: str, + files: Union[BedFiles, BedPlots, BedSetPlots], + base_path: str, + type: str = "files", + ) -> Union[BedFiles, BedPlots, BedSetPlots]: + """ + Upload files to s3. + + :param identifier: bed file identifier + :param files: dictionary with files to upload + :param base_path: local path to the output files + :param type: type of files to upload [files, plots, bedsets] + :return: None + """ + + if type == "files": + s3_output_base_folder = S3_FILE_PATH_FOLDER + elif type == "plots": + s3_output_base_folder = S3_PLOTS_PATH_FOLDER + elif type == "bedsets": + s3_output_base_folder = S3_BEDSET_PATH_FOLDER + else: + raise BedBaseConfError( + f"Invalid type: {type}. Should be 'files' or 'plots'" + ) + + for key, value in files: + if not value: + continue + file_base_name = os.path.basename(value.path) + file_path = get_absolute_path(value.path, base_path) + s3_path = os.path.join( + s3_output_base_folder, + identifier[0], + identifier[1], + file_base_name, + ) + self.upload_s3(file_path, s3_path=s3_path) + + setattr(value, "size", os.path.getsize(file_path)) + setattr(value, "path", s3_path) + + if value.path_thumbnail: + file_base_name_thumbnail = os.path.basename(value.path_thumbnail) + file_path_thumbnail = get_absolute_path(value.path_thumbnail, base_path) + s3_path_thumbnail = os.path.join( + s3_output_base_folder, + identifier[0], + identifier[1], + file_base_name_thumbnail, + ) + self.upload_s3(file_path_thumbnail, s3_path=s3_path_thumbnail) + setattr(value, "path_thumbnail", s3_path_thumbnail) + + return files diff --git a/bbconf/config_parser/const.py b/bbconf/config_parser/const.py index b2d21e9e..4f2238fe 100644 --- a/bbconf/config_parser/const.py +++ b/bbconf/config_parser/const.py @@ -20,3 +20,8 @@ DEFAULT_PEPHUB_TAG = "bedbase" DEFAULT_S3_BUCKET = "bedbase" + + +S3_FILE_PATH_FOLDER = "files" +S3_PLOTS_PATH_FOLDER = "stats" +S3_BEDSET_PATH_FOLDER = "bedsets" diff --git a/bbconf/config_parser/models.py b/bbconf/config_parser/models.py index f8b16fac..dcfd1912 100644 --- a/bbconf/config_parser/models.py +++ b/bbconf/config_parser/models.py @@ -1,4 +1,4 @@ -from typing import Optional, List, Union +from typing import Optional, Union from pydantic import BaseModel, ConfigDict from bbconf.config_parser.const import ( diff --git a/bbconf/db_utils.py b/bbconf/db_utils.py index 98836552..3b145ec1 100644 --- a/bbconf/db_utils.py +++ b/bbconf/db_utils.py @@ -124,10 +124,12 @@ class Bed(Base): # relations: # plots: Mapped[List["Plots"]] = relationship("Plots", back_populates="bedfile") - files: Mapped[List["Files"]] = relationship("Files", back_populates="bedfile") + files: Mapped[List["Files"]] = relationship( + "Files", back_populates="bedfile", cascade="all, delete-orphan" + ) bedsets: Mapped[List["BedFileBedSetRelation"]] = relationship( - "BedFileBedSetRelation", back_populates="bedfile" + "BedFileBedSetRelation", back_populates="bedfile", cascade="all, delete-orphan" ) @@ -150,10 +152,10 @@ class Files(Base): size: Mapped[Optional[int]] = mapped_column(default=0, comment="Size of the file") bedfile_id: Mapped[int] = mapped_column( - ForeignKey("bed.id"), nullable=True, index=True + ForeignKey("bed.id", ondelete="CASCADE"), nullable=True, index=True ) bedset_id: Mapped[int] = mapped_column( - ForeignKey("bedsets.id"), nullable=True, index=True + ForeignKey("bedsets.id", ondelete="CASCADE"), nullable=True, index=True ) bedfile: Mapped["Bed"] = relationship("Bed", back_populates="files") @@ -182,8 +184,12 @@ class Files(Base): class BedFileBedSetRelation(Base): __tablename__ = "bedfile_bedset_relation" - bedset_id: Mapped[int] = mapped_column(ForeignKey("bedsets.id"), primary_key=True) - bedfile_id: Mapped[int] = mapped_column(ForeignKey("bed.id"), primary_key=True) + bedset_id: Mapped[int] = mapped_column( + ForeignKey("bedsets.id", ondelete="CASCADE"), primary_key=True + ) + bedfile_id: Mapped[int] = mapped_column( + ForeignKey("bed.id", ondelete="CASCADE"), primary_key=True + ) bedset: Mapped["BedSets"] = relationship("BedSets", back_populates="bedfiles") bedfile: Mapped["Bed"] = relationship("Bed", back_populates="bedsets") @@ -214,7 +220,7 @@ class BedSets(Base): ) bedfiles: Mapped[List["BedFileBedSetRelation"]] = relationship( - "BedFileBedSetRelation", back_populates="bedset" + "BedFileBedSetRelation", back_populates="bedset", cascade="all, delete-orphan" ) # plots: Mapped[List["Plots"]] = relationship("Plots", back_populates="bedset") files: Mapped[List["Files"]] = relationship("Files", back_populates="bedset") diff --git a/bbconf/helpers.py b/bbconf/helpers.py index 77a83e5e..1fa119b9 100644 --- a/bbconf/helpers.py +++ b/bbconf/helpers.py @@ -1,6 +1,6 @@ import logging -from typing import NoReturn from yacman import select_config +import os from bbconf.exceptions import BedBaseConnectionError @@ -28,3 +28,17 @@ def get_bedbase_cfg(cfg: str = None) -> str: f"{'or '.join(CFG_ENV_VARS)} environment variable" ) return selected_cfg + + +def get_absolute_path(path: str, base_path: str) -> str: + """ + Get absolute path to the file and create it if it doesn't exist + + :param path: path to the file (abs or relative) + :param base_path: base path to the file (will be added to the relative path) + + :return: absolute path to the file + """ + if not os.path.isabs(path) or not os.path.exists(path): + return os.path.join(base_path, path) + return path diff --git a/bbconf/models/bedset_models.py b/bbconf/models/bedset_models.py index 4d8078f3..0ecd1168 100644 --- a/bbconf/models/bedset_models.py +++ b/bbconf/models/bedset_models.py @@ -1,5 +1,5 @@ -from pydantic import BaseModel -from typing import List, Union +from pydantic import BaseModel, ConfigDict +from typing import List from .bed_models import BedStats, BedMetadata from .base_models import FileModel @@ -32,3 +32,9 @@ class BedSetBedFiles(BaseModel): limit: int offset: int results: List[BedMetadata] + + +class BedSetPlots(BaseModel): + test_plot: FileModel = None + + model_config = ConfigDict(extra="ignore") diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index 92218f67..d4ffd527 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -1,4 +1,3 @@ -import warnings from logging import getLogger from typing import Dict, Union import numpy as np @@ -11,7 +10,6 @@ from sqlalchemy.orm import Session from sqlalchemy import select -import os from bbconf.const import ( PKG_NAME, @@ -31,17 +29,12 @@ from bbconf.exceptions import ( BedBaseConfError, BEDFileNotFoundError, - BedbaseS3ConnectionError, ) from bbconf.db_utils import Bed, Files from bbconf.config_parser.bedbaseconfig import BedBaseConfig _LOGGER = getLogger(PKG_NAME) - -BIGBED_PATH_FOLDER = "bigbed_files" -BED_PATH_FOLDER = "bed_files" -PLOTS_PATH_FOLDER = "stats" QDRANT_GENOME = "hg38" @@ -360,13 +353,14 @@ def add( # Upload files to s3 if upload_s3: if files: - files = self.upload_files_s3(files) + files = self._config.upload_files_s3( + identifier, files=files, base_path=local_path, type="files" + ) if plots: - plots = self.upload_plots_s3( - identifier, output_path=local_path, plots=plots + plots = self._config.upload_files_s3( + identifier, files=plots, base_path=local_path, type="plots" ) - with Session(self._sa_engine) as session: new_bed = Bed( id=identifier, @@ -380,24 +374,17 @@ def add( for k, v in files: if v: new_file = Files( - name=k, - path=v.path, - description=v.description, + **v.model_dump(exclude_none=True, exclude_unset=True), bedfile_id=identifier, type="file", - size=v.size, ) session.add(new_file) for k, v in plots: if v: new_plot = Files( - name=k, - path=v.path, - path_thumbnail=v.path_thumbnail, - description=v.description, + **v.model_dump(exclude_none=True, exclude_unset=True), bedfile_id=identifier, type="plot", - size=v.size, ) session.add(new_plot) @@ -414,118 +401,6 @@ def delete(self, identifier: str) -> None: """ raise NotImplemented - def upload_files_s3(self, files: BedFiles) -> BedFiles: - """ - Upload files to s3. - - :param files: dictionary with files to upload - :return: None - """ - - if files.bed_file: - file_base_name = os.path.basename(files.bed_file.path) - - bed_file_path = files.bed_file.path - bed_s3_path = os.path.join( - BED_PATH_FOLDER, - file_base_name[0], - file_base_name[1], - os.path.basename(bed_file_path), - ) - self._upload_s3(bed_file_path, bed_s3_path) - - files.bed_file.path = bed_s3_path - files.bed_file.size = os.path.getsize(bed_file_path) - - if files.bigbed_file: - file_base_name = os.path.basename(files.bigbed_file.path) - - bigbed_file_local = files.bigbed_file.path - bigbed_s3_path = os.path.join( - BIGBED_PATH_FOLDER, - file_base_name[0], - file_base_name[1], - os.path.basename(bigbed_file_local), - ) - self._upload_s3(bigbed_file_local, bigbed_s3_path) - - files.bigbed_file.path = bigbed_s3_path - files.bigbed_file.size = os.path.getsize(bigbed_file_local) - - return files - - def upload_plots_s3( - self, identifier: str, output_path: str, plots: BedPlots - ) -> BedPlots: - """ - Upload plots to s3. - - :param identifier: bed file identifier - :param plots: dictionary with plots to upload - :param output_path: local path to the output files - :return: None - """ - _LOGGER.info(f"Uploading plots to S3...") - - plots_output = BedPlots() - output_folder = os.path.join(PLOTS_PATH_FOLDER, identifier) - - for key, value in plots: - if value: - if value.path: - file_s3_path = os.path.join( - output_folder, os.path.basename(value.path) - ) - local_path = os.path.join(output_path, value.path) - self._upload_s3(local_path, file_s3_path) - else: - file_s3_path = None - local_path = None - if value.path_thumbnail: - file_s3_path_thumbnail = os.path.join( - output_folder, os.path.basename(value.path_thumbnail) - ) - local_path_thumbnail = os.path.join( - output_path, value.path_thumbnail - ) - self._upload_s3(local_path_thumbnail, file_s3_path_thumbnail) - else: - file_s3_path_thumbnail = None - - setattr( - plots_output, - key, - FileModel( - name=value.name, - path=file_s3_path, - path_thumbnail=file_s3_path_thumbnail, - description=value.description, - size=os.path.getsize(local_path) if local_path else None, - ), - ) - - return plots_output - - def _upload_s3(self, file_path: str, s3_path: str) -> None: - """ - Upload file to s3. - - :param file_path: local path to the file - :param s3_path: path to the file in s3 with file name - :return: None - """ - try: - self._config.boto3_client.upload_file( - file_path, self._config.config.s3.bucket, s3_path - ) - except AttributeError as e: - _LOGGER.warning( - f"Could not upload file to s3. Error: {e}. Connection to s3 not established. Skipping.." - ) - raise BedbaseS3ConnectionError( - "Could not upload file to s3. Connection error." - ) - def upload_pephub(self, identifier: str, metadata: dict, overwrite: bool = False): if not metadata: _LOGGER.warning("No metadata provided. Skipping pephub upload..") @@ -553,7 +428,6 @@ def upload_file_qdrant( :param bed_id: bed file id :param bed_file: path to the bed file, or RegionSet object :param payload: additional metadata to store alongside vectors - :param region_to_vec: initiated region to vector model. If None, new object will be created. :return: None """ diff --git a/bbconf/modules/bedsets.py b/bbconf/modules/bedsets.py index f2f55555..bdc6b2cf 100644 --- a/bbconf/modules/bedsets.py +++ b/bbconf/modules/bedsets.py @@ -1,6 +1,5 @@ from typing import List import logging -from hashlib import md5 from sqlalchemy import select, func, Numeric, Float, or_ from sqlalchemy.orm import Session @@ -8,7 +7,7 @@ from bbconf.config_parser import BedBaseConfig -from bbconf.db_utils import BedFileBedSetRelation, Bed, BedSets +from bbconf.db_utils import BedFileBedSetRelation, Bed, BedSets, Files from bbconf.models.bed_models import BedStats from bbconf.models.bedset_models import ( @@ -17,6 +16,7 @@ BedSetListResult, FileModel, BedSetBedFiles, + BedSetPlots, ) from bbconf.modules.bedfiles import BedAgentBedFile from bbconf.const import PKG_NAME @@ -84,17 +84,22 @@ def create( statistics: bool = False, plots: dict = None, upload_pephub: bool = False, + upload_s3: bool = False, + local_path: str = "", no_fail: bool = False, ) -> None: """ Create bedset in the database. :param identifier: bedset identifier + :param name: bedset name :param description: bedset description :param bedid_list: list of bed file identifiers :param statistics: calculate statistics for bedset :param plots: dictionary with plots :param upload_pephub: upload bedset to pephub (create view in pephub) + :param upload_s3: upload bedset to s3 + :param local_path: local path to the output files :param no_fail: do not raise an error if bedset already exists :return: None """ @@ -122,7 +127,11 @@ def create( md5sum=compute_md5sum_bedset(bedid_list), ) - # TODO: upload plots! We don't have them now + if upload_s3: + plots = BedSetPlots(**plots) + plots = self.config.upload_files_s3( + identifier, files=plots, base_path=local_path, type="bedsets" + ) with Session(self._db_engine.engine) as session: session.add(new_bedset) @@ -131,6 +140,15 @@ def create( session.add( BedFileBedSetRelation(bedset_id=identifier, bedfile_id=bedfile) ) + if upload_s3: + for k, v in plots: + if v: + new_file = Files( + **v.model_dump(exclude_none=True, exclude_unset=True), + bedset_id=identifier, + type="plot", + ) + session.add(new_file) session.commit() From 7ec37a4124c89f05d8ba44e7048bb2a7687e9107 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Fri, 22 Mar 2024 22:03:56 +0100 Subject: [PATCH 28/61] fixed bedsets --- bbconf/models/bedset_models.py | 2 +- bbconf/modules/bedsets.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bbconf/models/bedset_models.py b/bbconf/models/bedset_models.py index 0ecd1168..fdb81c06 100644 --- a/bbconf/models/bedset_models.py +++ b/bbconf/models/bedset_models.py @@ -35,6 +35,6 @@ class BedSetBedFiles(BaseModel): class BedSetPlots(BaseModel): - test_plot: FileModel = None + region_commonality: FileModel = None model_config = ConfigDict(extra="ignore") diff --git a/bbconf/modules/bedsets.py b/bbconf/modules/bedsets.py index bdc6b2cf..a703191f 100644 --- a/bbconf/modules/bedsets.py +++ b/bbconf/modules/bedsets.py @@ -79,8 +79,8 @@ def create( self, identifier: str, name: str, + bedid_list: List[str], description: str = None, - bedid_list: List[str] = None, statistics: bool = False, plots: dict = None, upload_pephub: bool = False, From 39a0b350f8bc5fddaa9d177a28f362d071086033 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Fri, 22 Mar 2024 22:41:36 +0100 Subject: [PATCH 29/61] fixed title of the files --- bbconf/modules/bedfiles.py | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index d4ffd527..761d7407 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -80,25 +80,14 @@ def get(self, identifier: str, full: bool = False) -> BedMetadata: setattr( bed_plots, result.name, - FileModel( - name=result.name, - path=result.path, - size=result.size, - path_thumbnail=result.path_thumbnail, - description=result.description, - ), + FileModel(**result.__dict__), ) # FILES elif result.name in BedFiles.model_fields: setattr( bed_files, result.name, - FileModel( - name=result.name, - path=result.path, - size=result.size, - description=result.description, - ), + FileModel(**result.__dict__), ) else: From fc88b620c42a1e9a0f65b80d2b2ed32f66527348 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Mon, 25 Mar 2024 18:02:42 +0100 Subject: [PATCH 30/61] fixed no_fail --- bbconf/config_parser/bedbaseconfig.py | 2 + bbconf/models/bed_models.py | 6 +-- bbconf/modules/bedfiles.py | 76 +++++++++++++++++---------- 3 files changed, 53 insertions(+), 31 deletions(-) diff --git a/bbconf/config_parser/bedbaseconfig.py b/bbconf/config_parser/bedbaseconfig.py index e7ba49ed..f277e876 100644 --- a/bbconf/config_parser/bedbaseconfig.py +++ b/bbconf/config_parser/bedbaseconfig.py @@ -240,6 +240,8 @@ def upload_s3(self, file_path: str, s3_path: Union[Path, str]) -> None: raise BedbaseS3ConnectionError( "Could not upload file to s3. Connection error." ) + if not os.path.exists(file_path): + raise BedBaseConfError(f"File {file_path} does not exist.") return self._boto3_client.upload_file(file_path, self.config.s3.bucket, s3_path) def upload_files_s3( diff --git a/bbconf/models/bed_models.py b/bbconf/models/bed_models.py index 9d6c6b68..5deaab2a 100644 --- a/bbconf/models/bed_models.py +++ b/bbconf/models/bed_models.py @@ -21,8 +21,8 @@ class BedPlots(BaseModel): class BedFiles(BaseModel): - bed_file: FileModel = Field(None, alias="bedfile") - bigbed_file: FileModel = Field(None, alias="bigbedfile") + bed_file: Union[FileModel, None] = Field(None, alias="bedfile") + bigbed_file: Union[FileModel, None] = Field(None, alias="bigbedfile") model_config = ConfigDict( populate_by_name=True, @@ -33,7 +33,7 @@ class BedFiles(BaseModel): class BedClassification(BaseModel): name: str genome_alias: str = None - genome_digest: str = None + genome_digest: Union[str, None] = None bed_type: str = Field( default="bed3", pattern="^bed(?:[3-9]|1[0-5])(?:\+|$)[0-9]?+$" ) diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index 761d7407..6476a548 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -9,6 +9,7 @@ from sqlalchemy.orm import Session from sqlalchemy import select +from sqlalchemy.exc import IntegrityError, NoResultFound from bbconf.const import ( @@ -350,37 +351,56 @@ def add( plots = self._config.upload_files_s3( identifier, files=plots, base_path=local_path, type="plots" ) - with Session(self._sa_engine) as session: - new_bed = Bed( - id=identifier, - **stats.model_dump(), - **classification.model_dump(), - indexed=add_to_qdrant, - pephub=upload_pephub, - ) - session.add(new_bed) - if upload_s3: - for k, v in files: - if v: - new_file = Files( - **v.model_dump(exclude_none=True, exclude_unset=True), - bedfile_id=identifier, - type="file", - ) - session.add(new_file) - for k, v in plots: - if v: - new_plot = Files( - **v.model_dump(exclude_none=True, exclude_unset=True), - bedfile_id=identifier, - type="plot", - ) - session.add(new_plot) - - session.commit() + try: + with Session(self._sa_engine) as session: + new_bed = Bed( + id=identifier, + **stats.model_dump(), + **classification.model_dump(), + indexed=add_to_qdrant, + pephub=upload_pephub, + ) + session.add(new_bed) + if upload_s3: + for k, v in files: + if v: + new_file = Files( + **v.model_dump(exclude_none=True, exclude_unset=True), + bedfile_id=identifier, + type="file", + ) + session.add(new_file) + for k, v in plots: + if v: + new_plot = Files( + **v.model_dump(exclude_none=True, exclude_unset=True), + bedfile_id=identifier, + type="plot", + ) + session.add(new_plot) + + session.commit() + except IntegrityError: + if not nofail: + raise BEDFileNotFoundError(f"Bed file with id: {identifier} not found.") + else: + _LOGGER.warning( + f"Bed file with id: {identifier} exists in the database. record won't be updated." + ) + # TODO: add overwrite option return None + def update( + self, + identifier: str, + stats: BedStats, + classification: BedClassification, + files: BedFiles, + plots: BedPlots, + ): + raise NotImplemented + def delete(self, identifier: str) -> None: """ Delete bed file from the database. From 62eb357d26c78467bee4354766a9e80abe0fbcb5 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Mon, 25 Mar 2024 18:57:27 +0100 Subject: [PATCH 31/61] cleaning --- bbconf/bbagent.py | 6 +++--- bbconf/config_parser/bedbaseconfig.py | 4 +--- bbconf/db_utils.py | 3 --- bbconf/models/drs_models.py | 4 ++-- bbconf/modules/bedfiles.py | 13 ++++++------- bbconf/modules/bedsets.py | 2 +- bbconf/modules/objects.py | 2 +- 7 files changed, 14 insertions(+), 20 deletions(-) diff --git a/bbconf/bbagent.py b/bbconf/bbagent.py index 8c06d24b..dc9ee188 100644 --- a/bbconf/bbagent.py +++ b/bbconf/bbagent.py @@ -1,5 +1,5 @@ from pathlib import Path -from typing import Union, List +from typing import Union from sqlalchemy.orm import Session from sqlalchemy.sql import select, func, distinct @@ -35,11 +35,11 @@ def bed(self) -> BedAgentBedFile: return self.__bed @property - def bedset(self): + def bedset(self) -> BedAgentBedSet: return self.__bedset @property - def objects(self): + def objects(self) -> BBObjects: return self.__objects def get_stats(self) -> StatsReturn: diff --git a/bbconf/config_parser/bedbaseconfig.py b/bbconf/config_parser/bedbaseconfig.py index f277e876..2efe7491 100644 --- a/bbconf/config_parser/bedbaseconfig.py +++ b/bbconf/config_parser/bedbaseconfig.py @@ -167,8 +167,6 @@ def _init_t2bsi_object(self) -> Union[text2bednn.Text2BEDSearchInterface, None]: Create Text 2 BED search interface and return this object :return: Text2BEDSearchInterface object - - # TODO: should it be text 2 vec? """ try: @@ -235,7 +233,7 @@ def upload_s3(self, file_path: str, s3_path: Union[Path, str]) -> None: """ if not self._boto3_client: _LOGGER.warning( - f"Could not upload file to s3. Connection to s3 not established. Skipping.." + "Could not upload file to s3. Connection to s3 not established. Skipping.." ) raise BedbaseS3ConnectionError( "Could not upload file to s3. Connection error." diff --git a/bbconf/db_utils.py b/bbconf/db_utils.py index 3b145ec1..98730262 100644 --- a/bbconf/db_utils.py +++ b/bbconf/db_utils.py @@ -4,15 +4,12 @@ from sqlalchemy import ( BigInteger, - FetchedValue, Result, Select, - String, event, select, TIMESTAMP, ForeignKey, - UniqueConstraint, ) from sqlalchemy.dialects.postgresql import JSON from sqlalchemy.engine import URL, create_engine, Engine diff --git a/bbconf/models/drs_models.py b/bbconf/models/drs_models.py index 9c129842..2466ff2f 100644 --- a/bbconf/models/drs_models.py +++ b/bbconf/models/drs_models.py @@ -1,6 +1,6 @@ import datetime -from typing import Optional, List, Union -from pydantic import BaseModel, ConfigDict +from typing import Optional, List +from pydantic import BaseModel # DRS Models diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index 6476a548..9b090f92 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -9,7 +9,7 @@ from sqlalchemy.orm import Session from sqlalchemy import select -from sqlalchemy.exc import IntegrityError, NoResultFound +from sqlalchemy.exc import IntegrityError from bbconf.const import ( @@ -399,7 +399,7 @@ def update( files: BedFiles, plots: BedPlots, ): - raise NotImplemented + raise NotImplementedError def delete(self, identifier: str) -> None: """ @@ -408,7 +408,7 @@ def delete(self, identifier: str) -> None: :param identifier: bed file identifier :return: None """ - raise NotImplemented + raise NotImplementedError def upload_pephub(self, identifier: str, metadata: dict, overwrite: bool = False): if not metadata: @@ -537,12 +537,11 @@ def delete_qdrant_point(self, identifier: str) -> None: ) return result - def create_qdrant_collection(self) -> None: + def create_qdrant_collection(self) -> bool: """ Create qdrant collection for bed files. """ - result = self._config.qdrant_engine.qd_client.create_collection( - collection_name="test_collection", + return self._config.qdrant_engine.qd_client.create_collection( + collection_name=self._config.config.qdrant.collection, vectors_config=VectorParams(size=100, distance=Distance.DOT), ) - return None diff --git a/bbconf/modules/bedsets.py b/bbconf/modules/bedsets.py index a703191f..b0042ba4 100644 --- a/bbconf/modules/bedsets.py +++ b/bbconf/modules/bedsets.py @@ -163,7 +163,7 @@ def _calculate_statistics(self, bed_ids: List[str]) -> BedSetStats: :return: statistics """ - _LOGGER.info(f"Calculating bedset statistics") + _LOGGER.info("Calculating bedset statistics") numeric_columns = BedStats.model_fields bedset_sd = {} diff --git a/bbconf/modules/objects.py b/bbconf/modules/objects.py index 294916a1..23195364 100644 --- a/bbconf/modules/objects.py +++ b/bbconf/modules/objects.py @@ -154,7 +154,7 @@ def get_drs_metadata( record_type, record_id, result_id ) # only get result once if not record_metadata: - raise MissingObjectError(f"Record not found") + raise MissingObjectError("Record not found") for access_id in self.config.config.access_methods.model_dump().keys(): access_dict = AccessMethod( From 75cc4ba391faf0a976f2af51220b83a0ff3fc137 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Tue, 26 Mar 2024 02:07:15 +0100 Subject: [PATCH 32/61] added delete function to bedfiles --- bbconf/config_parser/bedbaseconfig.py | 34 +++++- bbconf/exceptions.py | 6 ++ bbconf/modules/bedfiles.py | 149 +++++++++++++++++++------- requirements/requirements-all.txt | 10 +- tests/test_bbagent.py | 6 +- 5 files changed, 158 insertions(+), 47 deletions(-) diff --git a/bbconf/config_parser/bedbaseconfig.py b/bbconf/config_parser/bedbaseconfig.py index 2efe7491..0729ae75 100644 --- a/bbconf/config_parser/bedbaseconfig.py +++ b/bbconf/config_parser/bedbaseconfig.py @@ -1,5 +1,5 @@ from pathlib import Path -from typing import Union +from typing import Union, List import yacman import logging from geniml.search import QdrantBackend @@ -20,6 +20,7 @@ ) from bbconf.models.bed_models import BedFiles, BedPlots from bbconf.models.bedset_models import BedSetPlots +from bbconf.models.base_models import FileModel from bbconf.helpers import get_bedbase_cfg, get_absolute_path from bbconf.config_parser.models import ConfigFile from bbconf.config_parser.const import ( @@ -299,3 +300,34 @@ def upload_files_s3( setattr(value, "path_thumbnail", s3_path_thumbnail) return files + + def delete_s3(self, s3_path: str) -> None: + """ + Delete file from s3. + + :param s3_path: path to the file in s3 + :return: None + """ + if not self._boto3_client: + _LOGGER.warning( + "Could not delete file from s3. Connection to s3 not established. Skipping.." + ) + raise BedbaseS3ConnectionError( + "Could not delete file from s3. Connection error." + ) + return self._boto3_client.delete_object( + Bucket=self.config.s3.bucket, Key=s3_path + ) + + def delete_files_s3(self, files: List[FileModel]) -> None: + """ + Delete files from s3. + + :param files: list of file objects + :return: None + """ + for file in files: + self.delete_s3(file.path) + if file.path_thumbnail: + self.delete_s3(file.path_thumbnail) + return None diff --git a/bbconf/exceptions.py b/bbconf/exceptions.py index 15529d2c..6d891d7f 100644 --- a/bbconf/exceptions.py +++ b/bbconf/exceptions.py @@ -31,6 +31,12 @@ class MissingThumbnailError(BedBaseConfError): pass +class BedFIleExistsError(BedBaseConfError): + """Error where files exists, and should not be overwritten""" + + pass + + class MissingObjectError(BedBaseConfError): """Error type for missing object""" diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index 9b090f92..24fb6537 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -4,6 +4,7 @@ from geniml.io import RegionSet from geniml.bbclient import BBClient +from pephubclient.exceptions import ResponseError from qdrant_client.models import PointIdsList, VectorParams, Distance @@ -30,6 +31,7 @@ from bbconf.exceptions import ( BedBaseConfError, BEDFileNotFoundError, + BedFIleExistsError, ) from bbconf.db_utils import Bed, Files from bbconf.config_parser.bedbaseconfig import BedBaseConfig @@ -308,11 +310,23 @@ def add( :param upload_s3: upload files to s3 :param local_path: local path to the output files :param overwrite: overwrite bed file if it already exists - :param nofail: do not raise an error if sample not found + :param nofail: do not raise an error for error in pephub/s3/qdrant or record exsist and not overwrite :return: None """ _LOGGER.info(f"Adding bed file to database. bed_id: {identifier}") + if self.exists(identifier): + _LOGGER.warning(f"Bed file with id: {identifier} exists in the database.") + if not overwrite: + if not nofail: + raise BedFIleExistsError( + f"Bed file with id: {identifier} already exists in the database." + ) + _LOGGER.warning("Overwrite set to False. Skipping..") + return None + else: + self.delete(identifier) + stats = BedStats(**stats) # TODO: we should not check for specific keys, of the plots! plots = BedPlots(**plots) @@ -351,43 +365,35 @@ def add( plots = self._config.upload_files_s3( identifier, files=plots, base_path=local_path, type="plots" ) - try: - with Session(self._sa_engine) as session: - new_bed = Bed( - id=identifier, - **stats.model_dump(), - **classification.model_dump(), - indexed=add_to_qdrant, - pephub=upload_pephub, - ) - session.add(new_bed) - if upload_s3: - for k, v in files: - if v: - new_file = Files( - **v.model_dump(exclude_none=True, exclude_unset=True), - bedfile_id=identifier, - type="file", - ) - session.add(new_file) - for k, v in plots: - if v: - new_plot = Files( - **v.model_dump(exclude_none=True, exclude_unset=True), - bedfile_id=identifier, - type="plot", - ) - session.add(new_plot) - - session.commit() - except IntegrityError: - if not nofail: - raise BEDFileNotFoundError(f"Bed file with id: {identifier} not found.") - else: - _LOGGER.warning( - f"Bed file with id: {identifier} exists in the database. record won't be updated." - ) - # TODO: add overwrite option + + with Session(self._sa_engine) as session: + new_bed = Bed( + id=identifier, + **stats.model_dump(), + **classification.model_dump(), + indexed=add_to_qdrant, + pephub=upload_pephub, + ) + session.add(new_bed) + if upload_s3: + for k, v in files: + if v: + new_file = Files( + **v.model_dump(exclude_none=True, exclude_unset=True), + bedfile_id=identifier, + type="file", + ) + session.add(new_file) + for k, v in plots: + if v: + new_plot = Files( + **v.model_dump(exclude_none=True, exclude_unset=True), + bedfile_id=identifier, + type="plot", + ) + session.add(new_plot) + + session.commit() return None @@ -399,6 +405,21 @@ def update( files: BedFiles, plots: BedPlots, ): + """ + Update bed file in the database. + + :param identifier: bed file identifier + :param stats: bed file statistics + :param classification: bed file classification + :param files: bed file files + :param plots: bed file plots + + """ + if not self.exists(identifier): + raise BEDFileNotFoundError( + f"Bed file with id: {identifier} not found. Cannot update." + ) + raise NotImplementedError def delete(self, identifier: str) -> None: @@ -408,7 +429,26 @@ def delete(self, identifier: str) -> None: :param identifier: bed file identifier :return: None """ - raise NotImplementedError + _LOGGER.info(f"Deleting bed file from database. bed_id: {identifier}") + if not self.exists(identifier): + raise BEDFileNotFoundError(f"Bed file with id: {identifier} not found.") + + with Session(self._sa_engine) as session: + statement = select(Bed).where(Bed.id == identifier) + bed_object = session.scalar(statement) + + files = [FileModel(**k.__dict__) for k in bed_object.files] + delete_pephub = bed_object.pephub + delete_qdrant = bed_object.indexed + + session.delete(bed_object) + session.commit() + + if delete_pephub: + self.delete_pephub_sample(identifier) + if delete_qdrant: + self.delete_qdrant_point(identifier) + self._config.delete_files_s3(files) def upload_pephub(self, identifier: str, metadata: dict, overwrite: bool = False): if not metadata: @@ -423,6 +463,22 @@ def upload_pephub(self, identifier: str, metadata: dict, overwrite: bool = False overwrite=overwrite, ) + def delete_pephub_sample(self, identifier: str): + """ + Delete sample from pephub + + :param identifier: bed file identifier + """ + try: + self._config.phc.sample.remove( + namespace=self._config.config.phc.namespace, + name=self._config.config.phc.name, + tag=self._config.config.phc.tag, + sample_name=identifier, + ) + except ResponseError as e: + _LOGGER.warning(f"Could not delete from pephub. Error: {e}") + def upload_file_qdrant( self, bed_id: str, @@ -545,3 +601,18 @@ def create_qdrant_collection(self) -> bool: collection_name=self._config.config.qdrant.collection, vectors_config=VectorParams(size=100, distance=Distance.DOT), ) + + def exists(self, identifier: str) -> bool: + """ + Check if bed file exists in the database. + + :param identifier: bed file identifier + :return: True if bed file exists, False otherwise + """ + statement = select(Bed).where(Bed.id == identifier) + + with Session(self._sa_engine) as session: + bed_object = session.scalar(statement) + if not bed_object: + return False + return True diff --git a/requirements/requirements-all.txt b/requirements/requirements-all.txt index d261e982..ce0474b4 100644 --- a/requirements/requirements-all.txt +++ b/requirements/requirements-all.txt @@ -1,8 +1,8 @@ -yacman>=0.9.1 -sqlalchemy>=2.0.0 -geniml>=0.2.0 -psycopg>=3.1.15 +yacman >= 0.9.1 +sqlalchemy >= 2.0.0 +geniml >= 0.2.0 +psycopg >= 3.1.15 colorlogs -pydantic>=2.6.4 +pydantic >= 2.6.4 botocore >= 1.34.54 boto3 >= 1.34.54 \ No newline at end of file diff --git a/tests/test_bbagent.py b/tests/test_bbagent.py index f8356896..fc72ca9c 100644 --- a/tests/test_bbagent.py +++ b/tests/test_bbagent.py @@ -83,8 +83,10 @@ def test_delete_qdrant_point(self): assert True def test_bed_delete(self): - # agent = BedBaseAgent(config=config) - # ff = agent.bed.delete("91b2754c8ff01769bacfc80e6923c46e") + agent = BedBaseAgent( + config="/home/bnt4me/virginia/repos/bbuploader/config_db_local.yaml" + ) + ff = agent.bed.delete("ec8179a55ab7e649e15762d0e8cb5378") # print(ff) # assert ff != None pass From 20a71225fc2f0cd260aac8825ad3534b36d3da8e Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Tue, 26 Mar 2024 15:21:44 +0100 Subject: [PATCH 33/61] added updating of bedfiles in the db --- bbconf/modules/bedfiles.py | 110 ++++++++++++++++++++++++++++++++++--- 1 file changed, 101 insertions(+), 9 deletions(-) diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index 24fb6537..73e0d863 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -400,26 +400,106 @@ def add( def update( self, identifier: str, - stats: BedStats, - classification: BedClassification, - files: BedFiles, - plots: BedPlots, + stats: dict, + metadata: dict = None, + plots: dict = None, + files: dict = None, + classification: dict = None, + add_to_qdrant: bool = False, + upload_pephub: bool = False, + upload_s3: bool = False, + local_path: str = None, + overwrite: bool = False, + nofail: bool = False, ): """ - Update bed file in the database. + Update bed file to the database. :param identifier: bed file identifier - :param stats: bed file statistics - :param classification: bed file classification - :param files: bed file files + :param stats: bed file results {statistics, plots, files, metadata} + :param metadata: bed file metadata (will be saved in pephub) :param plots: bed file plots - + :param files: bed file files + :param classification: bed file classification + :param add_to_qdrant: add bed file to qdrant indexs + :param upload_pephub: add bed file to pephub + :param upload_s3: upload files to s3 + :param local_path: local path to the output files + :param overwrite: overwrite bed file if it already exists + :return: None """ if not self.exists(identifier): raise BEDFileNotFoundError( f"Bed file with id: {identifier} not found. Cannot update." ) + stats = BedStats(**stats) + plots = BedPlots(**plots) + files = BedFiles(**files) + classification = BedClassification(**classification) + + if upload_pephub: + metadata = BedPEPHub(**metadata) + try: + self.update_pephub(identifier, metadata.model_dump(), overwrite) + except Exception as e: + _LOGGER.warning( + f"Could not upload to pephub. Error: {e}. nofail: {nofail}" + ) + if not nofail: + raise e + else: + _LOGGER.info("upload_pephub set to false. Skipping pephub..") + + if add_to_qdrant: + self.upload_file_qdrant( + identifier, files.bed_file.path, {"bed_id": identifier} + ) + + statement = select(Bed).where(Bed.id == identifier) + + if upload_s3: + _LOGGER.warning("S3 upload is not implemented yet") + # if files: + # files = self._config.upload_files_s3( + # identifier, files=files, base_path=local_path, type="files" + # ) + # + # if plots: + # plots = self._config.upload_files_s3( + # identifier, files=plots, base_path=local_path, type="plots" + # ) + + with Session(self._sa_engine) as session: + bed_object = session.scalar(statement) + + setattr(bed_object, **stats.model_dump()) + setattr(bed_object, **classification.model_dump()) + + bed_object.indexed = add_to_qdrant + bed_object.pephub = upload_pephub + + if upload_s3: + _LOGGER.warning("S3 upload is not implemented yet") + # for k, v in files: + # if v: + # new_file = Files( + # **v.model_dump(exclude_none=True, exclude_unset=True), + # bedfile_id=identifier, + # type="file", + # ) + # session.add(new_file) + # for k, v in plots: + # if v: + # new_plot = Files( + # **v.model_dump(exclude_none=True, exclude_unset=True), + # bedfile_id=identifier, + # type="plot", + # ) + # session.add(new_plot) + + session.commit() + raise NotImplementedError def delete(self, identifier: str) -> None: @@ -463,6 +543,18 @@ def upload_pephub(self, identifier: str, metadata: dict, overwrite: bool = False overwrite=overwrite, ) + def update_pephub(self, identifier: str, metadata: dict): + if not metadata: + _LOGGER.warning("No metadata provided. Skipping pephub upload..") + return False + self._config.phc.sample.update( + namespace=self._config.config.phc.namespace, + name=self._config.config.phc.name, + tag=self._config.config.phc.tag, + sample_name=identifier, + sample_dict=metadata, + ) + def delete_pephub_sample(self, identifier: str): """ Delete sample from pephub From a2ccde5878feb69e6ed20da0021dfd030d71b122 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Tue, 26 Mar 2024 15:45:06 +0100 Subject: [PATCH 34/61] added filters to list ids and updated return models --- bbconf/models/bed_models.py | 17 ++++++++--------- bbconf/modules/bedfiles.py | 20 ++++++++++++++++++-- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/bbconf/models/bed_models.py b/bbconf/models/bed_models.py index 5deaab2a..ab41a6be 100644 --- a/bbconf/models/bed_models.py +++ b/bbconf/models/bed_models.py @@ -31,7 +31,6 @@ class BedFiles(BaseModel): class BedClassification(BaseModel): - name: str genome_alias: str = None genome_digest: Union[str, None] = None bed_type: str = Field( @@ -97,7 +96,7 @@ class BedPEPHub(BaseModel): model_config = ConfigDict(extra="allow", populate_by_name=True) -class BedMetadata(BaseModel): +class BedMetadata(BedClassification): id: str name: str description: Optional[str] = None @@ -109,13 +108,13 @@ class BedMetadata(BaseModel): files: Union[BedFiles, None] = None raw_metadata: Optional[Union[BedPEPHub, None]] = None - genome_alias: str = None - genome_digest: str = None - bed_type: str = Field( - default="bed3", pattern="^bed(?:[3-9]|1[0-5])(?:\+|$)[0-9]?+$" - ) - bed_format: str = None - full_response: bool = False + # genome_alias: str = None + # genome_digest: str = None + # bed_type: str = Field( + # default="bed3", pattern="^bed(?:[3-9]|1[0-5])(?:\+|$)[0-9]?+$" + # ) + # bed_format: str = None + # full_response: bool = False class BedListResult(BaseModel): diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index 73e0d863..b4a6a206 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -256,20 +256,36 @@ def get_objects(self, identifier: str) -> Dict[str, FileModel]: return return_dict def get_ids_list( - self, limit: int = 100, offset: int = 0, full: bool = False + self, + limit: int = 100, + offset: int = 0, + genome: str = None, + bed_type: str = None, + full: bool = False, ) -> BedListResult: """ Get list of bed file identifiers. :param limit: number of results to return :param offset: offset to start from + :param genome: filter by genome + :param bed_type: filter by bed type. e.g. 'bed6+4' :param full: if True, return full metadata, including statistics, files, and raw metadata from pephub :return: list of bed file identifiers """ # TODO: add filter (e.g. bed_type, genome...), search by description # TODO: question: Return Annotation? - statement = select(Bed.id).limit(limit).offset(offset) + statement = select(Bed.id) + + # TODO: make it generic, like in pephub + if genome: + statement = statement.where(Bed.genome_alias == genome) + + if bed_type: + statement = statement.where(Bed.bed_format == bed_format) + + statement = statement.limit(limit).offset(offset) with Session(self._sa_engine) as session: bed_ids = session.execute(statement).all() From efc0373b89bc09b66b77a075055377010f479eb3 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Tue, 26 Mar 2024 16:57:09 +0100 Subject: [PATCH 35/61] fixed models --- bbconf/config_parser/const.py | 4 ++-- bbconf/models/bed_models.py | 3 ++- bbconf/modules/bedfiles.py | 11 ++++++----- tests/test_bbagent.py | 8 ++++++++ 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/bbconf/config_parser/const.py b/bbconf/config_parser/const.py index 4f2238fe..5dee2c44 100644 --- a/bbconf/config_parser/const.py +++ b/bbconf/config_parser/const.py @@ -16,8 +16,8 @@ DEFAULT_REGION2_VEC_MODEL = "databio/r2v-ChIP-atlas-hg38" DEFAULT_PEPHUB_NAMESPACE = "databio" -DEFAULT_PEPHUB_NAME = "allbeds" -DEFAULT_PEPHUB_TAG = "bedbase" +DEFAULT_PEPHUB_NAME = "bedbase_all" +DEFAULT_PEPHUB_TAG = "default" DEFAULT_S3_BUCKET = "bedbase" diff --git a/bbconf/models/bed_models.py b/bbconf/models/bed_models.py index ab41a6be..bf0241bf 100644 --- a/bbconf/models/bed_models.py +++ b/bbconf/models/bed_models.py @@ -31,6 +31,7 @@ class BedFiles(BaseModel): class BedClassification(BaseModel): + name: Optional[str] = None genome_alias: str = None genome_digest: Union[str, None] = None bed_type: str = Field( @@ -98,7 +99,7 @@ class BedPEPHub(BaseModel): class BedMetadata(BedClassification): id: str - name: str + name: Optional[Union[str, None]] = "" description: Optional[str] = None submission_date: datetime.datetime = None last_update_date: Optional[datetime.datetime] = None diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index b4a6a206..421cbf33 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -305,7 +305,7 @@ def add( plots: dict = None, files: dict = None, classification: dict = None, - add_to_qdrant: bool = False, + upload_qdrant: bool = False, upload_pephub: bool = False, upload_s3: bool = False, local_path: str = None, @@ -321,7 +321,7 @@ def add( :param plots: bed file plots :param files: bed file files :param classification: bed file classification - :param add_to_qdrant: add bed file to qdrant indexs + :param upload_qdrant: add bed file to qdrant indexs :param upload_pephub: add bed file to pephub :param upload_s3: upload files to s3 :param local_path: local path to the output files @@ -363,12 +363,13 @@ def add( else: _LOGGER.info("upload_pephub set to false. Skipping pephub..") - if add_to_qdrant: + if upload_qdrant: self.upload_file_qdrant( identifier, files.bed_file.path, {"bed_id": identifier} ) + _LOGGER.info(f"File uploaded to qdrant. {identifier}") else: - _LOGGER.info("add_to_qdrant set to false. Skipping qdrant..") + _LOGGER.info("upload_qdrant set to false. Skipping qdrant..") # Upload files to s3 if upload_s3: @@ -387,7 +388,7 @@ def add( id=identifier, **stats.model_dump(), **classification.model_dump(), - indexed=add_to_qdrant, + indexed=upload_qdrant, pephub=upload_pephub, ) session.add(new_bed) diff --git a/tests/test_bbagent.py b/tests/test_bbagent.py index fc72ca9c..f7700c18 100644 --- a/tests/test_bbagent.py +++ b/tests/test_bbagent.py @@ -98,6 +98,14 @@ def test_bed_update(self): # assert ff != None pass + def test_create_qdrant_collection(self): + agent = BedBaseAgent( + config="/home/bnt4me/virginia/repos/bbuploader/config_db_local.yaml" + ) + ff = agent.bed.create_qdrant_collection() + ff + assert True + def test_get_stats(): agent = BedBaseAgent(config=config) From 71b824fc259752052d69025d67e2d6a42f8a79eb Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Wed, 27 Mar 2024 22:29:54 +0100 Subject: [PATCH 36/61] added context manager to tests --- bbconf/db_utils.py | 12 +++++ bbconf/modules/bedfiles.py | 4 +- tests/config_test.yaml | 3 -- tests/conftest.py | 10 +++- tests/test_bbagent.py | 41 +++++++++++++---- tests/utils.py | 94 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 149 insertions(+), 15 deletions(-) create mode 100644 tests/utils.py diff --git a/bbconf/db_utils.py b/bbconf/db_utils.py index 98730262..2f9f14c1 100644 --- a/bbconf/db_utils.py +++ b/bbconf/db_utils.py @@ -279,6 +279,18 @@ def create_schema(self, engine=None): Base.metadata.create_all(engine) return None + def delete_schema(self, engine=None) -> None: + """ + Delete sql schema in the database. + + :param engine: sqlalchemy engine [Default: None] + :return: None + """ + if not engine: + engine = self._engine + Base.metadata.drop_all(engine) + return None + def session_execute(self, statement: Select) -> Result: """ Execute statement using sqlalchemy statement diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index 421cbf33..7908edb6 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -283,7 +283,7 @@ def get_ids_list( statement = statement.where(Bed.genome_alias == genome) if bed_type: - statement = statement.where(Bed.bed_format == bed_format) + statement = statement.where(Bed.bed_format == bed_type) statement = statement.limit(limit).offset(offset) @@ -349,7 +349,6 @@ def add( files = BedFiles(**files) classification = BedClassification(**classification) - if upload_pephub: metadata = BedPEPHub(**metadata) try: @@ -443,6 +442,7 @@ def update( :param upload_s3: upload files to s3 :param local_path: local path to the output files :param overwrite: overwrite bed file if it already exists + :param nofail: do not raise an error for error in pephub/s3/qdrant or record exsist and not overwrite :return: None """ if not self.exists(identifier): diff --git a/tests/config_test.yaml b/tests/config_test.yaml index 8ee5c8b9..ea84400d 100644 --- a/tests/config_test.yaml +++ b/tests/config_test.yaml @@ -15,9 +15,6 @@ qdrant: port: 6333 collection: "bedbase" s3: - endpoint_url: test - aws_access_key_id: test - aws_secret_access_key: test bucket: bedbase phc: namespace: bedbase diff --git a/tests/conftest.py b/tests/conftest.py index 912621d2..7f7cf13b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,6 +1,7 @@ import os import pytest from bbconf.bbagent import BedBaseAgent +from bbconf.db_utils import Bed TESTS_DIR = os.path.dirname(os.path.abspath(__file__)) @@ -74,10 +75,15 @@ def example_dict(): plots=plots, files=files, classification=classification, - add_to_qdrant=False, + upload_qdrant=False, upload_pephub=False, upload_s3=True, local_path=DATA_PATH, overwrite=False, - nofail=True, + nofail=False, ) + + +@pytest.fixture +def load_test_data(): + db_engine = get_bbagent().config.db_engine() diff --git a/tests/test_bbagent.py b/tests/test_bbagent.py index f7700c18..ee8c37e5 100644 --- a/tests/test_bbagent.py +++ b/tests/test_bbagent.py @@ -1,11 +1,11 @@ -import warnings from bbconf.bbagent import BedBaseAgent -import os - -from sqlalchemy.exc import OperationalError -from .conftest import get_bbagent +from bbconf.exceptions import BedFIleExistsError from unittest.mock import Mock +import pytest + +from .utils import ContextManagerDBTesting +from .conftest import get_bbagent def test_bb_database(): @@ -17,11 +17,36 @@ class Test_BedFile_Agent: def test_upload(self, bbagent_obj, example_dict, mocker): upload_s3_mock = mocker.patch( - "bbconf.modules.bedfiles.BedAgentBedFile._upload_s3", + "bbconf.config_parser.bedbaseconfig.BedBaseConfig.upload_s3", + return_value=True, + ) + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=False): + bbagent_obj.bed.add(**example_dict) + + assert upload_s3_mock.called + assert bbagent_obj.bed.exists(example_dict["identifier"]) + + def test_upload_exists(self, bbagent_obj, example_dict, mocker): + upload_s3_mock = mocker.patch( + "bbconf.config_parser.bedbaseconfig.BedBaseConfig.upload_s3", return_value=True, ) - bbagent_obj.bed.get_ids_list() - bbagent_obj.bed.add(**example_dict) + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=False): + bbagent_obj.bed.add(**example_dict) + with pytest.raises(BedFIleExistsError): + bbagent_obj.bed.add(**example_dict) + + def test_add_nofail(self, bbagent_obj, example_dict, mocker): + upload_s3_mock = mocker.patch( + "bbconf.config_parser.bedbaseconfig.BedBaseConfig.upload_s3", + return_value=True, + ) + + example_dict["nofail"] = True + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=False): + bbagent_obj.bed.add(**example_dict) + bbagent_obj.bed.add(**example_dict) + assert bbagent_obj.bed.exists(example_dict["identifier"]) def test_get_all(self): agent = BedBaseAgent(config=config) diff --git a/tests/utils.py b/tests/utils.py new file mode 100644 index 00000000..11281d4e --- /dev/null +++ b/tests/utils.py @@ -0,0 +1,94 @@ +from bbconf.config_parser.bedbaseconfig import BedBaseConfig +from bbconf.db_utils import Bed, Files +from typing import Union + +from sqlalchemy.orm import Session + + +def get_example_dict() -> dict: + value = { + "id": "test_id", + "number_of_regions": 1, + "median_tss_dist": 2, + "mean_region_width": 3, + "exon_frequency": 4, + "exon_percentage": 5, + "intron_frequency": 6, + "intron_percentage": 7, + "intergenic_percentage": 8, + "intergenic_frequency": 9, + "promotercore_frequency": 10, + "promotercore_percentage": 11, + "fiveutr_frequency": 12, + "fiveutr_percentage": 13, + "threeutr_frequency": 14, + "threeutr_percentage": 15, + "promoterprox_frequency": 16, + "promoterprox_percentage": 17, + "bed_format": "narrowpeak", + "bed_type": "bed6+4", + "genome_alias": "hg38", + "genome_digest": "2230c535660fb4774114bfa966a62f823fdb6d21acf138d4", + "name": "random_name", + } + return value + + +def get_files() -> dict: + return { + "title": "Bed file", + "name": "bed_file", + "path": "data/files/bbad85f21962bb8d972444f7f9a3a932.bed.gz", + "description": "Bed file with regions", + } + + +def get_plots() -> dict: + return { + "name": "chrombins", + "description": "Regions distribution over chromosomes", + "title": "Regions distribution over chromosomes", + "path": "data/plots/bbad85f21962bb8d972444f7f9a3a932_chrombins.pdf", + "path_thumbnail": "data/plots/bbad85f21962bb8d972444f7f9a3a932_chrombins.png", + } + + +class ContextManagerDBTesting: + """ + Creates context manager to connect to database at db_url adds data and drop everything from the database upon exit to ensure + the db is empty for each new test. + """ + + def __init__(self, config: Union[str, BedBaseConfig], add_data: bool = False): + """ + :param config_path: path to the config file + :param add_data: add data to the database + """ + if isinstance(config, BedBaseConfig): + self.config = config + else: + self.config = BedBaseConfig(config) + + self.add_data = add_data + + def __enter__(self): + + self.db_engine = self.config.db_engine + + if self.add_data: + self._add_data() + + def __exit__(self, exc_type, exc_value, exc_traceback): + self.db_engine.delete_schema() + + def _add_data(self): + with Session(self.db_engine.engine) as session: + + new_bed = Bed(**get_example_dict()) + new_files = Files(**get_files()) + new_plots = Files(**get_plots()) + + session.add(new_bed) + session.add(new_files) + session.add(new_plots) + session.commit() From 991295230b61427a2bbdd3dcb9e2981c20a411d1 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Thu, 28 Mar 2024 19:34:33 +0100 Subject: [PATCH 37/61] tests tests tests --- bbconf/models/bedset_models.py | 16 ++- bbconf/models/drs_models.py | 4 +- bbconf/modules/bedfiles.py | 13 +- bbconf/modules/bedsets.py | 167 +++++++++++++++-------- bbconf/modules/objects.py | 3 +- tests/conftest.py | 12 +- tests/test_bbagent.py | 209 ----------------------------- tests/test_bedfile.py | 236 +++++++++++++++++++++++++++++++++ tests/test_bedset.py | 68 ++++++++++ tests/test_objects.py | 44 ++++++ tests/utils.py | 18 ++- 11 files changed, 506 insertions(+), 284 deletions(-) delete mode 100644 tests/test_bbagent.py create mode 100644 tests/test_bedfile.py create mode 100644 tests/test_bedset.py create mode 100644 tests/test_objects.py diff --git a/bbconf/models/bedset_models.py b/bbconf/models/bedset_models.py index fdb81c06..e6a139b6 100644 --- a/bbconf/models/bedset_models.py +++ b/bbconf/models/bedset_models.py @@ -1,5 +1,5 @@ from pydantic import BaseModel, ConfigDict -from typing import List +from typing import List, Union from .bed_models import BedStats, BedMetadata from .base_models import FileModel @@ -10,12 +10,18 @@ class BedSetStats(BaseModel): sd: BedStats = None +class BedSetPlots(BaseModel): + region_commonality: FileModel = None + + model_config = ConfigDict(extra="ignore") + + class BedSetMetadata(BaseModel): id: str name: str md5sum: str - statistics: BedSetStats = None - plots: List[FileModel] = None + statistics: Union[BedSetStats, None] = None + plots: Union[BedSetPlots, None] = None description: str = None bed_ids: List[str] = None @@ -34,7 +40,3 @@ class BedSetBedFiles(BaseModel): results: List[BedMetadata] -class BedSetPlots(BaseModel): - region_commonality: FileModel = None - - model_config = ConfigDict(extra="ignore") diff --git a/bbconf/models/drs_models.py b/bbconf/models/drs_models.py index 2466ff2f..ea85c1cd 100644 --- a/bbconf/models/drs_models.py +++ b/bbconf/models/drs_models.py @@ -1,5 +1,5 @@ import datetime -from typing import Optional, List +from typing import Optional, List, Union from pydantic import BaseModel @@ -20,7 +20,7 @@ class DRSModel(BaseModel): id: str name: Optional[str] = None self_uri: str - size: int + size: Union[int, None] = None created_time: Optional[datetime.datetime] = None updated_time: Optional[datetime.datetime] = None checksums: str diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index 7908edb6..c46b1ffb 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -93,10 +93,10 @@ def get(self, identifier: str, full: bool = False) -> BedMetadata: FileModel(**result.__dict__), ) - else: - _LOGGER.error( - f"Unknown file type: {result.name}. And is not in the model fields. Skipping.." - ) + else: + _LOGGER.error( + f"Unknown file type: {result.name}. And is not in the model fields. Skipping.." + ) bed_stats = BedStats(**bed_object.__dict__) else: bed_plots = None @@ -274,7 +274,6 @@ def get_ids_list( :return: list of bed file identifiers """ - # TODO: add filter (e.g. bed_type, genome...), search by description # TODO: question: Return Annotation? statement = select(Bed.id) @@ -283,7 +282,7 @@ def get_ids_list( statement = statement.where(Bed.genome_alias == genome) if bed_type: - statement = statement.where(Bed.bed_format == bed_type) + statement = statement.where(Bed.bed_type == bed_type) statement = statement.limit(limit).offset(offset) @@ -560,7 +559,7 @@ def upload_pephub(self, identifier: str, metadata: dict, overwrite: bool = False overwrite=overwrite, ) - def update_pephub(self, identifier: str, metadata: dict): + def update_pephub(self, identifier: str, metadata: dict, overwrite: bool = False): if not metadata: _LOGGER.warning("No metadata provided. Skipping pephub upload..") return False diff --git a/bbconf/modules/bedsets.py b/bbconf/modules/bedsets.py index b0042ba4..3cccd380 100644 --- a/bbconf/modules/bedsets.py +++ b/bbconf/modules/bedsets.py @@ -40,11 +40,12 @@ def __init__(self, config: BedBaseConfig): self.config = config self._db_engine = self.config.db_engine - def get(self, identifier: str) -> BedSetMetadata: + def get(self, identifier: str, full: bool = False) -> BedSetMetadata: """ Get file metadata by identifier. :param identifier: bed file identifier + :param full: return full record with stats, plots, files and metadata :return: project metadata """ @@ -59,22 +60,47 @@ def get(self, identifier: str) -> BedSetMetadata: list_of_bedfiles = [ bedset_obj.bedfile_id for bedset_obj in bedset_obj.bedfiles ] + if full: + plots = BedSetPlots() + for plot in bedset_obj.files: + setattr(plots, plot.name, FileModel(**plot.__dict__)) + + stats = BedSetStats( + mean=BedStats(**bedset_obj.bedset_means), + sd=BedStats(**bedset_obj.bedset_standard_deviation), + ).model_dump() + else: + plots = None + stats = None bedset_metadata = BedSetMetadata( id=bedset_obj.id, name=bedset_obj.name, description=bedset_obj.description, md5sum=bedset_obj.md5sum, - statistics=BedSetStats( - mean=BedStats(**bedset_obj.bedset_means), - sd=BedStats(**bedset_obj.bedset_standard_deviation), - ).model_dump(), - plots=[FileModel(**plot.__dict__) for plot in bedset_obj.files], + statistics=stats, + plots=plots, bed_ids=list_of_bedfiles, ) return bedset_metadata + def get_plots(self, identifier: str) -> BedSetPlots: + """ + Get plots for bedset by identifier. + + :param identifier: bedset identifier + :return: bedset plots + """ + statement = select(Files).where(Files.bedset_id == identifier) + + with Session(self._db_engine.engine) as session: + plots = session.execute(statement).all() + + return BedSetPlots( + **{plot[0].name: FileModel(**plot[0].model_dump()) for plot in plots} + ) + def create( self, identifier: str, @@ -213,37 +239,50 @@ def _create_pephub_view( """ _LOGGER.info(f"Creating view in pephub for bedset '{bedset_id}'") - self.config.phc.view.create( - namespace=self.config.config.phc.namespace, - name=self.config.config.phc.name, - tag=self.config.config.phc.tag, - view_name=bedset_id, - # description=description, - sample_list=bed_ids, - ) + try: + self.config.phc.view.create( + namespace=self.config.config.phc.namespace, + name=self.config.config.phc.name, + tag=self.config.config.phc.tag, + view_name=bedset_id, + # description=description, + sample_list=bed_ids, + ) + except Exception as e: + _LOGGER.error(f"Failed to create view in pephub: {e}") + if not nofail: + raise e return None - def get_ids_list(self, limit: int = 10, offset: int = 0) -> BedSetListResult: + def get_ids_list(self, query: str = None, limit: int = 10, offset: int = 0) -> BedSetListResult: """ Get list of bedsets from the database. + :param query: search query :param limit: limit of results :param offset: offset of results :return: list of bedsets """ - # TODO: add search and some metadata here - statement = select(BedSets).limit(limit).offset(offset) - + statement = select(BedSets.id) + if query: + sql_search_str = f"%{query}%" + statement = statement.where( + or_( + BedSets.name.ilike(sql_search_str), + BedSets.description.ilike(sql_search_str), + ) + ) with Session(self._db_engine.engine) as session: - bedset_list = session.execute(statement).all() - - results = [self.get(bedset[0].id) for bedset in bedset_list] + bedset_list = session.execute(statement.limit(limit).offset(offset)) + result_list = [] + for bedset_id in bedset_list: + result_list.append(self.get(bedset_id[0])) return BedSetListResult( - count=len(results), + count=len(result_list), limit=limit, offset=offset, - results=results, + results=result_list, ) def get_bedset_bedfiles( @@ -284,48 +323,70 @@ def get_bedset_bedfiles( results=results, ) - def search(self, query: str, limit: int = 10, offset: int = 0) -> BedSetListResult: + def delete(self, identifier: str) -> None: """ - Search bedsets in the database. + Delete bed file from the database. - :param query: search query - :param limit: limit of results - :param offset: offset of results - :return: list of bedsets + :param identifier: bedset identifier + :return: None """ - statement = select(BedSets.id) - if query: - sql_search_str = f"%{query}%" - statement = statement.where( - or_( - BedSets.name.ilike(sql_search_str), - BedSets.description.ilike(sql_search_str), - ) - ) + if not self.exists(identifier): + raise BedSetNotFoundError(identifier) + + _LOGGER.info(f"Deleting bedset '{identifier}'") + with Session(self._db_engine.engine) as session: - bedset_list = session.execute(statement.limit(limit).offset(offset)) + statement = select(BedSets).where(BedSets.id == identifier) - result_list = [] - for bedset_id in bedset_list: - result_list.append(self.get(bedset_id[0])) - return BedSetListResult( - count=len(result_list), - limit=limit, - offset=offset, - results=result_list, - ) + bedset_obj = session.scalar(statement) + files = [FileModel(**k.__dict__) for k in bedset_obj.files] + + session.delete(bedset_obj) + session.commit() + + self.delete_phc_view(identifier, nofail=True) + if files: + self.config.delete_files_s3(files) - def delete(self) -> None: + def delete_phc_view(self, identifier: str, nofail: bool = False) -> None: """ - Delete bed file from the database. + Delete view in pephub. - :param identifier: bed file identifier + :param identifier: bedset identifier + :param nofail: do not raise an error if view not found :return: None """ - raise NotImplementedError + _LOGGER.info(f"Deleting view in pephub for bedset '{identifier}'") + try: + self.config.phc.view.delete( + namespace=self.config.config.phc.namespace, + name=self.config.config.phc.name, + tag=self.config.config.phc.tag, + view_name=identifier, + ) + except Exception as e: + _LOGGER.error(f"Failed to delete view in pephub: {e}") + if not nofail: + raise e + return None + + def exists(self, identifier: str) -> bool: + """ + Check if bedset exists in the database. + + :param identifier: bedset identifier + :return: True if bedset exists, False otherwise + """ + statement = select(BedSets).where(BedSets.id == identifier) + with Session(self._db_engine.engine) as session: + result = session.execute(statement).one_or_none() + if result: + return True + return False + def add_bedfile(self, identifier: str, bedfile: str) -> None: raise NotImplementedError def delete_bedfile(self, identifier: str, bedfile: str) -> None: - raise NotImplementedError + raise NotImplementedError \ No newline at end of file diff --git a/bbconf/modules/objects.py b/bbconf/modules/objects.py index 23195364..67fa4155 100644 --- a/bbconf/modules/objects.py +++ b/bbconf/modules/objects.py @@ -115,7 +115,6 @@ def _get_result( f"Result {result_id} is not defined for bed {record_id}" ) elif record_type == "bedset": - # result = self.bedset.retrieve_one(record_id, result_id) _LOGGER.error("Not implemented") raise BedBaseConfError("ERROR NOT IMPLEMENTED YET") @@ -171,7 +170,7 @@ def get_drs_metadata( drs_dict = DRSModel( id=object_id, self_uri=f"drs://{base_uri}/{object_id}", - size=record_metadata.size or "unknown", + size=record_metadata.size or None, created_time=created_time, updated_time=modified_time, checksums=object_id, diff --git a/tests/conftest.py b/tests/conftest.py index 7f7cf13b..1e9102f6 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,7 +1,9 @@ import os import pytest from bbconf.bbagent import BedBaseAgent -from bbconf.db_utils import Bed +from unittest.mock import patch + +from .utils import BED_TEST_ID TESTS_DIR = os.path.dirname(os.path.abspath(__file__)) @@ -87,3 +89,11 @@ def example_dict(): @pytest.fixture def load_test_data(): db_engine = get_bbagent().config.db_engine() + + +@pytest.fixture() +def mocked_phc(mocker): + mocker.patch( + "pephubclient.modules.sample.PEPHubSample.get", + return_value={"sample_name": BED_TEST_ID, "other_metadata": "other_metadata_1"}, + ) diff --git a/tests/test_bbagent.py b/tests/test_bbagent.py deleted file mode 100644 index ee8c37e5..00000000 --- a/tests/test_bbagent.py +++ /dev/null @@ -1,209 +0,0 @@ -from bbconf.bbagent import BedBaseAgent -from bbconf.exceptions import BedFIleExistsError - -from unittest.mock import Mock -import pytest - -from .utils import ContextManagerDBTesting -from .conftest import get_bbagent - - -def test_bb_database(): - agent = get_bbagent() - assert isinstance(agent, BedBaseAgent) - - -class Test_BedFile_Agent: - - def test_upload(self, bbagent_obj, example_dict, mocker): - upload_s3_mock = mocker.patch( - "bbconf.config_parser.bedbaseconfig.BedBaseConfig.upload_s3", - return_value=True, - ) - with ContextManagerDBTesting(config=bbagent_obj.config, add_data=False): - bbagent_obj.bed.add(**example_dict) - - assert upload_s3_mock.called - assert bbagent_obj.bed.exists(example_dict["identifier"]) - - def test_upload_exists(self, bbagent_obj, example_dict, mocker): - upload_s3_mock = mocker.patch( - "bbconf.config_parser.bedbaseconfig.BedBaseConfig.upload_s3", - return_value=True, - ) - with ContextManagerDBTesting(config=bbagent_obj.config, add_data=False): - bbagent_obj.bed.add(**example_dict) - with pytest.raises(BedFIleExistsError): - bbagent_obj.bed.add(**example_dict) - - def test_add_nofail(self, bbagent_obj, example_dict, mocker): - upload_s3_mock = mocker.patch( - "bbconf.config_parser.bedbaseconfig.BedBaseConfig.upload_s3", - return_value=True, - ) - - example_dict["nofail"] = True - with ContextManagerDBTesting(config=bbagent_obj.config, add_data=False): - bbagent_obj.bed.add(**example_dict) - bbagent_obj.bed.add(**example_dict) - assert bbagent_obj.bed.exists(example_dict["identifier"]) - - def test_get_all(self): - agent = BedBaseAgent(config=config) - ff = agent.bed.get("91b2754c8ff01769bacfc80e6923c46e", full=True) - print(ff) - assert ff != None - - def test_get_raw_metadata(self): - agent = BedBaseAgent(config=config) - ff = agent.bed.get_raw_metadata("91b2754c8ff01769bacfc80e6923c46e") - print(ff) - assert ff != None - - def test_get_stats(self): - agent = BedBaseAgent(config=config) - ff = agent.bed.get_stats("91b2754c8ff01769bacfc80e6923c46e") - print(ff) - assert ff != None - - def test_get_files(self): - agent = BedBaseAgent(config=config) - ff = agent.bed.get_files("91b2754c8ff01769bacfc80e6923c46e") - print(ff) - assert ff != None - - def test_get_plots(self): - agent = BedBaseAgent(config=config) - ff = agent.bed.get_plots("91b2754c8ff01769bacfc80e6923c46e") - print(ff) - assert ff != None - - def test_get_objects(self): - agent = BedBaseAgent(config=config) - ff = agent.bed.get_objects("91b2754c8ff01769bacfc80e6923c46e") - print(ff) - - def test_get_list(self): - agent = BedBaseAgent(config=config) - ff = agent.bed.get_ids_list() - print(ff) - assert ff != None - - def test_qdrant_search(self): - agent = BedBaseAgent(config=config) - ff = agent.bed.text_to_bed_search("asf") - print(ff) - assert ff != None - - def test_qdrant_reindex(self): - agent = BedBaseAgent(config=config) - ff = agent.bed.reindex_qdrant() - ff - assert True - - def test_delete_qdrant_point(self): - agent = BedBaseAgent(config=config) - ff = agent.bed.delete_qdrant_point("91b2754c8ff01769bacfc80e6923c46e") - ff - assert True - - def test_bed_delete(self): - agent = BedBaseAgent( - config="/home/bnt4me/virginia/repos/bbuploader/config_db_local.yaml" - ) - ff = agent.bed.delete("ec8179a55ab7e649e15762d0e8cb5378") - # print(ff) - # assert ff != None - pass - - def test_bed_update(self): - # agent = BedBaseAgent(config=config) - # ff = agent.bed.update("91b2754c8ff01769bacfc80e6923c46e", {"number_of_regions": 44}) - # print(ff) - # assert ff != None - pass - - def test_create_qdrant_collection(self): - agent = BedBaseAgent( - config="/home/bnt4me/virginia/repos/bbuploader/config_db_local.yaml" - ) - ff = agent.bed.create_qdrant_collection() - ff - assert True - - -def test_get_stats(): - agent = BedBaseAgent(config=config) - ff = agent.get_stats("91b2754c8ff01769bacfc80e6923c46e") - print(ff) - assert ff != None - - -class TestObjects: - def test_object_path(self): - agent = BedBaseAgent(config=config) - ff = agent.objects.get_object_uri( - "bed", "bbad85f21962bb8d972444f7f9a3a932", "bed_file", "http" - ) - ff - - def test_object_path_thumbnail_error(self): - agent = BedBaseAgent(config=config) - # TODO: it should raise issue: - ff = agent.objects.get_thumbnail_uri( - "bed", "bbad85f21962bb8d972444f7f9a3a932", "bed_file", "http" - ) - ff - - def test_object_path_thumbnail(self): - agent = BedBaseAgent(config=config) - ff = agent.objects.get_thumbnail_uri( - "bed", "bbad85f21962bb8d972444f7f9a3a932", "widths_histogram", "http" - ) - ff - - def test_object_metadata(self): - agent = BedBaseAgent(config=config) - ff = agent.objects.get_drs_metadata( - "bed", "bbad85f21962bb8d972444f7f9a3a932", "widths_histogram", "localhost" - ) - ff - - -class TestBedset: - - def test_clalculate_stats(self): - agent = BedBaseAgent(config=config) - ff = agent.bedset._calculate_statistics(["91b2754c8ff01769bacfc80e6923c46e"]) - ff - assert ff != None - - def test_crate_bedset_all(self): - agent = BedBaseAgent(config=config) - agent.bedset.create( - "testinoo", - "test_name", - description="this is test description", - bedid_list=[ - "bbad85f21962bb8d972444f7f9a3a932", - "0dcdf8986a72a3d85805bbc9493a1302", - "db69691a3fee81a96c5dad57ca124fd8", - ], - statistics=True, - # plots={"test": "test"}, - upload_pephub=True, - no_fail=True, - ) - assert True - - def test_get_idset(self): - agent = BedBaseAgent(config=config) - ff = agent.bedset.get("test") - print(ff) - assert ff != None - - def test_get_idset_list(self): - agent = BedBaseAgent(config=config) - ff = agent.bedset.get_ids_list() - print(ff) - assert ff != None diff --git a/tests/test_bedfile.py b/tests/test_bedfile.py new file mode 100644 index 00000000..944edce7 --- /dev/null +++ b/tests/test_bedfile.py @@ -0,0 +1,236 @@ +from bbconf.bbagent import BedBaseAgent +from bbconf.exceptions import BedFIleExistsError, BEDFileNotFoundError +from bbconf.db_utils import Bed, Files + +from sqlalchemy.orm import Session +from sqlalchemy.sql import select + +from unittest.mock import Mock +import pytest + +from .utils import ContextManagerDBTesting +from .conftest import get_bbagent + +from .utils import BED_TEST_ID + + +def test_bb_database(): + agent = get_bbagent() + assert isinstance(agent, BedBaseAgent) + + +class Test_BedFile_Agent: + + def test_upload(self, bbagent_obj, example_dict, mocker): + upload_s3_mock = mocker.patch( + "bbconf.config_parser.bedbaseconfig.BedBaseConfig.upload_s3", + return_value=True, + ) + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=False): + bbagent_obj.bed.add(**example_dict) + + assert upload_s3_mock.called + assert bbagent_obj.bed.exists(example_dict["identifier"]) + + def test_upload_exists(self, bbagent_obj, example_dict, mocker): + upload_s3_mock = mocker.patch( + "bbconf.config_parser.bedbaseconfig.BedBaseConfig.upload_s3", + return_value=True, + ) + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=False): + bbagent_obj.bed.add(**example_dict) + with pytest.raises(BedFIleExistsError): + bbagent_obj.bed.add(**example_dict) + + def test_add_nofail(self, bbagent_obj, example_dict, mocker): + upload_s3_mock = mocker.patch( + "bbconf.config_parser.bedbaseconfig.BedBaseConfig.upload_s3", + return_value=True, + ) + + example_dict["nofail"] = True + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=False): + bbagent_obj.bed.add(**example_dict) + bbagent_obj.bed.add(**example_dict) + assert bbagent_obj.bed.exists(example_dict["identifier"]) + + def test_get_all(self, bbagent_obj, mocked_phc): + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): + return_result = bbagent_obj.bed.get(BED_TEST_ID, full=True) + assert return_result is not None + assert return_result.files is not None + assert return_result.plots is not None + assert return_result.raw_metadata is not None + + assert return_result.genome_alias == "hg38" + assert return_result.stats.number_of_regions == 1 + + assert return_result.files.bed_file is not None + assert return_result.plots.chrombins is not None + + def test_get_all_not_found(self, bbagent_obj): + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): + return_result = bbagent_obj.bed.get(BED_TEST_ID, full=False) + + assert return_result is not None + assert return_result.files is None + assert return_result.plots is None + assert return_result.raw_metadata is None + assert return_result.stats is None + + assert return_result.genome_alias == "hg38" + assert return_result.id == BED_TEST_ID + + def test_get_raw_metadata(self, bbagent_obj, mocked_phc): + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): + return_result = bbagent_obj.bed.get_raw_metadata(BED_TEST_ID) + + assert return_result is not None + assert return_result.sample_name == BED_TEST_ID + + def test_get_stats(self, bbagent_obj): + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): + return_result = bbagent_obj.bed.get_stats(BED_TEST_ID) + + assert return_result is not None + assert return_result.number_of_regions == 1 + + def test_get_files(self, bbagent_obj): + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): + return_result = bbagent_obj.bed.get_files(BED_TEST_ID) + + assert return_result is not None + assert return_result.bed_file.path is not None + + def test_get_plots(self, bbagent_obj): + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): + return_result = bbagent_obj.bed.get_plots(BED_TEST_ID) + + assert return_result is not None + assert return_result.chrombins is not None + + def test_get_objects(self, bbagent_obj): + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): + return_result = bbagent_obj.bed.get_objects(BED_TEST_ID) + + assert "bed_file" in return_result + assert "chrombins" in return_result + + def test_get_list(self, bbagent_obj): + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): + return_result = bbagent_obj.bed.get_ids_list(limit=100, offset=0) + + assert len(return_result.results) == 1 + assert return_result.count == 1 + assert return_result.results[0].id == BED_TEST_ID + assert return_result.limit == 100 + assert return_result.offset == 0 + + def test_get_list_genome_true(self, bbagent_obj): + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): + return_result = bbagent_obj.bed.get_ids_list( + limit=100, offset=0, genome="hg38" + ) + + assert len(return_result.results) == 1 + assert return_result.count == 1 + assert return_result.results[0].id == BED_TEST_ID + assert return_result.limit == 100 + assert return_result.offset == 0 + + def test_get_list_genome_false(self, bbagent_obj): + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): + return_result = bbagent_obj.bed.get_ids_list( + limit=100, offset=0, genome="hg381" + ) + + assert len(return_result.results) == 0 + assert return_result.count == 0 + + def test_get_list_bed_type_true(self, bbagent_obj): + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): + return_result = bbagent_obj.bed.get_ids_list( + limit=100, offset=0, bed_type="bed6+4" + ) + + assert len(return_result.results) == 1 + assert return_result.count == 1 + assert return_result.results[0].id == BED_TEST_ID + assert return_result.limit == 100 + assert return_result.offset == 0 + + def test_get_list_bed_type_false(self, bbagent_obj): + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): + return_result = bbagent_obj.bed.get_ids_list( + limit=100, offset=0, bed_type="bed6+5" + ) + + assert len(return_result.results) == 0 + assert return_result.count == 0 + + def test_get_list_bed_offset(self, bbagent_obj): + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): + return_result = bbagent_obj.bed.get_ids_list( + limit=100, + offset=1, + ) + + assert len(return_result.results) == 0 + assert return_result.count == 0 + assert return_result.offset == 1 + + def test_bed_delete(self, bbagent_obj, mocker): + mocker.patch("bbconf.config_parser.bedbaseconfig.BedBaseConfig.delete_files_s3") + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): + bbagent_obj.bed.delete(BED_TEST_ID) + + assert not bbagent_obj.bed.exists(BED_TEST_ID) + + with Session(bbagent_obj.config.db_engine.engine) as session: + result = session.scalar(select(Bed).where(Bed.id == BED_TEST_ID)) + assert result is None + + result = session.scalars(select(Files)) + assert len([k for k in result]) == 0 + + def test_bed_delete_not_found(self, bbagent_obj): + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): + with pytest.raises(BEDFileNotFoundError): + bbagent_obj.bed.delete("not_found") + + @pytest.mark.skip("Skipped, not fully implemented") + def test_bed_update(self): + # agent = BedBaseAgent(config=config) + # ff = agent.bed.update("91b2754c8ff01769bacfc80e6923c46e", {"number_of_regions": 44}) + # print(ff) + # assert ff != None + pass + + +@pytest.mark.skip("Skipped, because ML models and qdrant needed") +class TestVectorSearch: + + def test_qdrant_search(self, bbagent_obj, mocker): + mocker.patch( + "geniml.text2bednn.text2bednn.Text2BEDSearchInterface.nl_vec_search", + return_value={ + "id": BED_TEST_ID, + "payload": {"bed_id": "39b686ec08206b92b540ed434266ec9b"}, + "score": 0.2146723, + }, + ) + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): + return_result = bbagent_obj.bed.text_to_bed_search("something") + assert return_result + + def test_delete_qdrant_point(self, bbagent_obj): + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): + bbagent_obj.bed.delete_qdrant_point(BED_TEST_ID) + + def test_create_qdrant_collection(self): + agent = BedBaseAgent( + config="/home/bnt4me/virginia/repos/bbuploader/config_db_local.yaml" + ) + ff = agent.bed.create_qdrant_collection() + ff + assert True diff --git a/tests/test_bedset.py b/tests/test_bedset.py new file mode 100644 index 00000000..8399a024 --- /dev/null +++ b/tests/test_bedset.py @@ -0,0 +1,68 @@ +from bbconf.bbagent import BedBaseAgent +from bbconf.exceptions import BedFIleExistsError, BEDFileNotFoundError +from bbconf.db_utils import Bed, Files + +from sqlalchemy.orm import Session +from sqlalchemy.sql import select + +from unittest.mock import Mock +import pytest + +from .utils import ContextManagerDBTesting +from .conftest import get_bbagent + +from .utils import BED_TEST_ID + + +class TestBedset: + + def test_calculate_stats(self, bbagent_obj): + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): + results = bbagent_obj.bedset._calculate_statistics([BED_TEST_ID]) + + assert results is not None + assert results.sd is not None + assert results.mean is not None + + + def test_crate_bedset_all(self): + agent = BedBaseAgent(config=config) + agent.bedset.create( + "testinoo", + "test_name", + description="this is test description", + bedid_list=[ + "bbad85f21962bb8d972444f7f9a3a932", + ], + statistics=True, + upload_pephub=True, + no_fail=True, + ) + assert True + + def test_get_idset(self): + agent = BedBaseAgent(config=config) + ff = agent.bedset.get("test") + print(ff) + assert ff != None + + def test_get_idset_list(self): + agent = BedBaseAgent(config=config) + ff = agent.bedset.get_ids_list() + print(ff) + assert ff != None + +# +# +# def test_get_stats(bbagent_obj): +# with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): +# return_result = bbagent_obj.bed.get_stats() +# +# assert +# +# assert return_result is not None +# assert return_result.number_of_regions == 1 +# agent = BedBaseAgent(config=config) +# ff = agent.get_stats("91b2754c8ff01769bacfc80e6923c46e") +# print(ff) +# assert ff != None diff --git a/tests/test_objects.py b/tests/test_objects.py new file mode 100644 index 00000000..27c10925 --- /dev/null +++ b/tests/test_objects.py @@ -0,0 +1,44 @@ +from bbconf.exceptions import BEDFileNotFoundError, MissingThumbnailError +import pytest + +from .utils import ContextManagerDBTesting + +from .utils import BED_TEST_ID + + +class TestObjects: + def test_object_path(self, bbagent_obj): + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): + result = bbagent_obj.objects.get_object_uri( + "bed", BED_TEST_ID, "bed_file", "http" + ) + + assert isinstance(result, str) + + def test_object_path_error(self, bbagent_obj): + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): + with pytest.raises(BEDFileNotFoundError): + bbagent_obj.objects.get_object_uri( + "bed", "not_f", "bed_file", "http" + ) + + def test_object_path_thumbnail(self, bbagent_obj): + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): + result = bbagent_obj.objects.get_thumbnail_uri( + "bed", BED_TEST_ID, "chrombins", "http" + ) + assert isinstance(result, str) + + def test_object_path_thumbnail_error(self, bbagent_obj): + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): + with pytest.raises(MissingThumbnailError): + bbagent_obj.objects.get_thumbnail_uri( + "bed", BED_TEST_ID, "bed_file", "http" + ) + + def test_object_metadata(self, bbagent_obj): + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): + result = bbagent_obj.objects.get_drs_metadata( + "bed", BED_TEST_ID, "bed_file", "localhost" + ) + assert result is not None diff --git a/tests/utils.py b/tests/utils.py index 11281d4e..502d89f4 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -5,9 +5,12 @@ from sqlalchemy.orm import Session +BED_TEST_ID = "test_id" + + def get_example_dict() -> dict: value = { - "id": "test_id", + "id": BED_TEST_ID, "number_of_regions": 1, "median_tss_dist": 2, "mean_region_width": 3, @@ -40,6 +43,7 @@ def get_files() -> dict: "name": "bed_file", "path": "data/files/bbad85f21962bb8d972444f7f9a3a932.bed.gz", "description": "Bed file with regions", + "bedfile_id": BED_TEST_ID, } @@ -50,6 +54,7 @@ def get_plots() -> dict: "title": "Regions distribution over chromosomes", "path": "data/plots/bbad85f21962bb8d972444f7f9a3a932_chrombins.pdf", "path_thumbnail": "data/plots/bbad85f21962bb8d972444f7f9a3a932_chrombins.png", + "bedfile_id": BED_TEST_ID, } @@ -59,10 +64,11 @@ class ContextManagerDBTesting: the db is empty for each new test. """ - def __init__(self, config: Union[str, BedBaseConfig], add_data: bool = False): + def __init__(self, config: Union[str, BedBaseConfig], add_data: bool = False, bedset: bool = False): """ - :param config_path: path to the config file + :param config: config object :param add_data: add data to the database + :param bedset: add bedset data to the database """ if isinstance(config, BedBaseConfig): self.config = config @@ -70,6 +76,7 @@ def __init__(self, config: Union[str, BedBaseConfig], add_data: bool = False): self.config = BedBaseConfig(config) self.add_data = add_data + self.bedset = bedset def __enter__(self): @@ -77,6 +84,8 @@ def __enter__(self): if self.add_data: self._add_data() + if self.bedset: + self._add_bedset_data() def __exit__(self, exc_type, exc_value, exc_traceback): self.db_engine.delete_schema() @@ -92,3 +101,6 @@ def _add_data(self): session.add(new_files) session.add(new_plots) session.commit() + + def _add_bedset_data(self): + pass From 6e47c826c40321b0f5df57861ce3850adf098c94 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Thu, 28 Mar 2024 21:43:17 +0100 Subject: [PATCH 38/61] bedset tests --- .github/workflows/cli-coverage.yml | 4 +- .github/workflows/run-pytest.yml | 4 +- bbconf/models/bedset_models.py | 2 - bbconf/modules/bedsets.py | 11 +- tests/README.md | 4 +- tests/conftest.py | 12 ++ tests/test_bedset.py | 206 ++++++++++++++++++++++------- tests/test_objects.py | 8 +- tests/utils.py | 66 ++++++--- 9 files changed, 233 insertions(+), 84 deletions(-) diff --git a/.github/workflows/cli-coverage.yml b/.github/workflows/cli-coverage.yml index 65269542..15820a3a 100644 --- a/.github/workflows/cli-coverage.yml +++ b/.github/workflows/cli-coverage.yml @@ -16,8 +16,8 @@ jobs: image: postgres env: POSTGRES_USER: postgres - POSTGRES_PASSWORD: dockerpassword - POSTGRES_DB: pipestat-test + POSTGRES_PASSWORD: docker + POSTGRES_DB: bedbase POSTGRES_HOST: localhost ports: - 5432:5432 diff --git a/.github/workflows/run-pytest.yml b/.github/workflows/run-pytest.yml index 0b37a9fe..1389362c 100644 --- a/.github/workflows/run-pytest.yml +++ b/.github/workflows/run-pytest.yml @@ -20,8 +20,8 @@ jobs: image: postgres env: POSTGRES_USER: postgres - POSTGRES_PASSWORD: dockerpassword - POSTGRES_DB: pipestat-test + POSTGRES_PASSWORD: docker + POSTGRES_DB: bedbase POSTGRES_HOST: localhost ports: - 5432:5432 diff --git a/bbconf/models/bedset_models.py b/bbconf/models/bedset_models.py index e6a139b6..65b7dfd5 100644 --- a/bbconf/models/bedset_models.py +++ b/bbconf/models/bedset_models.py @@ -38,5 +38,3 @@ class BedSetBedFiles(BaseModel): limit: int offset: int results: List[BedMetadata] - - diff --git a/bbconf/modules/bedsets.py b/bbconf/modules/bedsets.py index 3cccd380..57a60696 100644 --- a/bbconf/modules/bedsets.py +++ b/bbconf/modules/bedsets.py @@ -52,11 +52,9 @@ def get(self, identifier: str, full: bool = False) -> BedSetMetadata: statement = select(BedSets).where(BedSets.id == identifier) with Session(self._db_engine.engine) as session: - bedset_obj = session.execute(statement).one() + bedset_obj = session.scalar(statement) if not bedset_obj: raise BedSetNotFoundError(identifier) - else: - bedset_obj = bedset_obj[0] list_of_bedfiles = [ bedset_obj.bedfile_id for bedset_obj in bedset_obj.bedfiles ] @@ -254,7 +252,9 @@ def _create_pephub_view( raise e return None - def get_ids_list(self, query: str = None, limit: int = 10, offset: int = 0) -> BedSetListResult: + def get_ids_list( + self, query: str = None, limit: int = 10, offset: int = 0 + ) -> BedSetListResult: """ Get list of bedsets from the database. @@ -384,9 +384,8 @@ def exists(self, identifier: str) -> bool: return True return False - def add_bedfile(self, identifier: str, bedfile: str) -> None: raise NotImplementedError def delete_bedfile(self, identifier: str, bedfile: str) -> None: - raise NotImplementedError \ No newline at end of file + raise NotImplementedError diff --git a/tests/README.md b/tests/README.md index 41765907..ee346086 100644 --- a/tests/README.md +++ b/tests/README.md @@ -1,6 +1,8 @@ # How to setup the test environment -### To create a test database for testing : +# before running the tests, make sure you have the following installed: + +### Create database before running the tests: ``` docker run --rm -it --name bedbase-test \ diff --git a/tests/conftest.py b/tests/conftest.py index 1e9102f6..47a11854 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -26,6 +26,18 @@ def bbagent_obj(): yield BedBaseAgent(config=CONFIG_PATH) +@pytest.fixture() +def example_bedset_plot(): + return { + "name": "chrombins", + "description": "Regions distribution over chromosomes", + "title": "Regions distribution over chromosomes", + "path": "data/plots/bbad85f21962bb8d972444f7f9a3a932_chrombins.pdf", + "path_thumbnail": "data/plots/bbad85f21962bb8d972444f7f9a3a932_chrombins.png", + "bedset_id": BED_TEST_ID, + } + + @pytest.fixture() def example_dict(): plots = { diff --git a/tests/test_bedset.py b/tests/test_bedset.py index 8399a024..51dca318 100644 --- a/tests/test_bedset.py +++ b/tests/test_bedset.py @@ -1,17 +1,18 @@ from bbconf.bbagent import BedBaseAgent -from bbconf.exceptions import BedFIleExistsError, BEDFileNotFoundError -from bbconf.db_utils import Bed, Files +from bbconf.exceptions import BedSetNotFoundError +from bbconf.db_utils import BedFileBedSetRelation, BedSets + +import os from sqlalchemy.orm import Session from sqlalchemy.sql import select -from unittest.mock import Mock import pytest from .utils import ContextManagerDBTesting -from .conftest import get_bbagent -from .utils import BED_TEST_ID +from .utils import BED_TEST_ID, BEDSET_TEST_ID +from .conftest import DATA_PATH class TestBedset: @@ -24,45 +25,158 @@ def test_calculate_stats(self, bbagent_obj): assert results.sd is not None assert results.mean is not None + def test_crate_bedset_all(self, bbagent_obj, mocker): + with ContextManagerDBTesting( + config=bbagent_obj.config, add_data=True, bedset=False + ): + upload_s3_mock = mocker.patch( + "bbconf.config_parser.bedbaseconfig.BedBaseConfig.upload_s3", + return_value=True, + ) + bbagent_obj.bedset.create( + "testinoo", + "test_name", + description="this is test description", + bedid_list=[ + BED_TEST_ID, + ], + plots={ + "region_commonality": { + "name": "region_commonality", + "description": "Regions distribution over chromosomes", + "title": "Regions distribution over chromosomes", + "path": os.path.join( + DATA_PATH, + "plots/bbad85f21962bb8d972444f7f9a3a932_chrombins.pdf", + ), + "path_thumbnail": os.path.join( + DATA_PATH, + "/plots/bbad85f21962bb8d972444f7f9a3a932_chrombins.png", + ), + }, + }, + statistics=True, + upload_s3=True, + upload_pephub=False, + no_fail=True, + ) + with Session(bbagent_obj.config.db_engine.engine) as session: + result = session.scalar(select(BedSets).where(BedSets.id == "testinoo")) + assert result is not None + assert result.name == "test_name" + assert len([k for k in result.files]) == 1 + + def test_get_metadata_full(self, bbagent_obj): + with ContextManagerDBTesting( + config=bbagent_obj.config, add_data=True, bedset=True + ): + result = bbagent_obj.bedset.get(BEDSET_TEST_ID, full=True) + + assert result.id == BEDSET_TEST_ID + assert result.md5sum == "bbad0000000000000000000000000000" + assert result.statistics.sd is not None + assert result.statistics.mean is not None + assert result.plots is not None + + def test_get_metadata_not_full(self, bbagent_obj): + with ContextManagerDBTesting( + config=bbagent_obj.config, add_data=True, bedset=True + ): + result = bbagent_obj.bedset.get(BEDSET_TEST_ID, full=False) + + assert result.id == BEDSET_TEST_ID + assert result.md5sum == "bbad0000000000000000000000000000" + assert result.statistics is None + assert result.plots is None + + def test_get_not_found(self, bbagent_obj): + with ContextManagerDBTesting( + config=bbagent_obj.config, add_data=True, bedset=True + ): + with pytest.raises(BedSetNotFoundError): + bbagent_obj.bedset.get("not_uid", full=True) + + def test_get_bedset_list(self, bbagent_obj): + with ContextManagerDBTesting( + config=bbagent_obj.config, add_data=True, bedset=True + ): + result = bbagent_obj.bedset.get_ids_list(limit=100, offset=0) + + assert result.count == 1 + assert result.limit == 100 + assert result.offset == 0 + assert len(result.results) == 1 + assert result.results[0].id == BEDSET_TEST_ID + + def test_get_bedset_list_offset(self, bbagent_obj): + with ContextManagerDBTesting( + config=bbagent_obj.config, add_data=True, bedset=True + ): + result = bbagent_obj.bedset.get_ids_list(limit=100, offset=1) + + # assert result.count == 1 + assert result.limit == 100 + assert result.offset == 1 + assert len(result.results) == 0 + + def test_get_idset_list_query_found(self, bbagent_obj): + with ContextManagerDBTesting( + config=bbagent_obj.config, add_data=True, bedset=True + ): + result = bbagent_obj.bedset.get_ids_list(query="rando", limit=100, offset=0) + + assert result.count == 1 + assert result.limit == 100 + assert result.offset == 0 + assert len(result.results) == 1 + + def test_get_idset_list_query_fail(self, bbagent_obj): + with ContextManagerDBTesting( + config=bbagent_obj.config, add_data=True, bedset=True + ): + result = bbagent_obj.bedset.get_ids_list( + query="rando1", limit=100, offset=0 + ) + + assert result.count == 0 + assert result.limit == 100 + assert result.offset == 0 + assert len(result.results) == 0 + + def test_get_get_bedset_bedfiles(self, bbagent_obj): + with ContextManagerDBTesting( + config=bbagent_obj.config, add_data=True, bedset=True + ): + result = bbagent_obj.bedset.get_bedset_bedfiles(BEDSET_TEST_ID) + + assert result.count == 1 + assert result.limit == 100 + assert result.offset == 0 + assert len(result.results) == 1 + + def test_delete(self, bbagent_obj): + with ContextManagerDBTesting( + config=bbagent_obj.config, add_data=True, bedset=True + ): + bbagent_obj.bedset.delete(BEDSET_TEST_ID) + + assert not bbagent_obj.bedset.exists(BEDSET_TEST_ID) + + def test_delete_not_existant(self, bbagent_obj): + with ContextManagerDBTesting( + config=bbagent_obj.config, add_data=True, bedset=True + ): + bbagent_obj.bedset.delete(BEDSET_TEST_ID) + + with pytest.raises(BedSetNotFoundError): + bbagent_obj.bedset.delete(BEDSET_TEST_ID) + + +def test_get_stats(bbagent_obj): + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True, bedset=True): + return_result = bbagent_obj.get_stats() - def test_crate_bedset_all(self): - agent = BedBaseAgent(config=config) - agent.bedset.create( - "testinoo", - "test_name", - description="this is test description", - bedid_list=[ - "bbad85f21962bb8d972444f7f9a3a932", - ], - statistics=True, - upload_pephub=True, - no_fail=True, - ) - assert True - - def test_get_idset(self): - agent = BedBaseAgent(config=config) - ff = agent.bedset.get("test") - print(ff) - assert ff != None - - def test_get_idset_list(self): - agent = BedBaseAgent(config=config) - ff = agent.bedset.get_ids_list() - print(ff) - assert ff != None - -# -# -# def test_get_stats(bbagent_obj): -# with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): -# return_result = bbagent_obj.bed.get_stats() -# -# assert -# -# assert return_result is not None -# assert return_result.number_of_regions == 1 -# agent = BedBaseAgent(config=config) -# ff = agent.get_stats("91b2754c8ff01769bacfc80e6923c46e") -# print(ff) -# assert ff != None + assert return_result + assert return_result.bedfiles_number == 1 + assert return_result.bedsets_number == 1 + assert return_result.genomes_number == 1 diff --git a/tests/test_objects.py b/tests/test_objects.py index 27c10925..7e0d1b3e 100644 --- a/tests/test_objects.py +++ b/tests/test_objects.py @@ -18,15 +18,13 @@ def test_object_path(self, bbagent_obj): def test_object_path_error(self, bbagent_obj): with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): with pytest.raises(BEDFileNotFoundError): - bbagent_obj.objects.get_object_uri( - "bed", "not_f", "bed_file", "http" - ) + bbagent_obj.objects.get_object_uri("bed", "not_f", "bed_file", "http") def test_object_path_thumbnail(self, bbagent_obj): with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): result = bbagent_obj.objects.get_thumbnail_uri( - "bed", BED_TEST_ID, "chrombins", "http" - ) + "bed", BED_TEST_ID, "chrombins", "http" + ) assert isinstance(result, str) def test_object_path_thumbnail_error(self, bbagent_obj): diff --git a/tests/utils.py b/tests/utils.py index 502d89f4..a856f871 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,39 +1,45 @@ from bbconf.config_parser.bedbaseconfig import BedBaseConfig -from bbconf.db_utils import Bed, Files +from bbconf.db_utils import Bed, Files, BedSets, BedFileBedSetRelation from typing import Union from sqlalchemy.orm import Session BED_TEST_ID = "test_id" +BEDSET_TEST_ID = "test_bedset_id" + + +stats = { + "number_of_regions": 1, + "median_tss_dist": 2, + "mean_region_width": 3, + "exon_frequency": 4, + "exon_percentage": 5, + "intron_frequency": 6, + "intron_percentage": 7, + "intergenic_percentage": 8, + "intergenic_frequency": 9, + "promotercore_frequency": 10, + "promotercore_percentage": 11, + "fiveutr_frequency": 12, + "fiveutr_percentage": 13, + "threeutr_frequency": 14, + "threeutr_percentage": 15, + "promoterprox_frequency": 16, + "promoterprox_percentage": 17, +} def get_example_dict() -> dict: value = { "id": BED_TEST_ID, - "number_of_regions": 1, - "median_tss_dist": 2, - "mean_region_width": 3, - "exon_frequency": 4, - "exon_percentage": 5, - "intron_frequency": 6, - "intron_percentage": 7, - "intergenic_percentage": 8, - "intergenic_frequency": 9, - "promotercore_frequency": 10, - "promotercore_percentage": 11, - "fiveutr_frequency": 12, - "fiveutr_percentage": 13, - "threeutr_frequency": 14, - "threeutr_percentage": 15, - "promoterprox_frequency": 16, - "promoterprox_percentage": 17, "bed_format": "narrowpeak", "bed_type": "bed6+4", "genome_alias": "hg38", "genome_digest": "2230c535660fb4774114bfa966a62f823fdb6d21acf138d4", "name": "random_name", } + value.update(stats) return value @@ -64,7 +70,12 @@ class ContextManagerDBTesting: the db is empty for each new test. """ - def __init__(self, config: Union[str, BedBaseConfig], add_data: bool = False, bedset: bool = False): + def __init__( + self, + config: Union[str, BedBaseConfig], + add_data: bool = False, + bedset: bool = False, + ): """ :param config: config object :param add_data: add data to the database @@ -103,4 +114,19 @@ def _add_data(self): session.commit() def _add_bedset_data(self): - pass + with Session(self.db_engine.engine) as session: + new_bedset = BedSets( + id=BEDSET_TEST_ID, + name=BEDSET_TEST_ID, + description="random desc", + bedset_means=stats, + bedset_standard_deviation=stats, + md5sum="bbad0000000000000000000000000000", + ) + new_bed_bedset = BedFileBedSetRelation( + bedfile_id=BED_TEST_ID, + bedset_id=BEDSET_TEST_ID, + ) + session.add(new_bedset) + session.add(new_bed_bedset) + session.commit() From e34e2880df08fb1ad6ebc3039bd211bfb1ff871a Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Thu, 28 Mar 2024 22:03:12 +0100 Subject: [PATCH 39/61] updated requirements --- bbconf/modules/bedsets.py | 7 +++++-- requirements/requirements-all.txt | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/bbconf/modules/bedsets.py b/bbconf/modules/bedsets.py index 57a60696..8ca728aa 100644 --- a/bbconf/modules/bedsets.py +++ b/bbconf/modules/bedsets.py @@ -3,8 +3,10 @@ from sqlalchemy import select, func, Numeric, Float, or_ from sqlalchemy.orm import Session -from geniml.io.utils import compute_md5sum_bedset +# TODO: will be available in the next geniml release +# from geniml.io.utils import compute_md5sum_bedset +from hashlib import md5 from bbconf.config_parser import BedBaseConfig from bbconf.db_utils import BedFileBedSetRelation, Bed, BedSets, Files @@ -148,7 +150,8 @@ def create( description=description, bedset_means=stats.mean.model_dump() if stats else None, bedset_standard_deviation=stats.sd.model_dump() if stats else None, - md5sum=compute_md5sum_bedset(bedid_list), + # md5sum=compute_md5sum_bedset(bedid_list), + md5sum=md5("".join(bedid_list).encode()).hexdigest(), ) if upload_s3: diff --git a/requirements/requirements-all.txt b/requirements/requirements-all.txt index ce0474b4..b3091a47 100644 --- a/requirements/requirements-all.txt +++ b/requirements/requirements-all.txt @@ -5,4 +5,5 @@ psycopg >= 3.1.15 colorlogs pydantic >= 2.6.4 botocore >= 1.34.54 -boto3 >= 1.34.54 \ No newline at end of file +boto3 >= 1.34.54 +pephubclient >= 0.4.1 From 64d4f13aeabeb37c83d9944a6d54a1aaac089356 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Thu, 28 Mar 2024 23:14:05 +0100 Subject: [PATCH 40/61] added tests and bedset functionalities --- bbconf/config_parser/bedbaseconfig.py | 13 ++++++--- bbconf/modules/bedsets.py | 38 +++++++++++++++++++++++- bbconf/modules/objects.py | 11 +++++-- tests/test_bedfile.py | 9 +++++- tests/test_bedset.py | 42 +++++++++++++++++++++++---- tests/utils.py | 14 +++++++++ 6 files changed, 114 insertions(+), 13 deletions(-) diff --git a/bbconf/config_parser/bedbaseconfig.py b/bbconf/config_parser/bedbaseconfig.py index 0729ae75..af8b3cad 100644 --- a/bbconf/config_parser/bedbaseconfig.py +++ b/bbconf/config_parser/bedbaseconfig.py @@ -12,7 +12,7 @@ from pephubclient import PEPHubClient import boto3 - +from botocore.exceptions import EndpointConnectionError from bbconf.db_utils import BaseEngine from bbconf.const import ( @@ -315,9 +315,14 @@ def delete_s3(self, s3_path: str) -> None: raise BedbaseS3ConnectionError( "Could not delete file from s3. Connection error." ) - return self._boto3_client.delete_object( - Bucket=self.config.s3.bucket, Key=s3_path - ) + try: + return self._boto3_client.delete_object( + Bucket=self.config.s3.bucket, Key=s3_path + ) + except EndpointConnectionError as e: + raise BedbaseS3ConnectionError( + "Could not delete file from s3. Connection error." + ) def delete_files_s3(self, files: List[FileModel]) -> None: """ diff --git a/bbconf/modules/bedsets.py b/bbconf/modules/bedsets.py index 8ca728aa..b13f0199 100644 --- a/bbconf/modules/bedsets.py +++ b/bbconf/modules/bedsets.py @@ -1,4 +1,4 @@ -from typing import List +from typing import List, Dict import logging from sqlalchemy import select, func, Numeric, Float, or_ @@ -101,6 +101,42 @@ def get_plots(self, identifier: str) -> BedSetPlots: **{plot[0].name: FileModel(**plot[0].model_dump()) for plot in plots} ) + def get_objects(self, identifier: str) -> Dict[str, FileModel]: + """ + Get objects for bedset by identifier. + + :param identifier: bedset identifier + :return: bedset objects + """ + statement = select(BedSets).where(BedSets.id == identifier) + return_dict = {} + + with Session(self._db_engine.engine) as session: + bedset_object = session.scalar(statement) + if not bedset_object: + raise BedSetNotFoundError(f"Bedset with id: {identifier} not found.") + for result in bedset_object.files: + return_dict[result.name] = FileModel(**result.__dict__) + + return return_dict + + def get_statistics(self, identifier: str) -> BedSetStats: + """ + Get statistics for bedset by identifier. + + :param identifier: bedset identifier + :return: bedset statistics + """ + statement = select(BedSets).where(BedSets.id == identifier) + with Session(self._db_engine.engine) as session: + bedset_object = session.scalar(statement) + if not bedset_object: + raise BedSetNotFoundError(f"Bedset with id: {identifier} not found.") + return BedSetStats( + mean=BedStats(**bedset_object.bedset_means), + sd=BedStats(**bedset_object.bedset_standard_deviation), + ) + def create( self, identifier: str, diff --git a/bbconf/modules/objects.py b/bbconf/modules/objects.py index 67fa4155..a4c19c56 100644 --- a/bbconf/modules/objects.py +++ b/bbconf/modules/objects.py @@ -3,6 +3,7 @@ from typing import List, Union, Literal from bbconf.modules.bedfiles import BedAgentBedFile +from bbconf.modules.bedsets import BedAgentBedSet from bbconf.config_parser.bedbaseconfig import BedBaseConfig from bbconf.const import PKG_NAME from bbconf.exceptions import ( @@ -28,6 +29,7 @@ def __init__(self, config: BedBaseConfig): """ self.config = config self.bed = BedAgentBedFile(self.config) + self.bedset = BedAgentBedSet(self.config) def _get_prefixed_uri(self, postfix: str, access_id: str) -> str: """ @@ -115,8 +117,13 @@ def _get_result( f"Result {result_id} is not defined for bed {record_id}" ) elif record_type == "bedset": - _LOGGER.error("Not implemented") - raise BedBaseConfError("ERROR NOT IMPLEMENTED YET") + try: + result = self.bedset.get_objects(identifier=record_id)[result_id] + _LOGGER.error(f"Result {result_id} is not defined for bed {record_id}") + except KeyError: + raise MissingObjectError( + f"Result {result_id} is not defined for bed {record_id}" + ) else: raise BedBaseConfError( diff --git a/tests/test_bedfile.py b/tests/test_bedfile.py index 944edce7..a887fb09 100644 --- a/tests/test_bedfile.py +++ b/tests/test_bedfile.py @@ -116,6 +116,13 @@ def test_get_objects(self, bbagent_obj): assert "bed_file" in return_result assert "chrombins" in return_result + def test_get_classification(self, bbagent_obj): + with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): + return_result = bbagent_obj.bed.get_classification(BED_TEST_ID) + + assert return_result is not None + assert return_result.bed_type == "bed6+4" + def test_get_list(self, bbagent_obj): with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): return_result = bbagent_obj.bed.get_ids_list(limit=100, offset=0) @@ -180,7 +187,7 @@ def test_get_list_bed_offset(self, bbagent_obj): assert return_result.offset == 1 def test_bed_delete(self, bbagent_obj, mocker): - mocker.patch("bbconf.config_parser.bedbaseconfig.BedBaseConfig.delete_files_s3") + mocker.patch("bbconf.config_parser.bedbaseconfig.BedBaseConfig.delete_s3") with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): bbagent_obj.bed.delete(BED_TEST_ID) diff --git a/tests/test_bedset.py b/tests/test_bedset.py index 51dca318..f4b14e3a 100644 --- a/tests/test_bedset.py +++ b/tests/test_bedset.py @@ -1,6 +1,6 @@ -from bbconf.bbagent import BedBaseAgent -from bbconf.exceptions import BedSetNotFoundError -from bbconf.db_utils import BedFileBedSetRelation, BedSets +from bbconf.exceptions import BedSetNotFoundError, BedbaseS3ConnectionError +from bbconf.db_utils import BedSets +from bbconf.models.base_models import FileModel import os @@ -96,6 +96,23 @@ def test_get_not_found(self, bbagent_obj): with pytest.raises(BedSetNotFoundError): bbagent_obj.bedset.get("not_uid", full=True) + def test_get_object(self, bbagent_obj): + with ContextManagerDBTesting( + config=bbagent_obj.config, add_data=True, bedset=True + ): + result = bbagent_obj.bedset.get_objects(BEDSET_TEST_ID) + + assert len(result) == 1 + + def test_get_stats(self, bbagent_obj): + with ContextManagerDBTesting( + config=bbagent_obj.config, add_data=True, bedset=True + ): + result = bbagent_obj.bedset.get_statistics(BEDSET_TEST_ID) + + assert result.sd is not None + assert result.mean is not None + def test_get_bedset_list(self, bbagent_obj): with ContextManagerDBTesting( config=bbagent_obj.config, add_data=True, bedset=True @@ -154,23 +171,38 @@ def test_get_get_bedset_bedfiles(self, bbagent_obj): assert result.offset == 0 assert len(result.results) == 1 - def test_delete(self, bbagent_obj): + def test_delete(self, bbagent_obj, mocker): with ContextManagerDBTesting( config=bbagent_obj.config, add_data=True, bedset=True ): + mocker.patch( + "bbconf.config_parser.bedbaseconfig.BedBaseConfig.delete_s3", + return_value=True, + ) bbagent_obj.bedset.delete(BEDSET_TEST_ID) assert not bbagent_obj.bedset.exists(BEDSET_TEST_ID) - def test_delete_not_existant(self, bbagent_obj): + def test_delete_none(self, bbagent_obj, mocker): with ContextManagerDBTesting( config=bbagent_obj.config, add_data=True, bedset=True ): + mocker.patch( + "bbconf.config_parser.bedbaseconfig.BedBaseConfig.delete_s3", + return_value=True, + ) bbagent_obj.bedset.delete(BEDSET_TEST_ID) with pytest.raises(BedSetNotFoundError): bbagent_obj.bedset.delete(BEDSET_TEST_ID) + def test_delete_s3_error(self, bbagent_obj): + with ContextManagerDBTesting( + config=bbagent_obj.config, add_data=True, bedset=True + ): + with pytest.raises(BedbaseS3ConnectionError): + bbagent_obj.bedset.delete(BEDSET_TEST_ID) + def test_get_stats(bbagent_obj): with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True, bedset=True): diff --git a/tests/utils.py b/tests/utils.py index a856f871..607636cc 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -43,6 +43,16 @@ def get_example_dict() -> dict: return value +def get_bedset_files() -> dict: + return { + "title": "region_commonality", + "name": "region_commonality", + "path": "data/files/bbad85f21962bb8d972444f7f9a3a932.bed.gz", + "description": "Bfffffff", + "bedset_id": BEDSET_TEST_ID, + } + + def get_files() -> dict: return { "title": "Bed file", @@ -127,6 +137,10 @@ def _add_bedset_data(self): bedfile_id=BED_TEST_ID, bedset_id=BEDSET_TEST_ID, ) + new_files = Files(**get_bedset_files()) + session.add(new_bedset) session.add(new_bed_bedset) + session.add(new_files) + session.commit() From b30f7fe892e7848e402fbf5f05c2b3591295b1d4 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Thu, 28 Mar 2024 23:26:26 +0100 Subject: [PATCH 41/61] fixed plot function --- bbconf/modules/bedsets.py | 19 +++++++++++++------ tests/test_bedset.py | 8 ++++++++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/bbconf/modules/bedsets.py b/bbconf/modules/bedsets.py index b13f0199..6b383f1f 100644 --- a/bbconf/modules/bedsets.py +++ b/bbconf/modules/bedsets.py @@ -92,14 +92,21 @@ def get_plots(self, identifier: str) -> BedSetPlots: :param identifier: bedset identifier :return: bedset plots """ - statement = select(Files).where(Files.bedset_id == identifier) + statement = select(BedSets).where(BedSets.id == identifier) with Session(self._db_engine.engine) as session: - plots = session.execute(statement).all() - - return BedSetPlots( - **{plot[0].name: FileModel(**plot[0].model_dump()) for plot in plots} - ) + bedset_object = session.scalar(statement) + if not bedset_object: + raise BedSetNotFoundError(f"Bed file with id: {identifier} not found.") + bedset_files = BedSetPlots() + for result in bedset_object.files: + if result.name in bedset_files.model_fields: + setattr( + bedset_files, + result.name, + FileModel(**result.__dict__), + ) + return bedset_files def get_objects(self, identifier: str) -> Dict[str, FileModel]: """ diff --git a/tests/test_bedset.py b/tests/test_bedset.py index f4b14e3a..f4b80a45 100644 --- a/tests/test_bedset.py +++ b/tests/test_bedset.py @@ -104,6 +104,14 @@ def test_get_object(self, bbagent_obj): assert len(result) == 1 + def test_get_plots(self, bbagent_obj): + with ContextManagerDBTesting( + config=bbagent_obj.config, add_data=True, bedset=True + ): + result = bbagent_obj.bedset.get_plots(BEDSET_TEST_ID) + + assert result is not None + def test_get_stats(self, bbagent_obj): with ContextManagerDBTesting( config=bbagent_obj.config, add_data=True, bedset=True From 5ef58aebe1eb33be4ebe9812af23b49db4ab989a Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Mon, 1 Apr 2024 19:02:06 +0200 Subject: [PATCH 42/61] added bedstat column --- bbconf/config_parser/bedbaseconfig.py | 23 ++++++++++++++ bbconf/db_utils.py | 32 +++++++++++++------ bbconf/models/bed_models.py | 4 +-- bbconf/models/bedset_models.py | 6 ++-- bbconf/modules/bedfiles.py | 45 +++++++++++++++++++++------ bbconf/modules/bedsets.py | 22 ++++++------- tests/utils.py | 7 +++-- 7 files changed, 101 insertions(+), 38 deletions(-) diff --git a/bbconf/config_parser/bedbaseconfig.py b/bbconf/config_parser/bedbaseconfig.py index af8b3cad..8cd2f896 100644 --- a/bbconf/config_parser/bedbaseconfig.py +++ b/bbconf/config_parser/bedbaseconfig.py @@ -5,6 +5,8 @@ from geniml.search import QdrantBackend import qdrant_client from geniml.text2bednn import text2bednn + +# from geniml.search import BED2BEDSearchInterface from fastembed.embedding import FlagEmbedding from geniml.region2vec import Region2VecExModel import warnings @@ -184,6 +186,27 @@ def _init_t2bsi_object(self) -> Union[text2bednn.Text2BEDSearchInterface, None]: ) return None + # def _init_b2bsi_object(self) -> Union[text2bednn.BED2BEDSearchInterface, None]: + # """ + # Create Bed 2 BED search interface and return this object + # + # :return: Bed2BEDSearchInterface object + # TODO: work in progress + # """ + # + # try: + # return text2bednn.BED2BEDSearchInterface( + # bed2vec_model=self._config.path.bed2vec, + # search_backend=self.qdrant_engine, + # ) + # except Exception as e: + # _LOGGER.error("Error in creating Bed2BEDSearchInterface object: " + str(e)) + # warnings.warn( + # "Error in creating Bed2BEDSearchInterface object: " + str(e), + # UserWarning, + # ) + # return None + @staticmethod def _init_pephubclient() -> Union[PEPHubClient, None]: """ diff --git a/bbconf/db_utils.py b/bbconf/db_utils.py index 2f9f14c1..e2cc58d5 100644 --- a/bbconf/db_utils.py +++ b/bbconf/db_utils.py @@ -98,7 +98,27 @@ class Bed(Base): onupdate=deliver_update_date, ) - # statistics: + files: Mapped[List["Files"]] = relationship( + "Files", back_populates="bedfile", cascade="all, delete-orphan" + ) + + bedsets: Mapped[List["BedFileBedSetRelation"]] = relationship( + "BedFileBedSetRelation", back_populates="bedfile", cascade="all, delete-orphan" + ) + + stats: Mapped["BedStats"] = relationship( + back_populates="bed", cascade="all, delete-orphan" + ) + + +class BedStats(Base): + __tablename__ = "bed_stats" + + id: Mapped[str] = mapped_column( + ForeignKey("bed.id", ondelete="CASCADE"), + primary_key=True, + index=True, + ) number_of_regions: Mapped[Optional[float]] gc_content: Mapped[Optional[float]] median_tss_dist: Mapped[Optional[float]] @@ -119,15 +139,7 @@ class Bed(Base): promotercore_percentage: Mapped[Optional[float]] tssdist: Mapped[Optional[float]] - # relations: - # plots: Mapped[List["Plots"]] = relationship("Plots", back_populates="bedfile") - files: Mapped[List["Files"]] = relationship( - "Files", back_populates="bedfile", cascade="all, delete-orphan" - ) - - bedsets: Mapped[List["BedFileBedSetRelation"]] = relationship( - "BedFileBedSetRelation", back_populates="bedfile", cascade="all, delete-orphan" - ) + bed: Mapped["Bed"] = relationship("Bed", back_populates="stats") class Files(Base): diff --git a/bbconf/models/bed_models.py b/bbconf/models/bed_models.py index bf0241bf..a7251b67 100644 --- a/bbconf/models/bed_models.py +++ b/bbconf/models/bed_models.py @@ -42,7 +42,7 @@ class BedClassification(BaseModel): model_config = ConfigDict(extra="ignore") -class BedStats(BaseModel): +class BedStatsModel(BaseModel): number_of_regions: Optional[float] = Field(None, alias="regions_no") gc_content: Optional[float] = None median_tss_dist: Optional[float] = None @@ -103,7 +103,7 @@ class BedMetadata(BedClassification): description: Optional[str] = None submission_date: datetime.datetime = None last_update_date: Optional[datetime.datetime] = None - stats: Union[BedStats, None] = None + stats: Union[BedStatsModel, None] = None # classification: BedClassification = None plots: Union[BedPlots, None] = None files: Union[BedFiles, None] = None diff --git a/bbconf/models/bedset_models.py b/bbconf/models/bedset_models.py index 65b7dfd5..c6523939 100644 --- a/bbconf/models/bedset_models.py +++ b/bbconf/models/bedset_models.py @@ -1,13 +1,13 @@ from pydantic import BaseModel, ConfigDict from typing import List, Union -from .bed_models import BedStats, BedMetadata +from .bed_models import BedStatsModel, BedMetadata from .base_models import FileModel class BedSetStats(BaseModel): - mean: BedStats = None - sd: BedStats = None + mean: BedStatsModel = None + sd: BedStatsModel = None class BedSetPlots(BaseModel): diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index c46b1ffb..d1b82bd8 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -10,7 +10,6 @@ from sqlalchemy.orm import Session from sqlalchemy import select -from sqlalchemy.exc import IntegrityError from bbconf.const import ( @@ -22,7 +21,7 @@ FileModel, BedPlots, BedClassification, - BedStats, + BedStatsModel, BedPEPHub, BedListResult, BedListSearchResult, @@ -33,7 +32,7 @@ BEDFileNotFoundError, BedFIleExistsError, ) -from bbconf.db_utils import Bed, Files +from bbconf.db_utils import Bed, Files, BedStats from bbconf.config_parser.bedbaseconfig import BedBaseConfig _LOGGER = getLogger(PKG_NAME) @@ -97,7 +96,7 @@ def get(self, identifier: str, full: bool = False) -> BedMetadata: _LOGGER.error( f"Unknown file type: {result.name}. And is not in the model fields. Skipping.." ) - bed_stats = BedStats(**bed_object.__dict__) + bed_stats = BedStatsModel(**bed_object.stats.__dict__) else: bed_plots = None bed_files = None @@ -136,7 +135,7 @@ def get(self, identifier: str, full: bool = False) -> BedMetadata: full_response=full, ) - def get_stats(self, identifier: str) -> BedStats: + def get_stats(self, identifier: str) -> BedStatsModel: """ Get file statistics by identifier. @@ -144,13 +143,13 @@ def get_stats(self, identifier: str) -> BedStats: :return: project statistics as BedStats object """ - statement = select(Bed).where(Bed.id == identifier) + statement = select(BedStats).where(BedStats.id == identifier) with Session(self._sa_engine) as session: bed_object = session.scalar(statement) if not bed_object: raise BEDFileNotFoundError(f"Bed file with id: {identifier} not found.") - bed_stats = BedStats(**bed_object.__dict__) + bed_stats = BedStatsModel(**bed_object.__dict__) return bed_stats @@ -342,7 +341,7 @@ def add( else: self.delete(identifier) - stats = BedStats(**stats) + stats = BedStatsModel(**stats) # TODO: we should not check for specific keys, of the plots! plots = BedPlots(**plots) files = BedFiles(**files) @@ -384,7 +383,6 @@ def add( with Session(self._sa_engine) as session: new_bed = Bed( id=identifier, - **stats.model_dump(), **classification.model_dump(), indexed=upload_qdrant, pephub=upload_pephub, @@ -408,6 +406,9 @@ def add( ) session.add(new_plot) + new_bedstat = BedStats(**stats.model_dump(), id=identifier) + session.add(new_bedstat) + session.commit() return None @@ -449,7 +450,7 @@ def update( f"Bed file with id: {identifier} not found. Cannot update." ) - stats = BedStats(**stats) + stats = BedStatsModel(**stats) plots = BedPlots(**plots) files = BedFiles(**files) classification = BedClassification(**classification) @@ -656,6 +657,30 @@ def text_to_bed_search( count=len(results), limit=limit, offset=offset, results=results_list ) + def bed_to_bed_search( + self, + region_set: RegionSet, + limit: int = 10, + offset: int = 0, + ) -> BedListSearchResult: + # # results = self._config.b2bsi.(query, limit=limit, offset=offset) + # results_list = [] + # for result in results: + # result_id = result["id"].replace("-", "") + # try: + # result_meta = self.get(result_id) + # except BEDFileNotFoundError as e: + # _LOGGER.warning( + # f"Could not retrieve metadata for bed file: {result_id}. Error: {e}" + # ) + # continue + # if result_meta: + # results_list.append(QdrantSearchResult(**result, metadata=result_meta)) + # return BedListSearchResult( + # count=0, limit=limit, offset=offset, results=[] + # ) + raise NotImplementedError + def reindex_qdrant(self) -> None: """ Re-upload all files to quadrant. diff --git a/bbconf/modules/bedsets.py b/bbconf/modules/bedsets.py index 6b383f1f..778f4a03 100644 --- a/bbconf/modules/bedsets.py +++ b/bbconf/modules/bedsets.py @@ -9,9 +9,9 @@ from hashlib import md5 from bbconf.config_parser import BedBaseConfig -from bbconf.db_utils import BedFileBedSetRelation, Bed, BedSets, Files +from bbconf.db_utils import BedFileBedSetRelation, BedSets, Files, BedStats -from bbconf.models.bed_models import BedStats +from bbconf.models.bed_models import BedStatsModel from bbconf.models.bedset_models import ( BedSetStats, BedSetMetadata, @@ -66,8 +66,8 @@ def get(self, identifier: str, full: bool = False) -> BedSetMetadata: setattr(plots, plot.name, FileModel(**plot.__dict__)) stats = BedSetStats( - mean=BedStats(**bedset_obj.bedset_means), - sd=BedStats(**bedset_obj.bedset_standard_deviation), + mean=BedStatsModel(**bedset_obj.bedset_means), + sd=BedStatsModel(**bedset_obj.bedset_standard_deviation), ).model_dump() else: plots = None @@ -140,8 +140,8 @@ def get_statistics(self, identifier: str) -> BedSetStats: if not bedset_object: raise BedSetNotFoundError(f"Bedset with id: {identifier} not found.") return BedSetStats( - mean=BedStats(**bedset_object.bedset_means), - sd=BedStats(**bedset_object.bedset_standard_deviation), + mean=BedStatsModel(**bedset_object.bedset_means), + sd=BedStatsModel(**bedset_object.bedset_standard_deviation), ) def create( @@ -234,7 +234,7 @@ def _calculate_statistics(self, bed_ids: List[str]) -> BedSetStats: """ _LOGGER.info("Calculating bedset statistics") - numeric_columns = BedStats.model_fields + numeric_columns = BedStatsModel.model_fields bedset_sd = {} bedset_mean = {} @@ -242,16 +242,16 @@ def _calculate_statistics(self, bed_ids: List[str]) -> BedSetStats: for column_name in numeric_columns: mean_bedset_statement = select( func.round( - func.avg(getattr(Bed, column_name)).cast(Numeric), 4 + func.avg(getattr(BedStats, column_name)).cast(Numeric), 4 ).cast(Float) - ).where(Bed.id.in_(bed_ids)) + ).where(BedStats.id.in_(bed_ids)) sd_bedset_statement = select( func.round( - func.stddev(getattr(Bed, column_name)).cast(Numeric), + func.stddev(getattr(BedStats, column_name)).cast(Numeric), 4, ).cast(Float) - ).where(Bed.id.in_(bed_ids)) + ).where(BedStats.id.in_(bed_ids)) bedset_sd[column_name] = session.execute(mean_bedset_statement).one()[0] bedset_mean[column_name] = session.execute(sd_bedset_statement).one()[0] diff --git a/tests/utils.py b/tests/utils.py index 607636cc..5d1b181d 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,5 +1,5 @@ from bbconf.config_parser.bedbaseconfig import BedBaseConfig -from bbconf.db_utils import Bed, Files, BedSets, BedFileBedSetRelation +from bbconf.db_utils import Bed, Files, BedSets, BedFileBedSetRelation, BedStats from typing import Union from sqlalchemy.orm import Session @@ -10,6 +10,7 @@ stats = { + "id": BED_TEST_ID, "number_of_regions": 1, "median_tss_dist": 2, "mean_region_width": 3, @@ -39,7 +40,6 @@ def get_example_dict() -> dict: "genome_digest": "2230c535660fb4774114bfa966a62f823fdb6d21acf138d4", "name": "random_name", } - value.update(stats) return value @@ -117,10 +117,13 @@ def _add_data(self): new_bed = Bed(**get_example_dict()) new_files = Files(**get_files()) new_plots = Files(**get_plots()) + new_stats = BedStats(**stats) session.add(new_bed) session.add(new_files) session.add(new_plots) + session.add(new_stats) + session.commit() def _add_bedset_data(self): From 06cfd3de9d849eec861a6b2cc0d5fec9d5edec60 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Mon, 1 Apr 2024 21:24:27 +0200 Subject: [PATCH 43/61] restructured drs metadata --- bbconf/modules/objects.py | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/bbconf/modules/objects.py b/bbconf/modules/objects.py index a4c19c56..cb391fdb 100644 --- a/bbconf/modules/objects.py +++ b/bbconf/modules/objects.py @@ -13,6 +13,7 @@ BedBaseConfError, ) +import datetime from bbconf.models.drs_models import AccessMethod, AccessURL, DRSModel from bbconf.models.bed_models import FileModel @@ -151,7 +152,6 @@ def get_drs_metadata( :return: DRS metadata """ - access_methods = [] object_id = f"{record_type}.{record_id}.{result_id}" bed_result = self.bed.get(record_id) created_time = bed_result.submission_date @@ -162,6 +162,35 @@ def get_drs_metadata( if not record_metadata: raise MissingObjectError("Record not found") + drs_dict = self.construct_drs_metadata( + base_uri, + object_id, + record_metadata, + created_time, + modified_time, + ) + + return drs_dict + + def construct_drs_metadata( + self, + base_uri: str, + object_id: str, + record_metadata: FileModel, + created_time: datetime.datetime = None, + modified_time: datetime.datetime = None, + ): + """ + Construct DRS metadata object + + :param base_uri: base uri to use for the self_uri field (server hostname of DRS broker) + :param object_id: record identifier + :param record_metadata: metadata of the record + :param created_time: time of creation + :param modified_time: time of last modification + :return: DRS metadata + """ + access_methods = [] for access_id in self.config.config.access_methods.model_dump().keys(): access_dict = AccessMethod( type=access_id, @@ -183,5 +212,4 @@ def get_drs_metadata( checksums=object_id, access_methods=access_methods, ) - return drs_dict From 754c38d8aa4acd47ddd0c2cef4e960fe551533a4 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Mon, 1 Apr 2024 23:03:17 +0200 Subject: [PATCH 44/61] added more objects info --- bbconf/config_parser/bedbaseconfig.py | 22 +++++++++++- bbconf/models/base_models.py | 2 ++ bbconf/modules/bedfiles.py | 49 +++++++++++++++++++++++---- bbconf/modules/bedsets.py | 20 +++++++++-- bbconf/modules/objects.py | 24 ++----------- tests/config_test.yaml | 1 + tests/utils.py | 2 +- 7 files changed, 89 insertions(+), 31 deletions(-) diff --git a/bbconf/config_parser/bedbaseconfig.py b/bbconf/config_parser/bedbaseconfig.py index 8cd2f896..a064e0ee 100644 --- a/bbconf/config_parser/bedbaseconfig.py +++ b/bbconf/config_parser/bedbaseconfig.py @@ -30,7 +30,11 @@ S3_PLOTS_PATH_FOLDER, S3_BEDSET_PATH_FOLDER, ) -from bbconf.exceptions import BedbaseS3ConnectionError, BedBaseConfError +from bbconf.exceptions import ( + BedbaseS3ConnectionError, + BedBaseConfError, + BadAccessMethodError, +) _LOGGER = logging.getLogger(PKG_NAME) @@ -359,3 +363,19 @@ def delete_files_s3(self, files: List[FileModel]) -> None: if file.path_thumbnail: self.delete_s3(file.path_thumbnail) return None + + def get_prefixed_uri(self, postfix: str, access_id: str) -> str: + """ + Return uri with correct prefix (schema) + + :param postfix: postfix of the uri (or everything after uri schema) + :param access_id: access method name, e.g. http, s3, etc. + :return: full uri path + """ + + try: + prefix = getattr(self.config.access_methods, access_id).prefix + return os.path.join(prefix, postfix) + except KeyError: + _LOGGER.error(f"Access method {access_id} is not defined.") + raise BadAccessMethodError(f"Access method {access_id} is not defined.") diff --git a/bbconf/models/base_models.py b/bbconf/models/base_models.py index 85ed64a6..d4decc13 100644 --- a/bbconf/models/base_models.py +++ b/bbconf/models/base_models.py @@ -9,6 +9,8 @@ class FileModel(BaseModel): path_thumbnail: Optional[Union[str, None]] = Field(None, alias="thumbnail_path") description: Optional[str] = None size: Optional[int] = None + object_id: Optional[str] = None + uri: Optional[str] = None model_config = ConfigDict(populate_by_name=True, extra="ignore") diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index d1b82bd8..c0acb8b1 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -38,6 +38,7 @@ _LOGGER = getLogger(PKG_NAME) QDRANT_GENOME = "hg38" +ACCESS_ID = "http" class BedAgentBedFile: @@ -82,14 +83,28 @@ def get(self, identifier: str, full: bool = False) -> BedMetadata: setattr( bed_plots, result.name, - FileModel(**result.__dict__), + FileModel( + **result.__dict__, + object_id=f"bed.{identifier}.{result.name}", + uri=self._config.get_prefixed_uri( + result.path, + access_id=ACCESS_ID, + ), + ), ) # FILES elif result.name in BedFiles.model_fields: setattr( bed_files, result.name, - FileModel(**result.__dict__), + FileModel( + **result.__dict__, + object_id=f"bed.{identifier}.{result.name}", + uri=self._config.get_prefixed_uri( + result.path, + access_id=ACCESS_ID, + ), + ), ) else: @@ -172,7 +187,14 @@ def get_plots(self, identifier: str) -> BedPlots: setattr( bed_plots, result.name, - FileModel(**result.__dict__), + FileModel( + **result.__dict__, + object_id=f"bed.{identifier}.{result.name}", + uri=self._config.get_prefixed_uri( + result.path, + access_id=ACCESS_ID, + ), + ), ) return bed_plots @@ -195,7 +217,14 @@ def get_files(self, identifier: str) -> BedFiles: setattr( bed_files, result.name, - FileModel(**result.__dict__), + FileModel( + **result.__dict__, + object_id=f"bed.{identifier}.{result.name}", + uri=self._config.get_prefixed_uri( + result.path, + access_id=ACCESS_ID, + ), + ), ) return bed_files @@ -392,7 +421,11 @@ def add( for k, v in files: if v: new_file = Files( - **v.model_dump(exclude_none=True, exclude_unset=True), + **v.model_dump( + exclude_none=True, + exclude_unset=True, + exclude={"object_id", "uri"}, + ), bedfile_id=identifier, type="file", ) @@ -400,7 +433,11 @@ def add( for k, v in plots: if v: new_plot = Files( - **v.model_dump(exclude_none=True, exclude_unset=True), + **v.model_dump( + exclude_none=True, + exclude_unset=True, + exclude={"object_id", "uri"}, + ), bedfile_id=identifier, type="plot", ) diff --git a/bbconf/modules/bedsets.py b/bbconf/modules/bedsets.py index 778f4a03..0d8014a8 100644 --- a/bbconf/modules/bedsets.py +++ b/bbconf/modules/bedsets.py @@ -27,6 +27,8 @@ _LOGGER = logging.getLogger(PKG_NAME) +ACCESS_ID = "http" + class BedAgentBedSet: """ @@ -104,7 +106,14 @@ def get_plots(self, identifier: str) -> BedSetPlots: setattr( bedset_files, result.name, - FileModel(**result.__dict__), + FileModel( + **result.__dict__, + object_id=f"bed.{identifier}.{result.name}", + uri=self.config.get_prefixed_uri( + result.path, + access_id=ACCESS_ID, + ), + ), ) return bedset_files @@ -123,7 +132,14 @@ def get_objects(self, identifier: str) -> Dict[str, FileModel]: if not bedset_object: raise BedSetNotFoundError(f"Bedset with id: {identifier} not found.") for result in bedset_object.files: - return_dict[result.name] = FileModel(**result.__dict__) + return_dict[result.name] = FileModel( + **result.__dict__, + object_id=f"bed.{identifier}.{result.name}", + uri=self.config.get_prefixed_uri( + result.path, + access_id=ACCESS_ID, + ), + ) return return_dict diff --git a/bbconf/modules/objects.py b/bbconf/modules/objects.py index cb391fdb..5f3a8679 100644 --- a/bbconf/modules/objects.py +++ b/bbconf/modules/objects.py @@ -1,5 +1,4 @@ import logging -import os from typing import List, Union, Literal from bbconf.modules.bedfiles import BedAgentBedFile @@ -7,7 +6,6 @@ from bbconf.config_parser.bedbaseconfig import BedBaseConfig from bbconf.const import PKG_NAME from bbconf.exceptions import ( - BadAccessMethodError, MissingThumbnailError, MissingObjectError, BedBaseConfError, @@ -32,22 +30,6 @@ def __init__(self, config: BedBaseConfig): self.bed = BedAgentBedFile(self.config) self.bedset = BedAgentBedSet(self.config) - def _get_prefixed_uri(self, postfix: str, access_id: str) -> str: - """ - Return uri with correct prefix (schema) - - :param postfix: postfix of the uri (or everything after uri schema) - :param access_id: access method name, e.g. http, s3, etc. - :return: full uri path - """ - - try: - prefix = getattr(self.config.config.access_methods, access_id).prefix - return os.path.join(prefix, postfix) - except KeyError: - _LOGGER.error(f"Access method {access_id} is not defined.") - raise BadAccessMethodError(f"Access method {access_id} is not defined.") - def get_thumbnail_uri( self, record_type: Literal["bed", "bedset"], @@ -66,7 +48,7 @@ def get_thumbnail_uri( """ result = self._get_result(record_type, record_id, result_id) if result.path_thumbnail: - return self._get_prefixed_uri(result.path_thumbnail, access_id) + return self.config.get_prefixed_uri(result.path_thumbnail, access_id) else: _LOGGER.error( @@ -93,7 +75,7 @@ def get_object_uri( :return: """ result = self._get_result(record_type, record_id, result_id) - return self._get_prefixed_uri(result.path, access_id) + return self.config.get_prefixed_uri(result.path, access_id) def _get_result( self, @@ -196,7 +178,7 @@ def construct_drs_metadata( type=access_id, access_id=access_id, access_url=AccessURL( - url=self._get_prefixed_uri(record_metadata.path, access_id) + url=self.config.get_prefixed_uri(record_metadata.path, access_id) ), region=self.config.config.access_methods.model_dump()[access_id].get( "region", None diff --git a/tests/config_test.yaml b/tests/config_test.yaml index ea84400d..6373dba5 100644 --- a/tests/config_test.yaml +++ b/tests/config_test.yaml @@ -16,6 +16,7 @@ qdrant: collection: "bedbase" s3: bucket: bedbase + endpoint_url: "None" phc: namespace: bedbase name: bedbase diff --git a/tests/utils.py b/tests/utils.py index 5d1b181d..55e54b2a 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -5,7 +5,7 @@ from sqlalchemy.orm import Session -BED_TEST_ID = "test_id" +BED_TEST_ID = "bbad85f21962bb8d972444f7f9a3a932" BEDSET_TEST_ID = "test_bedset_id" From 87dcb9d0abba66fb13af54830fb7f7d2b74f677c Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Tue, 2 Apr 2024 17:51:08 +0200 Subject: [PATCH 45/61] added access methods to files --- bbconf/config_parser/bedbaseconfig.py | 21 +++++++++++++++++++++ bbconf/models/base_models.py | 6 ++++-- bbconf/modules/bedfiles.py | 26 +++++++++++--------------- bbconf/modules/bedsets.py | 5 ++--- bbconf/modules/objects.py | 14 +------------- 5 files changed, 39 insertions(+), 33 deletions(-) diff --git a/bbconf/config_parser/bedbaseconfig.py b/bbconf/config_parser/bedbaseconfig.py index a064e0ee..872d9b67 100644 --- a/bbconf/config_parser/bedbaseconfig.py +++ b/bbconf/config_parser/bedbaseconfig.py @@ -35,6 +35,7 @@ BedBaseConfError, BadAccessMethodError, ) +from bbconf.models.drs_models import AccessMethod, AccessURL _LOGGER = logging.getLogger(PKG_NAME) @@ -379,3 +380,23 @@ def get_prefixed_uri(self, postfix: str, access_id: str) -> str: except KeyError: _LOGGER.error(f"Access method {access_id} is not defined.") raise BadAccessMethodError(f"Access method {access_id} is not defined.") + + def construct_access_method_list(self, rel_path: str) -> List[AccessMethod]: + """ + Construct access method list for a given record + + :param rel_path: relative path to the record + :return: list of access methods + """ + access_methods = [] + for access_id in self.config.access_methods.model_dump().keys(): + access_dict = AccessMethod( + type=access_id, + access_id=access_id, + access_url=AccessURL(url=self.get_prefixed_uri(rel_path, access_id)), + region=self.config.access_methods.model_dump()[access_id].get( + "region", None + ), + ) + access_methods.append(access_dict) + return access_methods diff --git a/bbconf/models/base_models.py b/bbconf/models/base_models.py index d4decc13..cfd37c70 100644 --- a/bbconf/models/base_models.py +++ b/bbconf/models/base_models.py @@ -1,5 +1,7 @@ from pydantic import BaseModel, ConfigDict, Field -from typing import Optional, Union +from typing import Optional, Union, List + +from .drs_models import AccessMethod class FileModel(BaseModel): @@ -10,7 +12,7 @@ class FileModel(BaseModel): description: Optional[str] = None size: Optional[int] = None object_id: Optional[str] = None - uri: Optional[str] = None + access_methods: List[AccessMethod] = None model_config = ConfigDict(populate_by_name=True, extra="ignore") diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index c0acb8b1..44fb10c9 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -86,9 +86,8 @@ def get(self, identifier: str, full: bool = False) -> BedMetadata: FileModel( **result.__dict__, object_id=f"bed.{identifier}.{result.name}", - uri=self._config.get_prefixed_uri( - result.path, - access_id=ACCESS_ID, + access_methods=self._config.construct_access_method_list( + result.path ), ), ) @@ -100,12 +99,11 @@ def get(self, identifier: str, full: bool = False) -> BedMetadata: FileModel( **result.__dict__, object_id=f"bed.{identifier}.{result.name}", - uri=self._config.get_prefixed_uri( - result.path, - access_id=ACCESS_ID, + access_methods=self._config.construct_access_method_list( + result.path ), ), - ) + ), else: _LOGGER.error( @@ -190,9 +188,8 @@ def get_plots(self, identifier: str) -> BedPlots: FileModel( **result.__dict__, object_id=f"bed.{identifier}.{result.name}", - uri=self._config.get_prefixed_uri( - result.path, - access_id=ACCESS_ID, + access_methods=self._config.construct_access_method_list( + result.path ), ), ) @@ -220,9 +217,8 @@ def get_files(self, identifier: str) -> BedFiles: FileModel( **result.__dict__, object_id=f"bed.{identifier}.{result.name}", - uri=self._config.get_prefixed_uri( - result.path, - access_id=ACCESS_ID, + access_methods=self._config.construct_access_method_list( + result.path ), ), ) @@ -424,7 +420,7 @@ def add( **v.model_dump( exclude_none=True, exclude_unset=True, - exclude={"object_id", "uri"}, + exclude={"object_id", "access_methods"}, ), bedfile_id=identifier, type="file", @@ -436,7 +432,7 @@ def add( **v.model_dump( exclude_none=True, exclude_unset=True, - exclude={"object_id", "uri"}, + exclude={"object_id", "access_methods"}, ), bedfile_id=identifier, type="plot", diff --git a/bbconf/modules/bedsets.py b/bbconf/modules/bedsets.py index 0d8014a8..9773ee1b 100644 --- a/bbconf/modules/bedsets.py +++ b/bbconf/modules/bedsets.py @@ -135,9 +135,8 @@ def get_objects(self, identifier: str) -> Dict[str, FileModel]: return_dict[result.name] = FileModel( **result.__dict__, object_id=f"bed.{identifier}.{result.name}", - uri=self.config.get_prefixed_uri( - result.path, - access_id=ACCESS_ID, + access_methods=self.config.construct_access_method_list( + result.path ), ) diff --git a/bbconf/modules/objects.py b/bbconf/modules/objects.py index 5f3a8679..d39b2f78 100644 --- a/bbconf/modules/objects.py +++ b/bbconf/modules/objects.py @@ -172,19 +172,7 @@ def construct_drs_metadata( :param modified_time: time of last modification :return: DRS metadata """ - access_methods = [] - for access_id in self.config.config.access_methods.model_dump().keys(): - access_dict = AccessMethod( - type=access_id, - access_id=access_id, - access_url=AccessURL( - url=self.config.get_prefixed_uri(record_metadata.path, access_id) - ), - region=self.config.config.access_methods.model_dump()[access_id].get( - "region", None - ), - ) - access_methods.append(access_dict) + access_methods = self.config.construct_access_method_list(record_metadata.path) drs_dict = DRSModel( id=object_id, self_uri=f"drs://{base_uri}/{object_id}", From 12889832bd3dd91373fa8a67fddaac4265861713 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Tue, 2 Apr 2024 21:37:59 +0200 Subject: [PATCH 46/61] added schema visualization --- bbconf/db_utils.py | 12 + docs/schema.svg | 755 ++++++++++++++++++++++++++++++ requirements/requirements-all.txt | 1 + tests/test_objects.py | 5 + 4 files changed, 773 insertions(+) create mode 100644 docs/schema.svg diff --git a/bbconf/db_utils.py b/bbconf/db_utils.py index e2cc58d5..887a56b4 100644 --- a/bbconf/db_utils.py +++ b/bbconf/db_utils.py @@ -22,6 +22,7 @@ mapped_column, relationship, ) +from sqlalchemy_schemadisplay import create_schema_graph from bbconf.const import PKG_NAME @@ -345,3 +346,14 @@ def check_db_connection(self): self.session_execute(select(Bed).limit(1)) except ProgrammingError: raise SchemaError() + + def create_schema_graph(self, output_file: str = "schema.svg"): + """ + Create schema graph of the database. + + :param output_file: path to the output file + :return: None + """ + graph = create_schema_graph(engine=self.engine, metadata=Base.metadata) + graph.write(output_file, format="svg", prog="dot") + return None diff --git a/docs/schema.svg b/docs/schema.svg new file mode 100644 index 00000000..1b3b8e4b --- /dev/null +++ b/docs/schema.svg @@ -0,0 +1,755 @@ + + + + + + + + + + bed + bed + + - id : VARCHAR + - name : VARCHAR + - genome_alias : VARCHAR + - genome_digest : VARCHAR + - description : VARCHAR + - bed_type : VARCHAR + - bed_format : VARCHAR + - indexed : BOOLEAN + - pephub : BOOLEAN + - submission_date : TIMESTAMP + - last_update_date : TIMESTAMP + + UNIQUE (id) + INDEX (id) + + + + bed_stats + bed_stats + + - id : VARCHAR + - number_of_regions : FLOAT + - gc_content : FLOAT + - median_tss_dist : FLOAT + - mean_region_width : FLOAT + - exon_frequency : FLOAT + - intron_frequency : FLOAT + - promoterprox_frequency : FLOAT + - intergenic_frequency : FLOAT + - promotercore_frequency : FLOAT + - fiveutr_frequency : FLOAT + - threeutr_frequency : FLOAT + - fiveutr_percentage : FLOAT + - threeutr_percentage : FLOAT + - promoterprox_percentage : FLOAT + - exon_percentage : FLOAT + - intron_percentage : FLOAT + - intergenic_percentage : FLOAT + - promotercore_percentage : FLOAT + - tssdist : FLOAT + + UNIQUE (id) + INDEX (id) + + + + id + + id + + bedfile_bedset_relation + bedfile_bedset_relation + + - bedset_id : VARCHAR + - bedfile_id : VARCHAR + + UNIQUE (bedset_id, bedfile_id) + + + + id + + bedfile_id + + files + files + + - id : INTEGER + - name : VARCHAR + - title : VARCHAR + - type : VARCHAR + - path : VARCHAR + - path_thumbnail : VARCHAR + - description : VARCHAR + - size : INTEGER + - bedfile_id : VARCHAR + - bedset_id : VARCHAR + + UNIQUE (id) + INDEX (bedset_id) + INDEX (id) + INDEX (bedfile_id) + + + + files->bed + + + + + id + + bedfile_id + + + bedsets + bedsets + + - id : VARCHAR + - name : VARCHAR + - description : VARCHAR + - submission_date : TIMESTAMP + - last_update_date : TIMESTAMP + - md5sum : VARCHAR + - bedset_means : JSON + - bedset_standard_deviation : JSON + + UNIQUE (id) + INDEX (id) + + + + files->bedsets + + + + + id + + bedset_id + + + id + + bedset_id + + + + diff --git a/requirements/requirements-all.txt b/requirements/requirements-all.txt index b3091a47..cb11dcae 100644 --- a/requirements/requirements-all.txt +++ b/requirements/requirements-all.txt @@ -7,3 +7,4 @@ pydantic >= 2.6.4 botocore >= 1.34.54 boto3 >= 1.34.54 pephubclient >= 0.4.1 +sqlalchemy_schemadisplay \ No newline at end of file diff --git a/tests/test_objects.py b/tests/test_objects.py index 7e0d1b3e..7f843258 100644 --- a/tests/test_objects.py +++ b/tests/test_objects.py @@ -40,3 +40,8 @@ def test_object_metadata(self, bbagent_obj): "bed", BED_TEST_ID, "bed_file", "localhost" ) assert result is not None + + +@pytest.mark.skip("Used to visualize the schema") +def test_create_schema_graph(bbagent_obj): + bbagent_obj.config.db_engine.create_schema_graph() From e834f591a8c300e4c52bd3060ff6d7d35cb92a40 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Tue, 2 Apr 2024 22:16:04 +0200 Subject: [PATCH 47/61] added name to the bedfile processing --- bbconf/modules/bedfiles.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index 44fb10c9..5b548b8b 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -324,6 +324,7 @@ def add( self, identifier: str, stats: dict, + name: str = None, metadata: dict = None, plots: dict = None, files: dict = None, @@ -340,6 +341,7 @@ def add( :param identifier: bed file identifier :param stats: bed file results {statistics, plots, files, metadata} + :param name: bed file human-readable name :param metadata: bed file metadata (will be saved in pephub) :param plots: bed file plots :param files: bed file files @@ -404,7 +406,7 @@ def add( plots = self._config.upload_files_s3( identifier, files=plots, base_path=local_path, type="plots" ) - + classification.name = name or identifier with Session(self._sa_engine) as session: new_bed = Bed( id=identifier, From 1fef3c94a559b0b42556eaaa632ef6f079392888 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Tue, 2 Apr 2024 23:27:37 +0200 Subject: [PATCH 48/61] reverted name changes --- bbconf/modules/bedfiles.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index 5b548b8b..a9845d71 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -324,7 +324,6 @@ def add( self, identifier: str, stats: dict, - name: str = None, metadata: dict = None, plots: dict = None, files: dict = None, @@ -341,7 +340,6 @@ def add( :param identifier: bed file identifier :param stats: bed file results {statistics, plots, files, metadata} - :param name: bed file human-readable name :param metadata: bed file metadata (will be saved in pephub) :param plots: bed file plots :param files: bed file files @@ -406,7 +404,6 @@ def add( plots = self._config.upload_files_s3( identifier, files=plots, base_path=local_path, type="plots" ) - classification.name = name or identifier with Session(self._sa_engine) as session: new_bed = Bed( id=identifier, From 1ccd44b2c4cf4d4326d0dc89a31870e4ddd7a055 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Wed, 3 Apr 2024 15:54:16 +0200 Subject: [PATCH 49/61] added bbconf overview --- docs/bedbase_overview.svg | 3406 +++++++++++++++++++++++++++++++++++++ 1 file changed, 3406 insertions(+) create mode 100644 docs/bedbase_overview.svg diff --git a/docs/bedbase_overview.svg b/docs/bedbase_overview.svg new file mode 100644 index 00000000..c9e6b6f9 --- /dev/null +++ b/docs/bedbase_overview.svg @@ -0,0 +1,3406 @@ + + + + + +BBclientBED2BED searchText2BED searchBedmakerBedstat.bed.bed.bedBedbuncherFastAPIBEDhostPEPhubBBconfOther toolsBBuploaderPEPhubgeofetchgeofetchGEO From ceda04a1690c14e59acda67d474ee5e6bc79aada Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Wed, 3 Apr 2024 19:05:33 +0200 Subject: [PATCH 50/61] added bbconf overview --- bbconf/config_parser/bedbaseconfig.py | 1 + bbconf/models/bed_models.py | 4 ++-- docs/bedbase_overview.svg | 5 ++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/bbconf/config_parser/bedbaseconfig.py b/bbconf/config_parser/bedbaseconfig.py index 872d9b67..a8f522dd 100644 --- a/bbconf/config_parser/bedbaseconfig.py +++ b/bbconf/config_parser/bedbaseconfig.py @@ -269,6 +269,7 @@ def upload_s3(self, file_path: str, s3_path: Union[Path, str]) -> None: ) if not os.path.exists(file_path): raise BedBaseConfError(f"File {file_path} does not exist.") + _LOGGER.info(f"Uploading file to s3: {s3_path}") return self._boto3_client.upload_file(file_path, self.config.s3.bucket, s3_path) def upload_files_s3( diff --git a/bbconf/models/bed_models.py b/bbconf/models/bed_models.py index a7251b67..7a0b44dc 100644 --- a/bbconf/models/bed_models.py +++ b/bbconf/models/bed_models.py @@ -21,8 +21,8 @@ class BedPlots(BaseModel): class BedFiles(BaseModel): - bed_file: Union[FileModel, None] = Field(None, alias="bedfile") - bigbed_file: Union[FileModel, None] = Field(None, alias="bigbedfile") + bedfile: Union[FileModel, None] = Field(None, alias="bed_file") + bigbedfile: Union[FileModel, None] = Field(None, alias="bigbed_file") model_config = ConfigDict( populate_by_name=True, diff --git a/docs/bedbase_overview.svg b/docs/bedbase_overview.svg index c9e6b6f9..d775db29 100644 --- a/docs/bedbase_overview.svg +++ b/docs/bedbase_overview.svg @@ -13,6 +13,9 @@ sodipodi:docname="bedbase_overview.svg" inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)" xml:space="preserve" + inkscape:export-filename="../../../../Downloads/bedbase_overview.png" + inkscape:export-xdpi="1000" + inkscape:export-ydpi="1000" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:xlink="http://www.w3.org/1999/xlink" @@ -103,7 +106,7 @@ inkscape:deskcolor="#d1d1d1" inkscape:document-units="pt" inkscape:zoom="0.92593837" - inkscape:cx="389.87476" + inkscape:cx="389.33477" inkscape:cy="185.7575" inkscape:window-width="1920" inkscape:window-height="1082" From 642e443b166b251213778c305270941dbe94a480 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Wed, 3 Apr 2024 20:27:57 +0200 Subject: [PATCH 51/61] hot fix for geniml --- requirements/requirements-all.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/requirements/requirements-all.txt b/requirements/requirements-all.txt index cb11dcae..c6c7aaaa 100644 --- a/requirements/requirements-all.txt +++ b/requirements/requirements-all.txt @@ -7,4 +7,6 @@ pydantic >= 2.6.4 botocore >= 1.34.54 boto3 >= 1.34.54 pephubclient >= 0.4.1 -sqlalchemy_schemadisplay \ No newline at end of file +sqlalchemy_schemadisplay +# quick fix for gesnim +scipy <= 1.11.0 \ No newline at end of file From 2b5f30227f522a0155915d99ba5706e3c8bbfbd3 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Wed, 3 Apr 2024 20:55:25 +0200 Subject: [PATCH 52/61] updated uploading s3 --- bbconf/config_parser/bedbaseconfig.py | 1 + bbconf/models/bed_models.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/bbconf/config_parser/bedbaseconfig.py b/bbconf/config_parser/bedbaseconfig.py index a8f522dd..0f53059a 100644 --- a/bbconf/config_parser/bedbaseconfig.py +++ b/bbconf/config_parser/bedbaseconfig.py @@ -313,6 +313,7 @@ def upload_files_s3( ) self.upload_s3(file_path, s3_path=s3_path) + setattr(value, "name", key) setattr(value, "size", os.path.getsize(file_path)) setattr(value, "path", s3_path) diff --git a/bbconf/models/bed_models.py b/bbconf/models/bed_models.py index 7a0b44dc..a7251b67 100644 --- a/bbconf/models/bed_models.py +++ b/bbconf/models/bed_models.py @@ -21,8 +21,8 @@ class BedPlots(BaseModel): class BedFiles(BaseModel): - bedfile: Union[FileModel, None] = Field(None, alias="bed_file") - bigbedfile: Union[FileModel, None] = Field(None, alias="bigbed_file") + bed_file: Union[FileModel, None] = Field(None, alias="bedfile") + bigbed_file: Union[FileModel, None] = Field(None, alias="bigbedfile") model_config = ConfigDict( populate_by_name=True, From fa35699bada9062cf7d3cdd7536624df7a51c5c6 Mon Sep 17 00:00:00 2001 From: Oleksandr Date: Wed, 3 Apr 2024 21:03:36 +0200 Subject: [PATCH 53/61] Update bbconf/config_parser/bedbaseconfig.py Co-authored-by: Nathan LeRoy <41063083+nleroy917@users.noreply.github.com> --- bbconf/config_parser/bedbaseconfig.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bbconf/config_parser/bedbaseconfig.py b/bbconf/config_parser/bedbaseconfig.py index 0f53059a..833cfb60 100644 --- a/bbconf/config_parser/bedbaseconfig.py +++ b/bbconf/config_parser/bedbaseconfig.py @@ -297,7 +297,7 @@ def upload_files_s3( s3_output_base_folder = S3_BEDSET_PATH_FOLDER else: raise BedBaseConfError( - f"Invalid type: {type}. Should be 'files' or 'plots'" +f"Invalid type: {type}. Should be 'files', 'plots', or 'bedsets'" ) for key, value in files: From 07a593ac86e3e0713a58f4691a473e5eb0594e56 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Wed, 3 Apr 2024 21:18:39 +0200 Subject: [PATCH 54/61] sorted, fixed cleand --- bbconf/__init__.py | 4 +- bbconf/bbagent.py | 5 +-- bbconf/config_parser/bedbaseconfig.py | 55 +++++++++++++------------- bbconf/config_parser/models.py | 19 ++++----- bbconf/db_utils.py | 10 ++--- bbconf/helpers.py | 3 +- bbconf/models/base_models.py | 3 +- bbconf/models/bed_models.py | 3 +- bbconf/models/bedset_models.py | 5 ++- bbconf/models/drs_models.py | 3 +- bbconf/modules/bedfiles.py | 57 +++++++++++++-------------- bbconf/modules/bedsets.py | 24 ++++++----- bbconf/modules/objects.py | 16 ++++---- tests/conftest.py | 5 ++- tests/test_bedfile.py | 20 ++++------ tests/test_bedset.py | 15 +++---- tests/test_objects.py | 5 +-- tests/utils.py | 6 +-- 18 files changed, 121 insertions(+), 137 deletions(-) diff --git a/bbconf/__init__.py b/bbconf/__init__.py index f5de3d37..c225ce3c 100644 --- a/bbconf/__init__.py +++ b/bbconf/__init__.py @@ -1,9 +1,11 @@ import logging + import coloredlogs +from bbconf.bbagent import BedBaseAgent + from ._version import __version__ from .const import PKG_NAME -from bbconf.bbagent import BedBaseAgent __all__ = ["BedBaseAgent", "__version__"] diff --git a/bbconf/bbagent.py b/bbconf/bbagent.py index dc9ee188..ec847e21 100644 --- a/bbconf/bbagent.py +++ b/bbconf/bbagent.py @@ -2,15 +2,14 @@ from typing import Union from sqlalchemy.orm import Session -from sqlalchemy.sql import select, func, distinct +from sqlalchemy.sql import distinct, func, select from bbconf.config_parser.bedbaseconfig import BedBaseConfig from bbconf.db_utils import Bed, BedSets - +from bbconf.models.base_models import StatsReturn from bbconf.modules.bedfiles import BedAgentBedFile from bbconf.modules.bedsets import BedAgentBedSet from bbconf.modules.objects import BBObjects -from bbconf.models.base_models import StatsReturn class BedBaseAgent(object): diff --git a/bbconf/config_parser/bedbaseconfig.py b/bbconf/config_parser/bedbaseconfig.py index 833cfb60..817be7c7 100644 --- a/bbconf/config_parser/bedbaseconfig.py +++ b/bbconf/config_parser/bedbaseconfig.py @@ -1,49 +1,47 @@ -from pathlib import Path -from typing import Union, List -import yacman import logging -from geniml.search import QdrantBackend +import os +import warnings +from pathlib import Path +from typing import List, Literal, Union + +import boto3 import qdrant_client -from geniml.text2bednn import text2bednn +import yacman +from botocore.exceptions import EndpointConnectionError # from geniml.search import BED2BEDSearchInterface from fastembed.embedding import FlagEmbedding from geniml.region2vec import Region2VecExModel -import warnings -import os - +from geniml.search import QdrantBackend +from geniml.text2bednn import text2bednn from pephubclient import PEPHubClient -import boto3 -from botocore.exceptions import EndpointConnectionError -from bbconf.db_utils import BaseEngine -from bbconf.const import ( - PKG_NAME, -) -from bbconf.models.bed_models import BedFiles, BedPlots -from bbconf.models.bedset_models import BedSetPlots -from bbconf.models.base_models import FileModel -from bbconf.helpers import get_bedbase_cfg, get_absolute_path -from bbconf.config_parser.models import ConfigFile from bbconf.config_parser.const import ( + S3_BEDSET_PATH_FOLDER, S3_FILE_PATH_FOLDER, S3_PLOTS_PATH_FOLDER, - S3_BEDSET_PATH_FOLDER, ) +from bbconf.config_parser.models import ConfigFile +from bbconf.const import ( + PKG_NAME, +) +from bbconf.db_utils import BaseEngine from bbconf.exceptions import ( - BedbaseS3ConnectionError, - BedBaseConfError, BadAccessMethodError, + BedBaseConfError, + BedbaseS3ConnectionError, ) +from bbconf.helpers import get_absolute_path, get_bedbase_cfg +from bbconf.models.base_models import FileModel +from bbconf.models.bed_models import BedFiles, BedPlots +from bbconf.models.bedset_models import BedSetPlots from bbconf.models.drs_models import AccessMethod, AccessURL - _LOGGER = logging.getLogger(PKG_NAME) class BedBaseConfig: def __init__(self, config: Union[Path, str]): - self.cfg_path = get_bedbase_cfg(config) self._config = self._read_config_file(self.cfg_path) @@ -148,7 +146,7 @@ def _init_db_engine(self) -> BaseEngine: database=self._config.database.database, user=self._config.database.user, password=self._config.database.password, - drivername="postgresql+psycopg", + drivername=f"{self._config.database.dialect}+{self._config.database.driver}", ) def _init_qdrant_backend(self) -> QdrantBackend: @@ -277,7 +275,7 @@ def upload_files_s3( identifier: str, files: Union[BedFiles, BedPlots, BedSetPlots], base_path: str, - type: str = "files", + type: Literal["files", "plots", "bedsets"] = "files", ) -> Union[BedFiles, BedPlots, BedSetPlots]: """ Upload files to s3. @@ -297,7 +295,7 @@ def upload_files_s3( s3_output_base_folder = S3_BEDSET_PATH_FOLDER else: raise BedBaseConfError( -f"Invalid type: {type}. Should be 'files', 'plots', or 'bedsets'" + f"Invalid type: {type}. Should be 'files', 'plots', or 'bedsets'" ) for key, value in files: @@ -346,10 +344,11 @@ def delete_s3(self, s3_path: str) -> None: "Could not delete file from s3. Connection error." ) try: + _LOGGER.info(f"Deleting file from s3: {s3_path}") return self._boto3_client.delete_object( Bucket=self.config.s3.bucket, Key=s3_path ) - except EndpointConnectionError as e: + except EndpointConnectionError: raise BedbaseS3ConnectionError( "Could not delete file from s3. Connection error." ) diff --git a/bbconf/config_parser/models.py b/bbconf/config_parser/models.py index dcfd1912..6f2c2569 100644 --- a/bbconf/config_parser/models.py +++ b/bbconf/config_parser/models.py @@ -1,22 +1,23 @@ from typing import Optional, Union + from pydantic import BaseModel, ConfigDict from bbconf.config_parser.const import ( - DEFAULT_VEC2VEC_MODEL, - DEFAULT_TEXT2VEC_MODEL, - DEFAULT_REGION2_VEC_MODEL, DEFAULT_DB_DIALECT, - DEFAULT_DB_NAME, DEFAULT_DB_DRIVER, - DEFAULT_QDRANT_COLLECTION_NAME, + DEFAULT_DB_NAME, DEFAULT_DB_PORT, - DEFAULT_QDRANT_PORT, - DEFAULT_SERVER_HOST, - DEFAULT_SERVER_PORT, - DEFAULT_PEPHUB_NAMESPACE, DEFAULT_PEPHUB_NAME, + DEFAULT_PEPHUB_NAMESPACE, DEFAULT_PEPHUB_TAG, + DEFAULT_QDRANT_COLLECTION_NAME, + DEFAULT_QDRANT_PORT, + DEFAULT_REGION2_VEC_MODEL, DEFAULT_S3_BUCKET, + DEFAULT_SERVER_HOST, + DEFAULT_SERVER_PORT, + DEFAULT_TEXT2VEC_MODEL, + DEFAULT_VEC2VEC_MODEL, ) diff --git a/bbconf/db_utils.py b/bbconf/db_utils.py index 887a56b4..f08e5b32 100644 --- a/bbconf/db_utils.py +++ b/bbconf/db_utils.py @@ -1,18 +1,18 @@ import datetime import logging -from typing import Optional, List +from typing import List, Optional from sqlalchemy import ( + TIMESTAMP, BigInteger, + ForeignKey, Result, Select, event, select, - TIMESTAMP, - ForeignKey, ) from sqlalchemy.dialects.postgresql import JSON -from sqlalchemy.engine import URL, create_engine, Engine +from sqlalchemy.engine import URL, Engine, create_engine from sqlalchemy.exc import ProgrammingError from sqlalchemy.ext.compiler import compiles from sqlalchemy.orm import ( @@ -26,7 +26,6 @@ from bbconf.const import PKG_NAME - _LOGGER = logging.getLogger(PKG_NAME) @@ -74,7 +73,6 @@ def deliver_update_date(context): class Bed(Base): - __tablename__ = "bed" id: Mapped[str] = mapped_column(primary_key=True, index=True) diff --git a/bbconf/helpers.py b/bbconf/helpers.py index 1fa119b9..47fe67c3 100644 --- a/bbconf/helpers.py +++ b/bbconf/helpers.py @@ -1,7 +1,8 @@ import logging -from yacman import select_config import os +from yacman import select_config + from bbconf.exceptions import BedBaseConnectionError _LOGGER = logging.getLogger(__name__) diff --git a/bbconf/models/base_models.py b/bbconf/models/base_models.py index cfd37c70..91e4e5d6 100644 --- a/bbconf/models/base_models.py +++ b/bbconf/models/base_models.py @@ -1,5 +1,6 @@ +from typing import List, Optional, Union + from pydantic import BaseModel, ConfigDict, Field -from typing import Optional, Union, List from .drs_models import AccessMethod diff --git a/bbconf/models/bed_models.py b/bbconf/models/bed_models.py index a7251b67..0c2954df 100644 --- a/bbconf/models/bed_models.py +++ b/bbconf/models/bed_models.py @@ -1,9 +1,8 @@ import datetime -from typing import Optional, Union, List +from typing import List, Optional, Union from pydantic import BaseModel, ConfigDict, Field - from .base_models import FileModel diff --git a/bbconf/models/bedset_models.py b/bbconf/models/bedset_models.py index c6523939..20175429 100644 --- a/bbconf/models/bedset_models.py +++ b/bbconf/models/bedset_models.py @@ -1,8 +1,9 @@ -from pydantic import BaseModel, ConfigDict from typing import List, Union -from .bed_models import BedStatsModel, BedMetadata +from pydantic import BaseModel, ConfigDict + from .base_models import FileModel +from .bed_models import BedMetadata, BedStatsModel class BedSetStats(BaseModel): diff --git a/bbconf/models/drs_models.py b/bbconf/models/drs_models.py index ea85c1cd..01435a56 100644 --- a/bbconf/models/drs_models.py +++ b/bbconf/models/drs_models.py @@ -1,5 +1,6 @@ import datetime -from typing import Optional, List, Union +from typing import List, Optional, Union + from pydantic import BaseModel diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index a9845d71..0291c3f3 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -1,39 +1,36 @@ from logging import getLogger from typing import Dict, Union -import numpy as np -from geniml.io import RegionSet +import numpy as np from geniml.bbclient import BBClient +from geniml.io import RegionSet from pephubclient.exceptions import ResponseError - -from qdrant_client.models import PointIdsList, VectorParams, Distance - -from sqlalchemy.orm import Session +from qdrant_client.models import Distance, PointIdsList, VectorParams from sqlalchemy import select +from sqlalchemy.orm import Session - +from bbconf.config_parser.bedbaseconfig import BedBaseConfig from bbconf.const import ( PKG_NAME, ) +from bbconf.db_utils import Bed, BedStats, Files +from bbconf.exceptions import ( + BedBaseConfError, + BedFIleExistsError, + BEDFileNotFoundError, +) from bbconf.models.bed_models import ( - BedMetadata, - BedFiles, - FileModel, - BedPlots, BedClassification, - BedStatsModel, - BedPEPHub, + BedFiles, BedListResult, BedListSearchResult, + BedMetadata, + BedPEPHub, + BedPlots, + BedStatsModel, + FileModel, QdrantSearchResult, ) -from bbconf.exceptions import ( - BedBaseConfError, - BEDFileNotFoundError, - BedFIleExistsError, -) -from bbconf.db_utils import Bed, Files, BedStats -from bbconf.config_parser.bedbaseconfig import BedBaseConfig _LOGGER = getLogger(PKG_NAME) @@ -93,17 +90,19 @@ def get(self, identifier: str, full: bool = False) -> BedMetadata: ) # FILES elif result.name in BedFiles.model_fields: - setattr( - bed_files, - result.name, - FileModel( - **result.__dict__, - object_id=f"bed.{identifier}.{result.name}", - access_methods=self._config.construct_access_method_list( - result.path + ( + setattr( + bed_files, + result.name, + FileModel( + **result.__dict__, + object_id=f"bed.{identifier}.{result.name}", + access_methods=self._config.construct_access_method_list( + result.path + ), ), ), - ), + ) else: _LOGGER.error( diff --git a/bbconf/modules/bedsets.py b/bbconf/modules/bedsets.py index 9773ee1b..c6470d21 100644 --- a/bbconf/modules/bedsets.py +++ b/bbconf/modules/bedsets.py @@ -1,29 +1,27 @@ -from typing import List, Dict import logging -from sqlalchemy import select, func, Numeric, Float, or_ -from sqlalchemy.orm import Session - # TODO: will be available in the next geniml release # from geniml.io.utils import compute_md5sum_bedset from hashlib import md5 +from typing import Dict, List -from bbconf.config_parser import BedBaseConfig -from bbconf.db_utils import BedFileBedSetRelation, BedSets, Files, BedStats +from sqlalchemy import Float, Numeric, func, or_, select +from sqlalchemy.orm import Session +from bbconf.config_parser import BedBaseConfig +from bbconf.const import PKG_NAME +from bbconf.db_utils import BedFileBedSetRelation, BedSets, BedStats, Files +from bbconf.exceptions import BEDFileNotFoundError, BedSetNotFoundError from bbconf.models.bed_models import BedStatsModel from bbconf.models.bedset_models import ( - BedSetStats, - BedSetMetadata, - BedSetListResult, - FileModel, BedSetBedFiles, + BedSetListResult, + BedSetMetadata, BedSetPlots, + BedSetStats, + FileModel, ) from bbconf.modules.bedfiles import BedAgentBedFile -from bbconf.const import PKG_NAME -from bbconf.exceptions import BedSetNotFoundError, BEDFileNotFoundError - _LOGGER = logging.getLogger(PKG_NAME) diff --git a/bbconf/modules/objects.py b/bbconf/modules/objects.py index d39b2f78..19054cfe 100644 --- a/bbconf/modules/objects.py +++ b/bbconf/modules/objects.py @@ -1,20 +1,18 @@ +import datetime import logging -from typing import List, Union, Literal +from typing import List, Literal, Union -from bbconf.modules.bedfiles import BedAgentBedFile -from bbconf.modules.bedsets import BedAgentBedSet from bbconf.config_parser.bedbaseconfig import BedBaseConfig from bbconf.const import PKG_NAME from bbconf.exceptions import ( - MissingThumbnailError, - MissingObjectError, BedBaseConfError, + MissingObjectError, + MissingThumbnailError, ) - -import datetime -from bbconf.models.drs_models import AccessMethod, AccessURL, DRSModel from bbconf.models.bed_models import FileModel - +from bbconf.models.drs_models import DRSModel +from bbconf.modules.bedfiles import BedAgentBedFile +from bbconf.modules.bedsets import BedAgentBedSet _LOGGER = logging.getLogger(PKG_NAME) diff --git a/tests/conftest.py b/tests/conftest.py index 47a11854..1ef4a853 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,7 +1,8 @@ import os + import pytest + from bbconf.bbagent import BedBaseAgent -from unittest.mock import patch from .utils import BED_TEST_ID @@ -100,7 +101,7 @@ def example_dict(): @pytest.fixture def load_test_data(): - db_engine = get_bbagent().config.db_engine() + get_bbagent().config.db_engine() @pytest.fixture() diff --git a/tests/test_bedfile.py b/tests/test_bedfile.py index a887fb09..b01b4175 100644 --- a/tests/test_bedfile.py +++ b/tests/test_bedfile.py @@ -1,17 +1,13 @@ -from bbconf.bbagent import BedBaseAgent -from bbconf.exceptions import BedFIleExistsError, BEDFileNotFoundError -from bbconf.db_utils import Bed, Files - +import pytest from sqlalchemy.orm import Session from sqlalchemy.sql import select -from unittest.mock import Mock -import pytest +from bbconf.bbagent import BedBaseAgent +from bbconf.db_utils import Bed, Files +from bbconf.exceptions import BedFIleExistsError, BEDFileNotFoundError -from .utils import ContextManagerDBTesting from .conftest import get_bbagent - -from .utils import BED_TEST_ID +from .utils import BED_TEST_ID, ContextManagerDBTesting def test_bb_database(): @@ -20,7 +16,6 @@ def test_bb_database(): class Test_BedFile_Agent: - def test_upload(self, bbagent_obj, example_dict, mocker): upload_s3_mock = mocker.patch( "bbconf.config_parser.bedbaseconfig.BedBaseConfig.upload_s3", @@ -33,7 +28,7 @@ def test_upload(self, bbagent_obj, example_dict, mocker): assert bbagent_obj.bed.exists(example_dict["identifier"]) def test_upload_exists(self, bbagent_obj, example_dict, mocker): - upload_s3_mock = mocker.patch( + mocker.patch( "bbconf.config_parser.bedbaseconfig.BedBaseConfig.upload_s3", return_value=True, ) @@ -43,7 +38,7 @@ def test_upload_exists(self, bbagent_obj, example_dict, mocker): bbagent_obj.bed.add(**example_dict) def test_add_nofail(self, bbagent_obj, example_dict, mocker): - upload_s3_mock = mocker.patch( + mocker.patch( "bbconf.config_parser.bedbaseconfig.BedBaseConfig.upload_s3", return_value=True, ) @@ -216,7 +211,6 @@ def test_bed_update(self): @pytest.mark.skip("Skipped, because ML models and qdrant needed") class TestVectorSearch: - def test_qdrant_search(self, bbagent_obj, mocker): mocker.patch( "geniml.text2bednn.text2bednn.Text2BEDSearchInterface.nl_vec_search", diff --git a/tests/test_bedset.py b/tests/test_bedset.py index f4b80a45..492c5292 100644 --- a/tests/test_bedset.py +++ b/tests/test_bedset.py @@ -1,22 +1,17 @@ -from bbconf.exceptions import BedSetNotFoundError, BedbaseS3ConnectionError -from bbconf.db_utils import BedSets -from bbconf.models.base_models import FileModel - import os +import pytest from sqlalchemy.orm import Session from sqlalchemy.sql import select -import pytest - -from .utils import ContextManagerDBTesting +from bbconf.db_utils import BedSets +from bbconf.exceptions import BedbaseS3ConnectionError, BedSetNotFoundError -from .utils import BED_TEST_ID, BEDSET_TEST_ID from .conftest import DATA_PATH +from .utils import BED_TEST_ID, BEDSET_TEST_ID, ContextManagerDBTesting class TestBedset: - def test_calculate_stats(self, bbagent_obj): with ContextManagerDBTesting(config=bbagent_obj.config, add_data=True): results = bbagent_obj.bedset._calculate_statistics([BED_TEST_ID]) @@ -29,7 +24,7 @@ def test_crate_bedset_all(self, bbagent_obj, mocker): with ContextManagerDBTesting( config=bbagent_obj.config, add_data=True, bedset=False ): - upload_s3_mock = mocker.patch( + mocker.patch( "bbconf.config_parser.bedbaseconfig.BedBaseConfig.upload_s3", return_value=True, ) diff --git a/tests/test_objects.py b/tests/test_objects.py index 7f843258..635b0f03 100644 --- a/tests/test_objects.py +++ b/tests/test_objects.py @@ -1,9 +1,8 @@ -from bbconf.exceptions import BEDFileNotFoundError, MissingThumbnailError import pytest -from .utils import ContextManagerDBTesting +from bbconf.exceptions import BEDFileNotFoundError, MissingThumbnailError -from .utils import BED_TEST_ID +from .utils import BED_TEST_ID, ContextManagerDBTesting class TestObjects: diff --git a/tests/utils.py b/tests/utils.py index 55e54b2a..9566ebdb 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,9 +1,9 @@ -from bbconf.config_parser.bedbaseconfig import BedBaseConfig -from bbconf.db_utils import Bed, Files, BedSets, BedFileBedSetRelation, BedStats from typing import Union from sqlalchemy.orm import Session +from bbconf.config_parser.bedbaseconfig import BedBaseConfig +from bbconf.db_utils import Bed, BedFileBedSetRelation, BedSets, BedStats, Files BED_TEST_ID = "bbad85f21962bb8d972444f7f9a3a932" BEDSET_TEST_ID = "test_bedset_id" @@ -100,7 +100,6 @@ def __init__( self.bedset = bedset def __enter__(self): - self.db_engine = self.config.db_engine if self.add_data: @@ -113,7 +112,6 @@ def __exit__(self, exc_type, exc_value, exc_traceback): def _add_data(self): with Session(self.db_engine.engine) as session: - new_bed = Bed(**get_example_dict()) new_files = Files(**get_files()) new_plots = Files(**get_plots()) From fba9758df2ae347a3d60c54c247954a29cef56a3 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Wed, 3 Apr 2024 22:06:43 +0200 Subject: [PATCH 55/61] fixed naming --- bbconf/models/bed_models.py | 4 ++-- bbconf/modules/bedfiles.py | 1 - bbconf/modules/bedsets.py | 7 ++----- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/bbconf/models/bed_models.py b/bbconf/models/bed_models.py index 0c2954df..b0a646af 100644 --- a/bbconf/models/bed_models.py +++ b/bbconf/models/bed_models.py @@ -20,8 +20,8 @@ class BedPlots(BaseModel): class BedFiles(BaseModel): - bed_file: Union[FileModel, None] = Field(None, alias="bedfile") - bigbed_file: Union[FileModel, None] = Field(None, alias="bigbedfile") + bed_file: Union[FileModel, None] = None + bigbed_file: Union[FileModel, None] = None model_config = ConfigDict( populate_by_name=True, diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index 0291c3f3..759750fd 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -35,7 +35,6 @@ _LOGGER = getLogger(PKG_NAME) QDRANT_GENOME = "hg38" -ACCESS_ID = "http" class BedAgentBedFile: diff --git a/bbconf/modules/bedsets.py b/bbconf/modules/bedsets.py index c6470d21..ffa80aad 100644 --- a/bbconf/modules/bedsets.py +++ b/bbconf/modules/bedsets.py @@ -25,8 +25,6 @@ _LOGGER = logging.getLogger(PKG_NAME) -ACCESS_ID = "http" - class BedAgentBedSet: """ @@ -107,9 +105,8 @@ def get_plots(self, identifier: str) -> BedSetPlots: FileModel( **result.__dict__, object_id=f"bed.{identifier}.{result.name}", - uri=self.config.get_prefixed_uri( - result.path, - access_id=ACCESS_ID, + access_methods=self.config.construct_access_method_list( + result.path ), ), ) From e24f1632a4c47c45b0a68020f292b26371b3fd41 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Thu, 4 Apr 2024 03:34:04 +0200 Subject: [PATCH 56/61] added geniml search bed-bed --- bbconf/config_parser/bedbaseconfig.py | 90 +++++++++++++++------------ bbconf/modules/bedfiles.py | 40 ++++++------ 2 files changed, 72 insertions(+), 58 deletions(-) diff --git a/bbconf/config_parser/bedbaseconfig.py b/bbconf/config_parser/bedbaseconfig.py index 817be7c7..8f00ac57 100644 --- a/bbconf/config_parser/bedbaseconfig.py +++ b/bbconf/config_parser/bedbaseconfig.py @@ -9,11 +9,10 @@ import yacman from botocore.exceptions import EndpointConnectionError -# from geniml.search import BED2BEDSearchInterface -from fastembed.embedding import FlagEmbedding +from geniml.search import QdrantBackend, BED2BEDSearchInterface, Text2BEDSearchInterface +from geniml.search.query2vec import BED2Vec, Text2Vec from geniml.region2vec import Region2VecExModel -from geniml.search import QdrantBackend -from geniml.text2bednn import text2bednn + from pephubclient import PEPHubClient from bbconf.config_parser.const import ( @@ -48,7 +47,8 @@ def __init__(self, config: Union[Path, str]): self._db_engine = self._init_db_engine() self._qdrant_engine = self._init_qdrant_backend() self._t2bsi = self._init_t2bsi_object() - self._r2v = self._init_r2v_object() + self._b2bsi = self._init_b2bsi_object() + # self._r2v = self._init_r2v_object() self._phc = self._init_pephubclient() self._boto3_client = self._init_boto3_client() @@ -95,7 +95,7 @@ def db_engine(self) -> BaseEngine: return self._db_engine @property - def t2bsi(self) -> Union[text2bednn.Text2BEDSearchInterface, None]: + def t2bsi(self) -> Union[Text2BEDSearchInterface, None]: """ Get text2bednn object @@ -104,13 +104,23 @@ def t2bsi(self) -> Union[text2bednn.Text2BEDSearchInterface, None]: return self._t2bsi @property - def r2v(self) -> Region2VecExModel: + def b2bsi(self) -> Union[BED2BEDSearchInterface, None]: """ - Get region2vec object + Get bed2bednn object - :return: region2vec object + :return: bed2bednn object """ - return self._r2v + return self._b2bsi + + # + # @property + # def r2v(self) -> Region2VecExModel: + # """ + # Get region2vec object + # + # :return: region2vec object + # """ + # return self._r2v @property def qdrant_engine(self) -> QdrantBackend: @@ -168,7 +178,7 @@ def _init_qdrant_backend(self) -> QdrantBackend: f"error in Connection to qdrant! skipping... Error: {err}", UserWarning ) - def _init_t2bsi_object(self) -> Union[text2bednn.Text2BEDSearchInterface, None]: + def _init_t2bsi_object(self) -> Union[Text2BEDSearchInterface, None]: """ Create Text 2 BED search interface and return this object @@ -176,10 +186,12 @@ def _init_t2bsi_object(self) -> Union[text2bednn.Text2BEDSearchInterface, None]: """ try: - return text2bednn.Text2BEDSearchInterface( - nl2vec_model=FlagEmbedding(model_name=self._config.path.text2vec), - vec2vec_model=self._config.path.vec2vec, - search_backend=self.qdrant_engine, + return Text2BEDSearchInterface( + backend=self.qdrant_engine, + query2vec=Text2Vec( + text_embedder=self._config.path.text2vec, + v2v=self._config.path.vec2vec, + ), ) except Exception as e: _LOGGER.error("Error in creating Text2BEDSearchInterface object: " + str(e)) @@ -189,26 +201,24 @@ def _init_t2bsi_object(self) -> Union[text2bednn.Text2BEDSearchInterface, None]: ) return None - # def _init_b2bsi_object(self) -> Union[text2bednn.BED2BEDSearchInterface, None]: - # """ - # Create Bed 2 BED search interface and return this object - # - # :return: Bed2BEDSearchInterface object - # TODO: work in progress - # """ - # - # try: - # return text2bednn.BED2BEDSearchInterface( - # bed2vec_model=self._config.path.bed2vec, - # search_backend=self.qdrant_engine, - # ) - # except Exception as e: - # _LOGGER.error("Error in creating Bed2BEDSearchInterface object: " + str(e)) - # warnings.warn( - # "Error in creating Bed2BEDSearchInterface object: " + str(e), - # UserWarning, - # ) - # return None + def _init_b2bsi_object(self) -> Union[BED2BEDSearchInterface, None]: + """ + Create Bed 2 BED search interface and return this object + + :return: Bed2BEDSearchInterface object + """ + try: + return BED2BEDSearchInterface( + backend=self.qdrant_engine, + query2vec=BED2Vec(model=self._config.path.region2vec), + ) + except Exception as e: + _LOGGER.error("Error in creating BED2BEDSearchInterface object: " + str(e)) + warnings.warn( + "Error in creating BED2BEDSearchInterface object: " + str(e), + UserWarning, + ) + return None @staticmethod def _init_pephubclient() -> Union[PEPHubClient, None]: @@ -244,11 +254,11 @@ def _init_boto3_client( warnings.warn(f"Error in creating boto3 client object: {e}", UserWarning) return None - def _init_r2v_object(self) -> Region2VecExModel: - """ - Create Region2VecExModel object using credentials provided in config file - """ - return Region2VecExModel(self.config.path.region2vec) + # def _init_r2v_object(self) -> Region2VecExModel: + # """ + # Create Region2VecExModel object using credentials provided in config file + # """ + # return Region2VecExModel(self.config.path.region2vec) def upload_s3(self, file_path: str, s3_path: Union[Path, str]) -> None: """ diff --git a/bbconf/modules/bedfiles.py b/bbconf/modules/bedfiles.py index 759750fd..31e7e117 100644 --- a/bbconf/modules/bedfiles.py +++ b/bbconf/modules/bedfiles.py @@ -670,7 +670,7 @@ def text_to_bed_search( _LOGGER.info(f"Looking for: {query}") _LOGGER.info(f"Using backend: {self._config.t2bsi}") - results = self._config.t2bsi.nl_vec_search(query, limit=limit, offset=offset) + results = self._config.t2bsi.query_search(query, limit=limit, offset=offset) results_list = [] for result in results: result_id = result["id"].replace("-", "") @@ -693,23 +693,27 @@ def bed_to_bed_search( limit: int = 10, offset: int = 0, ) -> BedListSearchResult: - # # results = self._config.b2bsi.(query, limit=limit, offset=offset) - # results_list = [] - # for result in results: - # result_id = result["id"].replace("-", "") - # try: - # result_meta = self.get(result_id) - # except BEDFileNotFoundError as e: - # _LOGGER.warning( - # f"Could not retrieve metadata for bed file: {result_id}. Error: {e}" - # ) - # continue - # if result_meta: - # results_list.append(QdrantSearchResult(**result, metadata=result_meta)) - # return BedListSearchResult( - # count=0, limit=limit, offset=offset, results=[] - # ) - raise NotImplementedError + results = self._config.b2bsi.query_search( + region_set, limit=limit, offset=offset + ) + results_list = [] + for result in results: + result_id = result["id"].replace("-", "") + try: + result_meta = self.get(result_id) + except BEDFileNotFoundError as e: + _LOGGER.warning( + f"Could not retrieve metadata for bed file: {result_id}. Error: {e}" + ) + continue + if result_meta: + results_list.append(QdrantSearchResult(**result, metadata=result_meta)) + return BedListSearchResult( + count=len(results_list), + limit=limit, + offset=offset, + results=results_list, + ) def reindex_qdrant(self) -> None: """ From 2e36a727562bde558b3b9c445349b066ab00ab39 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Thu, 4 Apr 2024 17:53:04 +0200 Subject: [PATCH 57/61] updated requirements --- requirements/requirements-all.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/requirements-all.txt b/requirements/requirements-all.txt index c6c7aaaa..af05779d 100644 --- a/requirements/requirements-all.txt +++ b/requirements/requirements-all.txt @@ -1,6 +1,6 @@ yacman >= 0.9.1 sqlalchemy >= 2.0.0 -geniml >= 0.2.0 +geniml >= 0.3.0 psycopg >= 3.1.15 colorlogs pydantic >= 2.6.4 From ec2c948a284b946d3bc797458e9ff3bac69de899 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Thu, 4 Apr 2024 19:52:44 +0200 Subject: [PATCH 58/61] fixed region to vec --- bbconf/config_parser/bedbaseconfig.py | 30 +++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/bbconf/config_parser/bedbaseconfig.py b/bbconf/config_parser/bedbaseconfig.py index 8f00ac57..46fcad7b 100644 --- a/bbconf/config_parser/bedbaseconfig.py +++ b/bbconf/config_parser/bedbaseconfig.py @@ -48,7 +48,7 @@ def __init__(self, config: Union[Path, str]): self._qdrant_engine = self._init_qdrant_backend() self._t2bsi = self._init_t2bsi_object() self._b2bsi = self._init_b2bsi_object() - # self._r2v = self._init_r2v_object() + self._r2v = self._init_r2v_object() self._phc = self._init_pephubclient() self._boto3_client = self._init_boto3_client() @@ -112,15 +112,15 @@ def b2bsi(self) -> Union[BED2BEDSearchInterface, None]: """ return self._b2bsi - # - # @property - # def r2v(self) -> Region2VecExModel: - # """ - # Get region2vec object - # - # :return: region2vec object - # """ - # return self._r2v + + @property + def r2v(self) -> Region2VecExModel: + """ + Get region2vec object + + :return: region2vec object + """ + return self._r2v @property def qdrant_engine(self) -> QdrantBackend: @@ -254,11 +254,11 @@ def _init_boto3_client( warnings.warn(f"Error in creating boto3 client object: {e}", UserWarning) return None - # def _init_r2v_object(self) -> Region2VecExModel: - # """ - # Create Region2VecExModel object using credentials provided in config file - # """ - # return Region2VecExModel(self.config.path.region2vec) + def _init_r2v_object(self) -> Region2VecExModel: + """ + Create Region2VecExModel object using credentials provided in config file + """ + return Region2VecExModel(self.config.path.region2vec) def upload_s3(self, file_path: str, s3_path: Union[Path, str]) -> None: """ From 9c5eb0f2ced82b0688a636858a2c97e759d567f6 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Mon, 8 Apr 2024 18:49:18 +0200 Subject: [PATCH 59/61] fixed readme and version --- README.md | 2 +- bbconf/_version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a7076339..4ff58b7e 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ ## What is this? `bbconf` is a configuration and management tool for BEDbase, facilitating the reading of configuration files, -setting up connections to PostgreSQL and Qdrant databases, managing file paths, and storing transformer models. +setting up connections to PostgreSQL, PEPhub, S3, and Qdrant databases, managing file paths, and storing transformer models. It formalizes communication pathways for pipelines and downstream tools, ensuring seamless interaction." --- diff --git a/bbconf/_version.py b/bbconf/_version.py index c6422df7..3d187266 100644 --- a/bbconf/_version.py +++ b/bbconf/_version.py @@ -1 +1 @@ -__version__ = "0.6.0a1" +__version__ = "0.5.0" From d61ebacebf01ccc8a72b94d2d4eb1049dd3a1d8c Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Mon, 8 Apr 2024 18:49:44 +0200 Subject: [PATCH 60/61] lint --- bbconf/config_parser/bedbaseconfig.py | 1 - 1 file changed, 1 deletion(-) diff --git a/bbconf/config_parser/bedbaseconfig.py b/bbconf/config_parser/bedbaseconfig.py index 46fcad7b..92fc08fd 100644 --- a/bbconf/config_parser/bedbaseconfig.py +++ b/bbconf/config_parser/bedbaseconfig.py @@ -112,7 +112,6 @@ def b2bsi(self) -> Union[BED2BEDSearchInterface, None]: """ return self._b2bsi - @property def r2v(self) -> Region2VecExModel: """ From c75d00665d8402d51cc228f87b6c669fe689af61 Mon Sep 17 00:00:00 2001 From: Khoroshevskyi Date: Mon, 8 Apr 2024 19:06:56 +0200 Subject: [PATCH 61/61] added changelog --- docs/changelog.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/changelog.md b/docs/changelog.md index a65d5bd1..bf97d730 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -2,10 +2,15 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) and [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) format. -# [0.5.0] - 2024-XX-XX -### Added +# [0.5.0] - 2024-04-08 +### Changed -- pydantic schema for bedfile and bedset table +- Rebuild bbconf +- Introduced new DB schema +- Added bbagent that will be used to interact with the database +- Updated config schema +- Added new functionality to the bbagent +- New tests ## [0.4.2] - 2024-03-12

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⋙tps?*_o30NK zjw>X#to?>%c0ZW%_R_w$Cz2O$;a1f|jq+@%nA61y{^43*_S||4L&ahUbiOHBqg{dUr&}$pv)<)=Lh(p&KZ0b2PGt z%Iv#XP@2bBS{GS0GKHd2({t0(>W42Ya4z{$5#h+%$rcs+OfNoHKA_>eSmgZZAK7Dz zHgFSg0_ofUUio<%r9Rwn;fEv~k7aa>_lstRR+@)8I^I44`IuTK6~gcA@~JSkW@#Z~ zfdc0}HCr}qpUF^Z@E}E^4a~Ji!RdAFH9Jrcn-*xtY%@sV|6-j+71^VQgi&3R4h-U7 zI_~$f!9{xg0_~U~io(Ya#hHiC0pX&PdkEx<6h0!bGH2hbh`s2o#5e@nU7@tFxCWNl zTlfZj6A+Kdbrkq5dv!C@gAPS9i~5(egbI#RyA5KQpic+`2=wCt=?b?f3~^ldhj}u? z;Yj`i;-4>BX6$QOOLvo=)?4{@RY5| z99UI611&Yom^I}`?bB@;;EwedQ)vSIqUc8Tzs}#)Qp&6z2w#YbelS7XrdP8Xcf|nb z%{&@64~3lw6$>a)*rx!cCGvjTRdj?95q=bC$8=a*l|5PpgB_W`p%699J}i-^(pc7` zS}IHICQyzgW-2b(-*Qw>?HH*`{C5X9R{`co)s&Fo`aa|C`2%@?VnXGtL7vYIG+`+ z^3eQ{Y<*_py8RZ3WLqE~Gc_yHL|>1(&qRyVEU+sBoX?&!?q#>kWOQ5HIbu|&7{%7_ zO%~v8ZDPwQt9|4G{UX~Ek^Iwf<=MoA_fdm@_s68}itAuVQ&id)%Gcy}R3b(Rxv7R5 zo@JXyNOXX75ywy+_~fNNLhv13W~z|_>Ee@>O8N8_h{Gk&Zdch7C8!3X96wQ8hsJ@r zwm?6oYE~w>LmgdktWjm5);&#le&e9lR$QxM97L=EP*M4GRWt(ld{H~`srnXz+-G;VDuM&S{i16Y`I9;4D`f83e8T+(o7@=VGN zom_~FkMLG+G(HHS0PUh?jXA~ehUKbZC?eDTC(=+p?e%N-wJbV)ULb{IYHC%OKbjGZ zAeF?9W<*B9j%Ea7COepE%$)ZDsy{Z>tWE>E|GUIk*RvL<_Mt#Jrs-6)626}`uVtGj z4HAg{qKJ!3xqlkcnIRi$UUm(t=WmCf-AwDKpcKdXEKrYys4CUcAg?@~46_eiiyOm$ zBwc;W@OCU$=%WhA7UgtV|D1~%{omAeE+#~uITzK2-*H7}a@M|Qfp|RKS>aK|TxSy` z!mo;%mu+!P3}Vr|+*0ik?O@_O?wU*)pOo-jbZxZWv8d=}h#Sj#r$4g&F*uwM~L{Z=4Zsb#OYcZ31Xy*w*S zl&W9W9@27mc&8ctsmPGIMU1-G9&L0icRSrMfqL__NJ7nXk^UT^Q&B_Oeqyvy(|a2? z*I=>=8 zpkH#ls{i4eeQrGOq*TFy21B#o?%Fe*-%ZoZrLX2$$!iu~VTO z&No$yKiqo{rvsN^Utr@7)Q$<16~*ijr}K*KPp5%!yYQ+Xyn1w27UjUJJ|cxGr%{xP zo&f%Ag`ZqX z=zV>|zC@%-CdwDhy-sm)T=_97Dao`HordL@V@kV9#A^7kFN7YT0LWr|4#H{ytt{He!eg>5|a^-