From 8935f3d556061ef10a15178a7b9d01432da85361 Mon Sep 17 00:00:00 2001 From: Hannah Beilinson Date: Fri, 10 Oct 2025 22:22:07 -0700 Subject: [PATCH 1/4] Added the capability to run embeddings on files stored in AWS S3 --- package-lock.json | 4 +- src/models/clip/generate_embeddings.py | 91 +++++++++++++++++++++++++- src/models/clip/util.py | 14 ++++ 3 files changed, 105 insertions(+), 4 deletions(-) create mode 100644 src/models/clip/util.py diff --git a/package-lock.json b/package-lock.json index b103052..013fa43 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "digital-collections-explorer", - "version": "0.0.1", + "version": "1.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "digital-collections-explorer", - "version": "0.0.1", + "version": "1.2.0", "dependencies": { "chalk": "^4.1.2" } diff --git a/src/models/clip/generate_embeddings.py b/src/models/clip/generate_embeddings.py index 13ea044..1679bba 100644 --- a/src/models/clip/generate_embeddings.py +++ b/src/models/clip/generate_embeddings.py @@ -10,9 +10,12 @@ from typing import Dict, Any import PyPDF2 import base64 +import argparse + from transformers import CLIPProcessor, CLIPModel from src.backend.core.config import settings +import src.models.clip.util as util logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) @@ -232,9 +235,90 @@ def process_files(model: Any, return ProcessingResult(embeddings, metadata, skipped_items_count, failed_items_count) +def process_remote_files(model: Any, + processor: Any, + device: str, + raw_data_dir: str, + processed_dir: str, + thumbnails_dir: str, + bucket: str, + prefix: str, + timing_info: Dict[str, float]) -> ProcessingResult: + """Process all files in the raw data directory""" + logger.info(f"Looking for files in {bucket}/{prefix}") + + client = util.create_client() + + files = util.get_file_names(client, bucket, prefix) + + supported_extensions = { + 'pdf': ['pdf'], + 'image': ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'tiff', 'webp'] + } + + files_to_process = [] + skipped_items_count = 0 + failed_items_count = 0 + + for file_path in files: + ext = file_path.suffix.lower().lstrip('.') + is_image = ext in supported_extensions['image'] + is_pdf = ext in supported_extensions['pdf'] + + if is_image or is_pdf and settings.collection_type != 'photographs': + files_to_process.append(file_path) + else: + skipped_items_count += 1 + + logger.info(f"Found {len(files_to_process)} eligible files to process.") + + if not files_to_process: + logger.warning(f"No files found in {bucket}") + return ProcessingResult({}, {}, skipped_items_count, failed_items_count) + + embeddings = {} + metadata = {} + + for file_path in files: + try: + ext = file_path.suffix.lower().lstrip('.') + is_image = ext in supported_extensions['image'] + is_pdf = ext in supported_extensions['pdf'] + client.download_file(bucket, f"{prefix}/{file_path}", f"{raw_data_dir}/{file_path}") + if is_pdf: + results = process_pdf(file_path, raw_data_dir, model, processor, device, processed_dir, thumbnails_dir, timing_info) + elif is_image: + results = process_image(file_path, raw_data_dir, model, processor, device, processed_dir, thumbnails_dir, timing_info) + Path.unlink(raw_data_dir + file_path) + + if results: + for item_id, embedding, metadata_item in results: + embeddings[item_id] = embedding + metadata[item_id] = metadata_item + else: + failed_items_count += 1 + except Exception as e: + logger.error(f"Error processing {file_path}: {e}") + failed_items_count += 1 + + return ProcessingResult(embeddings, metadata, skipped_items_count, failed_items_count) + +def parse_args(): + parser = argparse.ArgumentParser() + parser.add_argument("--use_remote", action='store_true', + help="Whether to use a remote set of inputs.") + parser.add_argument("--bucket", type=str, default="", help="The name of the bucket where the images are stored") + parser.add_argument("--prefix", type=str, default="", help="The prefix where the images are stored") + + args = parser.parse_args() + return args.use_remote, args.bucket, args.prefix + def main(): start_time = time.time() + # Get command line arguments + USE_REMOTE, BUCKET, PREFIX = parse_args() + RAW_DATA_DIR = Path(settings.raw_data_dir) EMBEDDINGS_DIR = Path(settings.embeddings_dir) PROCESSED_DIR = Path(settings.processed_data_dir) @@ -257,8 +341,11 @@ def main(): processor = CLIPProcessor.from_pretrained(MODEL_ID) embedding_timing_info = {'total_duration': 0.0} - - result = process_files(model, processor, DEVICE, RAW_DATA_DIR, PROCESSED_DIR, THUMBNAILS_DIR, embedding_timing_info) + + if USE_REMOTE: + result = process_remote_files(model, processor, DEVICE, RAW_DATA_DIR, PROCESSED_DIR, THUMBNAILS_DIR, BUCKET, PREFIX, embedding_timing_info) + else: + result = process_files(model, processor, DEVICE, RAW_DATA_DIR, PROCESSED_DIR, THUMBNAILS_DIR, embedding_timing_info) embeddings_file = EMBEDDINGS_DIR / "embeddings.pt" item_ids_file = EMBEDDINGS_DIR / "item_ids.pt" diff --git a/src/models/clip/util.py b/src/models/clip/util.py new file mode 100644 index 0000000..ce9f145 --- /dev/null +++ b/src/models/clip/util.py @@ -0,0 +1,14 @@ +import boto3 +from typing import Any + +def create_client(): + client = boto3.session.Session(profile_name="default").client('s3') + return client + +def get_file_names( + client: Any, + bucket: str, + prefix: str): + return client.list_objects(Bucket=bucket, Prefix=prefix) + + From b2f8572186369feb8e6ebaf392cad27ed8098032 Mon Sep 17 00:00:00 2001 From: Hannah Beilinson Date: Thu, 16 Oct 2025 18:48:42 -0700 Subject: [PATCH 2/4] Sample download from S3 working through full app --- README.md | 8 ++++ src/backend/api/routes/images.py | 8 ++++ src/backend/main.py | 7 +++ src/backend/utils/helpers.py | 16 +++++++ src/models/clip/generate_embeddings.py | 65 +++++++++++++++++--------- src/models/clip/util.py | 27 ++++++++++- 6 files changed, 106 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index a3f2d5e..cc62333 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,12 @@ python -m src.models.clip.generate_embeddings This will process all images found in `raw_data_dir` and create embeddings in `embeddings_dir` (both set in `config.json`). +If your data is stored in an S3 bucket instead of locally, ensure your default profile has read and list access to your bucket, then run the above command with the following arguments: + +```bash +python -m src.models.clip.generate_embeddings --use-remote --bucket --prefix +``` + ### Step 5: Start the Backend Server ```bash @@ -83,6 +89,8 @@ python -m src.backend.main The API server will start at http://localhost:8000 +If your data is stored in S3, change the REMOTE flag in src.backend.main to True. + ### Customizing the Frontend #### Development Mode diff --git a/src/backend/api/routes/images.py b/src/backend/api/routes/images.py index 594fe1a..9b6ee06 100644 --- a/src/backend/api/routes/images.py +++ b/src/backend/api/routes/images.py @@ -3,7 +3,10 @@ from fastapi import APIRouter, HTTPException, Query from fastapi.responses import FileResponse +import boto3 + from src.backend.services.embedding_service import embedding_service +import src.backend.utils.helpers as helpers router = APIRouter(tags=["images"]) @@ -37,6 +40,11 @@ async def get_image_by_id( and "processed" in doc["metadata"]["paths"] ): path_str = doc["metadata"]["paths"]["processed"] + if doc["metadata"]["remote"]: + s3_client = boto3.session.Session().client('s3') + local_dir = f"{doc['metadata']['processed_dir']}/{path_str}" + helpers.download_file(s3_client, doc["metadata"]["bucket"], path_str, local_dir) + path_str = local_dir else: raise HTTPException( status_code=404, detail="Image path not found in document metadata" diff --git a/src/backend/main.py b/src/backend/main.py index 7826ab4..97d7d3b 100644 --- a/src/backend/main.py +++ b/src/backend/main.py @@ -11,12 +11,15 @@ from .core.config import settings from .services.embedding_service import embedding_service +import os + logging.basicConfig( level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", ) logger = logging.getLogger(__name__) +REMOTE_FILES = False @asynccontextmanager async def lifespan(app): @@ -29,6 +32,10 @@ async def lifespan(app): yield + # Clean up cached files downloaded from S3 + if REMOTE_FILES: + os.system(f'rm -rf {str(settings.processed_data_dir)}/*') + app = FastAPI( title=settings.api_title, diff --git a/src/backend/utils/helpers.py b/src/backend/utils/helpers.py index dcfcb5f..ac777d4 100644 --- a/src/backend/utils/helpers.py +++ b/src/backend/utils/helpers.py @@ -1,6 +1,7 @@ import json import os from pathlib import Path +from typing import Any def load_config(config_path=None): @@ -25,3 +26,18 @@ def load_config(config_path=None): config[key] = str(root_dir / config[key]) return config + +def download_file( + client: Any, + bucket: str, + filename: str, + destination: str): + # Get the directory path (everything except the filename) + directory = os.path.dirname(destination) + + # Create the directory structure if it doesn't exist + # exist_ok=True means no error if directory already exists + if directory: # Only create if there's actually a directory path + os.makedirs(directory, exist_ok=True) + + client.download_file(bucket, filename, destination) diff --git a/src/models/clip/generate_embeddings.py b/src/models/clip/generate_embeddings.py index b02c2a9..39d54e7 100644 --- a/src/models/clip/generate_embeddings.py +++ b/src/models/clip/generate_embeddings.py @@ -70,6 +70,9 @@ def process_pdf( processed_dir, thumbnails_dir, timing_info: Dict[str, float], + use_remote=False, + bucket="", + file="" ): """Process a PDF file and generate embeddings for each page""" try: @@ -112,10 +115,11 @@ def process_pdf( thumbnail_path = pdf_thumbnails_dir / f"{i}.jpg" thumbnail.save(thumbnail_path, "JPEG", quality=80) - processed_image = image.copy() - processed_image.thumbnail((1920, 1920), Image.Resampling.LANCZOS) - processed_image_path = pdf_processed_dir / f"{i}.jpg" - processed_image.save(processed_image_path, "JPEG", quality=90) + if not use_remote: + processed_image = image.copy() + processed_image.thumbnail((1920, 1920), Image.Resampling.LANCZOS) + processed_image_path = pdf_processed_dir / f"{i}.jpg" + processed_image.save(processed_image_path, "JPEG", quality=90) page_embedding = generate_embeddings( model, processor, [image], device, timing_info @@ -151,9 +155,13 @@ def process_pdf( "n_pages": n_pages, "paths": { "original": str(file_path), - "processed": str(pdf_processed_dir / f"{i}.jpg"), + "processed": str(pdf_processed_dir / f"{i}.jpg") + if not use_remote else f"{file}", "thumbnail": str(pdf_thumbnails_dir / f"{i}.jpg"), }, + "remote": use_remote, + "bucket": bucket, + "processed_dir": str(processed_dir) } results.append((item_id, embedding, metadata)) @@ -172,6 +180,9 @@ def process_image( processed_dir, thumbnails_dir, timing_info: Dict[str, float], + use_remote=False, + bucket="", + file="" ): """Process an image file and generate its embedding""" try: @@ -182,14 +193,15 @@ def process_image( thumbnail.thumbnail((400, 400), Image.Resampling.LANCZOS) thumbnail_path = thumbnails_dir / f"{file_path.stem}.jpg" thumbnail.save(thumbnail_path, "JPEG", quality=80) + + if not use_remote: + processed_image = image.copy() + processed_image.thumbnail((1920, 1920), Image.Resampling.LANCZOS) - processed_image = image.copy() - processed_image.thumbnail((1920, 1920), Image.Resampling.LANCZOS) - - image_processed_dir = processed_dir / file_path.stem - image_processed_dir.mkdir(parents=True, exist_ok=True) - processed_image_path = image_processed_dir / "0.jpg" - processed_image.save(processed_image_path, "JPEG", quality=90) + image_processed_dir = processed_dir / file_path.stem + image_processed_dir.mkdir(parents=True, exist_ok=True) + processed_image_path = image_processed_dir / "0.jpg" + processed_image.save(processed_image_path, "JPEG", quality=90) embedding = generate_embeddings(model, processor, [image], device, timing_info) if embedding is None: @@ -207,9 +219,13 @@ def process_image( "type": "image", "paths": { "original": str(file_path), - "processed": str(processed_image_path), + "processed": str(processed_image_path) + if not use_remote else f"{file}", "thumbnail": str(thumbnail_path), }, + "remote": use_remote, + "bucket": bucket, + "processed_dir": str(processed_dir) } return [(item_id, embedding[0], metadata)] @@ -306,9 +322,9 @@ def process_files( def process_remote_files(model: Any, processor: Any, device: str, - raw_data_dir: str, - processed_dir: str, - thumbnails_dir: str, + raw_data_dir: Path, + processed_dir: Path, + thumbnails_dir: Path, bucket: str, prefix: str, timing_info: Dict[str, float]) -> ProcessingResult: @@ -317,7 +333,8 @@ def process_remote_files(model: Any, client = util.create_client() - files = util.get_file_names(client, bucket, prefix) + files = util.get_file_names(client, bucket, prefix)[1:] + file_paths = [Path(file) for file in files] supported_extensions = { 'pdf': ['pdf'], @@ -328,7 +345,7 @@ def process_remote_files(model: Any, skipped_items_count = 0 failed_items_count = 0 - for file_path in files: + for file_path in file_paths: ext = file_path.suffix.lower().lstrip('.') is_image = ext in supported_extensions['image'] is_pdf = ext in supported_extensions['pdf'] @@ -347,17 +364,19 @@ def process_remote_files(model: Any, embeddings = {} metadata = {} - for file_path in files: + for i, file_path in enumerate(file_paths): try: ext = file_path.suffix.lower().lstrip('.') is_image = ext in supported_extensions['image'] is_pdf = ext in supported_extensions['pdf'] - client.download_file(bucket, f"{prefix}/{file_path}", f"{raw_data_dir}/{file_path}") + (raw_data_dir / prefix).mkdir(parents=True, exist_ok=True) + local_dir = f"{raw_data_dir}/{files[i]}" + util.download_file(client, bucket, files[i], local_dir) if is_pdf: - results = process_pdf(file_path, raw_data_dir, model, processor, device, processed_dir, thumbnails_dir, timing_info) + results = process_pdf(local_dir, raw_data_dir, model, processor, device, processed_dir, thumbnails_dir, timing_info, True, bucket, files[i]) elif is_image: - results = process_image(file_path, raw_data_dir, model, processor, device, processed_dir, thumbnails_dir, timing_info) - Path.unlink(raw_data_dir + file_path) + results = process_image(local_dir, raw_data_dir, model, processor, device, processed_dir, thumbnails_dir, timing_info, True, bucket, files[i]) + Path.unlink(raw_data_dir / file_path) if results: for item_id, embedding, metadata_item in results: diff --git a/src/models/clip/util.py b/src/models/clip/util.py index ce9f145..6213736 100644 --- a/src/models/clip/util.py +++ b/src/models/clip/util.py @@ -1,14 +1,37 @@ import boto3 from typing import Any +import os def create_client(): - client = boto3.session.Session(profile_name="default").client('s3') + client = boto3.session.Session().client('s3') return client def get_file_names( client: Any, bucket: str, prefix: str): - return client.list_objects(Bucket=bucket, Prefix=prefix) + + paginator = client.get_paginator('list_objects_v2') + pages = paginator.paginate(Bucket=bucket, Prefix=prefix) + filenames = [] + for page in pages: + for obj in page['Contents']: + filenames.append(obj["Key"]) + return filenames + +def download_file( + client: Any, + bucket: str, + filename: str, + destination: str): + # Get the directory path (everything except the filename) + directory = os.path.dirname(destination) + + # Create the directory structure if it doesn't exist + # exist_ok=True means no error if directory already exists + if directory: # Only create if there's actually a directory path + os.makedirs(directory, exist_ok=True) + + client.download_file(bucket, filename, destination) From 686e6acde68e308923315199b91f4e3a9aae1d53 Mon Sep 17 00:00:00 2001 From: Hannah Beilinson Date: Mon, 8 Dec 2025 15:40:34 -0800 Subject: [PATCH 3/4] feat: added capacity to access photographs stored on S3, as well as two forms of metadata search --- PullRequestInformation.md | 130 +++++++++++++ README.md | 6 +- image-1.png | Bin 0 -> 85059 bytes image-2.png | Bin 0 -> 68576 bytes image.png | Bin 0 -> 50453 bytes src/backend/api/routes/images.py | 6 +- src/backend/api/routes/search.py | 36 +++- src/backend/main.py | 3 +- src/backend/services/embedding_service.py | 41 +++- .../services/metadata_search_service.py | 71 +++++++ src/backend/utils/helpers.py | 11 +- src/frontend/photographs/src/App.jsx | 46 ++++- .../photographs/src/components/FilterBar.css | 11 ++ .../photographs/src/components/FilterBar.jsx | 24 +++ .../photographs/src/components/SearchBar.css | 35 ++++ .../photographs/src/components/SearchBar.jsx | 94 +++++++-- src/frontend/photographs/src/services/api.js | 30 ++- src/models/clip/generate_embeddings.py | 180 ++++++++++++------ src/models/clip/util.py | 28 ++- 19 files changed, 638 insertions(+), 114 deletions(-) create mode 100644 PullRequestInformation.md create mode 100644 image-1.png create mode 100644 image-2.png create mode 100644 image.png create mode 100644 src/backend/services/metadata_search_service.py create mode 100644 src/frontend/photographs/src/components/FilterBar.css create mode 100644 src/frontend/photographs/src/components/FilterBar.jsx diff --git a/PullRequestInformation.md b/PullRequestInformation.md new file mode 100644 index 0000000..acb84d3 --- /dev/null +++ b/PullRequestInformation.md @@ -0,0 +1,130 @@ +## Description + +I made three changes, all specifically to the photograph part of the app. These were: + +1) Allowing the app to run on photographs stored in S3, without having to locally store all of the raw images. +2) Adding a date search filter. +3) Adding an option to filter photographs by file path before running the embedding search. + +## Motivation and Context + +The first of these changes allows the app to scale to larger datasets of photographs. For use cases where there are over a million photos, it will be helpful to be able to run the app without having to store all of the photos locally. + +The next two are to enable more specific photograph searching. This is particularly useful for contexts where a user might know about a specific photo they're looking for, but not know where to find it. By filtering based on date or file name they can get closer to finding the photo they want, and then layer the embedding search on top of that. + +## Type of Change + + + +- [ ] Bug fix (non-breaking change that fixes an issue) +- [x] New feature (non-breaking change that adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [x] Documentation update +- [ ] Code refactoring (no functional changes) +- [ ] Performance improvement +- [ ] Research contribution (new models, evaluation methods, etc.) +- [ ] Other (please describe): + +## Component(s) Affected + + + +- [x] Backend (Python/FastAPI) +- [x] Frontend - Photographs +- [ ] Frontend - Maps +- [ ] Frontend - Documents +- [ ] CLIP/ML models +- [x] Configuration +- [x] Documentation +- [ ] Tests +- [x] Build/deployment + +## Changes Made + + + +- Updated the generate_embeddings script to be able to download files from S3. +- Updated the generate_embeddigns script to store the origin date of a photograph into the metadata file. +- Updated the backend to fetch full photographs from S3 when they are not stored locally. +- Updated the backend to provide an API for date search. +- Updated the backend to enable file name filter on text search. +- Updated the photograph frontend to add a date search option. +- Updated the photograph frontend to include a filter bar below the text search, currently only including the file path filter. + +## Testing + +### How Has This Been Tested? + + + +I ran manual tests on each aspect that I described above. + +## Screenshots (if applicable) + + + +| Before | After | +|--------|-------| +| ![Previous text search](image.png) | ![Updated text search](image-1.png) | +| N/A | ![New date search](image-2.png) | + +## Checklist + + + +### Code Quality + +- [x] My code follows the project's coding standards +- [x] I have run `black .` and `isort .` on Python code +- [x] I have run `npm run lint` on frontend code (if applicable) +- [x] I have performed a self-review of my own code +- [x] I have commented my code, particularly in hard-to-understand areas +- [x] My changes generate no new warnings or errors + +### Testing + +- [ ] I have added tests that prove my fix is effective or that my feature works +I didn't see unit tests. +- [ ] New and existing unit tests pass locally with my changes +I didn't see unit tests. +- [x] I have tested this locally with actual data + +### Documentation + +- [x] I have updated the documentation accordingly +- [x] I have updated the README if needed +- [x] I have added docstrings to new functions/classes +- [x] I have updated `config.json` documentation if config changes were made + +### Dependencies + +- [x] I have updated `requirements.txt` (if Python dependencies changed) +- [x] I have updated `package.json` (if Node dependencies changed) +- [x] I have documented any new configuration options + +### Research (if applicable) + +- [ ] I have included references to relevant papers or research +- [ ] I have shared evaluation results or benchmarks +- [ ] I have included information about datasets used +- [ ] I have documented model training procedures + +## Breaking Changes + + + + +None / (describe breaking changes) + +## Additional Notes + + + +## Reviewers Checklist (for maintainers) + +- [ ] Code quality and style compliance +- [ ] Test coverage adequate +- [ ] Documentation complete +- [ ] No security concerns +- [ ] Performance implications acceptable +- [ ] Breaking changes documented diff --git a/README.md b/README.md index cc62333..6148f20 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,11 @@ This project describes out Digital Collections Explorer, available at: [https:// We present Digital Collections Explorer, a web-based, open-source exploratory search platform that leverages CLIP (Contrastive Language-Image Pre-training) for enhanced visual discovery of digital collections. Our Digital Collections Explorer can be installed locally and configured to run on a visual collection of interest on disk in just a few steps. Building upon recent advances in multimodal search techniques, our interface enables natural language queries and reverse image searches over digital collections with visual features. An overview of our system can be seen in the image above. +We are in the process of adding additional capabilities that are currently only available for photography collections. These include a configuration to run on collections stored in AWS S3 buckets, the option to limit the natural language search to sub-directories of the collection, and the option to perform a search on the original date of the photographs. + ## Features -- Multimodal search capabilities using both text and image inputs +- Multimodal search capabilities using text, image, and metadata inputs (for photographs) - Support for various digital collection types: - Historical maps - Photographs @@ -75,7 +77,7 @@ python -m src.models.clip.generate_embeddings This will process all images found in `raw_data_dir` and create embeddings in `embeddings_dir` (both set in `config.json`). -If your data is stored in an S3 bucket instead of locally, ensure your default profile has read and list access to your bucket, then run the above command with the following arguments: +If your data is stored in an S3 bucket instead of locally, ensure your default AWS profile has read and list access to your bucket, then run the above command with the following arguments: ```bash python -m src.models.clip.generate_embeddings --use-remote --bucket --prefix diff --git a/image-1.png b/image-1.png new file mode 100644 index 0000000000000000000000000000000000000000..729bdea40037c95ab0e36c3d58361e9c6d87a833 GIT binary patch literal 85059 zcmeFZcUTkI{s)YRil71_pddw5kS-#du$AfQyG zLkLxRuOWoMJM6A|_wIZ5-re_)-yiQIJb5yinRDixGvE68er8@hQd2ljMo&gWM08&9 z;R8(~BC=5;BH{$n)4(2-J;a2F=$yK(tn4F2Sy`4xE)XkQ2TLNNhp(db&gg6DF-Un> zyrpEJd=XY0%W~)BXVNF9UQ3c_oK<{!+f0R&)3IFtW0f3uh4B04{RQaJS*C8x#c(9kWSb|*Y`b5Tr2dxeHQdO#X~WdDu!70rF3*ZMC7T;^FGnbJD-iZxZmZji@kK4`FiiAy^e@cxRH*CRyg1JksB>rEdC@!@obcz z%T9byQ3T=64l30^ z79Wy)^DErnAHTXE!xu*g$eIp_4f35?zltpGarr*Ekr(%5jA=$SQu_)0CrC#8H-5?` zqNh_AzopiamASl|RJ8NyQ_Gq7m~?{n6ZIwB*@J6RrZ-3I3t3-x-Madvz%%vNAgt?Pd#NLXL|qpYgKRO3w+)~@AXuQEq7o-me}Y4$mBvpPGy6mw7F zj$yl*<25Ryd-)QA2`2t|(>!E(gT>iDE)?}tL__1tK0;rU-(aj&tzB2cP?M3!Tqq5^EOMT|>AL1=pN#bcqR@|P zl&=EKER4TCMqIvh?{NB-ZnL7i$WH%Ri}O3V+M5mLFUe(Yd=A03-MhK)^30bBDvKLO z>koDt%9{Ng}OE^`C#_f2Y2K!ttb_(sPCr z?4yibP0c4KI+$M1oW~Wmk@>va9cSH}I(vRt!}!)MIrzngB@B|9z4v;}AIL>7@olB= z3cB7HuX&U5ZELIUa~&!2O*&5rqC|GcVEKkSlYMgn5rcSyp!v#>1`U&ebL45g(RGK7 zXNTYKC4aM@-HOt&)ST2@>zUrXhta#0qLVWcR$2etc%y`BX{+9Z3)+=%&?g5Dv4?;O%jQ85c$N#%F~Wb{k`W?0;Sf;Y7{7ggTGR-nZ1m=Ht_QL zRHzeWzzvdD_ov=y-#Gb2KI7%Zco?^Q+Z(}$G^OWrWiPNOypHN}Wx+N=3XcNvlcY15Uz(%9TIe71Uz;ak-Fscrg^=TfqG{-?H& zxjU}9Hi}%PfPL&K=2nU5Y;7whD>!Z6U^wAg7v%P&cE~8{rGT^0Dv6$xNJ=pI#+5x^ zUs2QNgHz#qwg+VX%xg{3RP!X}LDxTqG_b3%T2NbER60u&oE+Q~Ea1fFMr}&<>H+Py znE6v!Gfw_kk&w!y%J|Ai&!8bi--pZWZyvt5q41WOG;kV^)(+gDdxZpFp2@Uo1U6JuUqhy)*sA@aOc=^mxH8+tEQ!<=*$AUp>pA32%`> zNSJ$&J8bu@S~mLY$pzc(`}<_xjD$-BCPFxyRHui?5*$(EHE_ zV#-kDQc{oC=TC7lDok3RjXOp^N;EAG+*}-4+;nqwYj?vgy3g+}EX;pcy1CTZlRqGy zH`v^$FT^dy1+RGP_S!9ZM{WE8JfCj>lr^3jU~p9N@$xg7lO^}!KT18bKfQKt_{Fss zUN7>`C!SlQpOn8K?<_A6j=Y@AzsQ&_-r^DFq%s`$%-o+}KAbUZI(+UjMA%VyRhVD! ztiYRihr6PdJ@##P&fo16G_m&XC~pn3orSRR8(F)LE(;@>65G41^-9&t@EzfuO`XxR z=nnCYaibx_8wT(6m&+>c6)V2$TNxCUIg~Az-6>135gg1LTcooO6>Jr2^?tTvurw%y z6ygw41}8YAjL;8lf??n#@Y>L~72;*9q5dJ03ic7#<*j95G{{AUQR1r0)jURCv9ySk zh>NYA5y|Ff&1+kgS_i^vCm*;@iP4Dmi(@>jL={A1MTAAAnXLtR!J~`L)~$Xn8%|$5 zh9_NoYP$AbZrq$UYB^e1oZy5Oy4Nnsdyu;sO$;pWHe$Y+EY~#?vd;9Hr?qNE3Pnby zn5MXNpYCSj<3gN6sG16kR3+(mxpav_f;?VhiPv=3P*N#U&!x`z9j?1=c5Y!-@X(+Y zl8svqpBCf|8_W)$w$kNjMv1jDPGgLhP}^ozf5*X7T+k*I2)Wy${wun0&$`Kqwpj- z&h4O%6!FrFD*L+ao3n3p-cY1nP5Z9FL;dX)74@K64K?`?#FW3 zE5Tv!!Z25uN%({4?**_)yJ}g%U$c+0__C2*Dx}_dN%&;{Nxk%-bihKgbGO|z5ferI zTI)?O*Q8?J4L+A9SJZ4>7wii?4aNtbPP4X(b7d!ldi!*>&=1Stm9jM0@5wM7mX&{B4xG-%Sa#Oodj|;aui!26* z3knI+pkJY3Na?XRHPg!;No$Ml^ef!sIOkZXo*vkDWkC#4RfTD()*DFQY1>bcT=3yt zIX{LTo#-nDGuwl3{>7jVN2rrm&J;0+NesEabj_LcSy~fjv|{45e?V_7yel|!*G({6 z$b;#XNYB6&+GX#|9J6~x0!o*;U%YDb^3Kp(^OLQxNG$wy^1Nic-{uo^ITD@CmR#j6 zwhC>H|12=)e~z%xXRtavJ$KMmk%AQs_|D#?u1Y7tcNghX&U^^$Z(>Yg45zE*6#{M6 z_4SCp-x`{E+Rlz30pT_{j~1WXe;X7-u$$C-T_?y7s($OtMr}fB_cG^Wu_(H+Yoi?1 z`EIDGl#SX1&`JPiaAw$T+kc&~d*&>Kqx2;y-`$5B^Rn2tt=p|M>K!S4l5Tz@Bh(|V z3#c#kZqiYbKI2CF)w^qnDQL-~!^j5d5j@+DTm9?$%X_Xk<)+x`LzkocLTTjDSbmV+ z8Ys4w-&YGCv$eZi{mw&utouM_{}Jxnp?Q1uXLXO$WT#JC5Px{Qu19n-FI|;+P?7iiUq=qIH8jQI|#Kb&YdWF#7r@sk%LDuEJR ztUa+fE2J6H?ec6+P3Kx;*+*1kWc;c4iSbK2@!RC}3MiS(#S8MNBVr-kGk*Vivd=(< z5o4*ZXr-!3#0hMZ5}i76k?16_bprS&Izdl#>X&UIBBc`yzi(@vxb@pP#6(0PwnQYq zonr`mAOF1uK0xc=zE8e=L39TAbrJXkrxO1-n`|`o#-g+;=}!b(i@f&6dHfnSoWHc+UO7$2X9hX=2R058PFnvY*pRFv=b9lkqvcz`o_ zT)iBjPds@XU9bPz$&Y>>Sh||K*g8RNA&xA^{XQ{+xIraZS&uLD``@qQwDh$7*OeSy zf14ICLB8W7eEht(`TkQgsIApsG&?@>YqMYG_3Py%jyn_6akX@jg@D19j!>z8t+>Q5 zSNgYu{~G774IkNhS~}=IumxJW0&|kOBP??Jw`PAn^dFlV{Hv*ukkB7n{^7_US{~0q zOw-a8;^20?hB}V6P^mi-eE(_ppIhnwtCMpjx zGCnyTp45+P{BhrJ=S%P%-~T_z!>_{j%U(d*q{t-rewSP+vNJ;CXd)sRBE<*yv^`HO zW6ma-PS>7UXD{U|WiNe8seFC6V%INQ$EaUZT&GXBpLS4F2PFrIuG(#Pwyr_7OO zV}JI3(A~F`REjr(K6m*Yv3GqDkNT3RXvNn49Y5OrU2;ys+N%r8{Vj3)V4N*k+~bhd zmV}g&Mdm5d3F5!E(RZs@GhCVH#y@BR^v^;~S?PBDA6QmHRiFf>L-BJuKkv>@Vf(2&KTW~^&kXg~g8QKK#r-K5AALVg ze{nBT&9)sq2P%dOo=$0*C|o2G~5Z?9>b%xHQQ-o^Y^=bN)*U< zD$U9E(w%U)gte&sK*3$t*$(bthI|f3!yR{9?Lf4I1H(NuEsvqLq?YU73l4tsh=ODf z)`k38q2lH(=V&1L9D<<@V5ai$JY=C^Mcc)}{;po`f8x{|?vtcV*lO1$OZipVp)7T| zqE-1~qr8TMcpVdkz`@|y_I#VKe}8}trL2!6qvEXvW1}~C!kxJX1JMV>@|NgXVw{_h8Blq`?xiQjw+E3g`C6G+09(oDL3 zI5#>=$JTZUW%G>{zN7e$`syZr(;wC`8#)?OUB;&_PmV77j4E8|AY98zE;LU=z4WLYE#9!u7E#)S1%B~N&cZp}ZjDk5=fbai<+oP}Y>o`t3Cf>Czjf+KF{i8*I zasILhu!faTLw`>Vh{e)BnE<`vW4R7DUb;Z^i@Nn)^?xvI7MaKQfZ&__ZAsEUirHlp zWhMr|e_!;DGn~|*rw!m!S55xW!jO34p*Q5Kn>QNhocjrgZ2_-P7$nu4F{+i`;YGaLPxT>qa%1qs)F2jujn zNW|RqMJw#lRcg-&dr`TzN( zE%sz8H}k8eNQkP!rD~_dxb9mYAi9M<~?)pfI8NsL*nj@ z)MpozmWrw!2afRLM^fjRBs>F`7Jr}dpEqK{o;Iw!b#}k>8#*YHe9GUw>s7ANT!h<5 z_qv984+U?1ks4lqgaNzojVIZ)2c-$usp=Gd*ImEI8t&`iu#Y?Mk-0(5-aS~)$~`o} zbutv6p`5+T)yTmYHRn0`oQ`(73cp(2E6^>W)sdJ}EfdKk*;CTWl&EW98I5z_m0OUc zd{UbTsT1|vn+(0u7)j(ZmLRw#jdz9J#Cd(b7Lw5^gm!ozk|gMAm2lhH%)PsAyGPk} z{_A^kOjb$3*F2qk=yxiGjC)Ikdea=L@po=woLdScND2NB%yg30Hi+NW*{iFW9c#D!|VsS**Fn1NNKgxg3xD2#Erg0{Vv?&=n zMgyxzlthiQ%AFcKRS~Tuud%Z`0_#@65*EHd=VT-KY;@YsQtGRnLSo#}m!g^J`ld{- z=s@@?CxW);(<8G&nEgHPUtbg^!r#S?9tvrHavw>)NTIjwPfGTF9xKdD%xbA9=$Icf5mtRTm;a_ zez}ex=x2;Zps;+H8exC8z!@r8?WU-zXUMUXC~2)mFYK%tzEr!hD=x?jx=4;1@qDD= z<>nkQSmqN8UA~6b9)|Y$O!v(9sKa^&+pv7Y+w)?mi^e1n5459eAez(Aij@0^7*pk@ ze1^&MaWwT6ad!vrwOXtuOw*}E9WIrt9LsAEKmtLHdE5VTdd!OkKz38)!!B#geC3Kh z>{@gf|u-36=UkhN}$M| ztbNk~|4o58^IN(?_HdcCwK>dM6ms&+g^tFL#HbH1)&C0oer$V|bd;CJtM%q@FeP_d zL$olatbwOU?5MBY5b*(2csTIcqt{Dsw6ei1R##z7r)pr~Yc{jrqfi!bd3>2wHZx&r ze|uNlJb&4>)8DUWxHUk4e0L0r%8Su)>Y%hCAy#1WvY=86dprhMfaozlEQZq>IbxTe znI0)6hUeV%S*t}U!LJZ2%d+J4oBHka3o?l{A|-uxRTQo|KUl<6dmznmz57IBZdN#q1XJ4{Ns3Rv1`4Dr@`e{{67?y^sZfC#EPEj@|OL05!mjV@7P*stpwDw*^lQ- zF}Sy9Flex%zg22c>@*r7LcF1~+ingEjq6P4^r1M%AXG4A%MF}nqMF`jdtk$bY?zLe zPGR!;{)YIyY{&&$K#F;1xl}(%>Z5&fj8Klz?)?*flDhFmZ=^5W_4S;o?~cu$6Y0t> zS_>Kq`OA71cQx_WVTH>uWBQxl?NDD?LjnPxL2w@vD=aZw>nn6^<<8jp)(X#fvlgL@ z8pXHX-F^0|nW|grFwwT~(60>lDk?i;3sJ+-8847M-_6c?*L!lIHAAPaz`|z@o}%&$ z#GG=vXqayYFxeH3!>k}dM%S;V%}|vC!t-kjg>Q7~Y3qES+Y03A=9>g0pICS`XUYk( ze3OM5H)|?iv0BPL^z+G5%Vb$k>XufYmQG4~ae+D7@o~!uri8VcWB1Eg+O1{_XpSag)kLeEwzId-wzoG9+nOCvyDwjL^rl`%+Bh1g ze>73+p~B#6*;#IfST(q8)5Z?Z8XTvOFCvVe>Dj&_kY50?`a-%~+;qVZXXk}JH+o>IyK5r^l)9TMou_*+ z9^=U^VOPo;0#UZTY%72X$_+R=TcR3_?`m~0-gM=bVu0p@wv#sdY zRR*Jxow~3&=?MIgd88$L1}&f2wMjc!26QJWC)b`L>0{N;Y2BF=&!&z0wq| zPgsF)6@wbR{Jw0(!GnUt+6c66~{$&Alw6C|{3qRDh)$&u;pXd%abRF@pUeR3Y zab@6HEjxBqb(|r})+%j&{XwWIj>2e;L)QqA4+OGWXkUVDg4ID4tv;of)Y z9$f~CwybLR#n%zy7Vz!yBPS?9tZ6`gn;2CZZuf+b#l0C$#>{xqiruwd0mAnVK#p%# zS0Akpa^{!Y_li9?DQ83u-BQKv^+G@9Dp+pem`frh3X=HHF6n^_9p)5Y?$_c<_s)e> z=z#?B!+z+_o@Tux_2}2oI>+%8Oz(~~!Qb%1%IJh{oy7eX=M;v*YF)9V?7<8m@S8J{ zihV6Z!Xoaz97lLyT1lvOrMIEFT%S>?V2xN5Se&d{!N}C^H@)sg>Vn9@--s+jkM## zQx`N87?4IPP1`@Z7he(hr9hB1bq0`-Amr%>H{%aGZi_-3fwR zJvPC`kR>%d$1ji3EG4v-roGE~rNa=7w zTD$;?$o(;@?}yz-2i@EYye6Ni-g5iI;!mjdPJY(}cwmdNS+$};Qa4yH?g_k*|f9!IXA z9y01V#&)X2ZENf=5$DyXxK6#djV%=B8ET0*x=q-cdB4!9={6jbNmkCN>zMf5=X7C( zH@)aAVcRsf2fU1MZQZpE*Nh&pIjN-M3}@byPmq|2GLr^fDK->4eC-Frfkr*`=r_8C z`f8P1?>foUYrbBBX@0gC8yr#)929kx;`2}Obae8zUOv;jE2vsvnkQdv2ZVUCjQEiX zDATh6Q%P0saK5}=-U2z1`FcLd>LG;!X@^hq%LnOcknA2&Bcb%){{VfY&<`;N(@m{$ula;TcdX_RdYvBGuJk@MeMRrDHTP+`I z_eK(j-F;T}`dJ?{M7v%8%)pa3(&A}^bVy0I=C=P9)*fuwh4dGb{2 zfUFDWuzO`Pr>5=uVm>0}lv%o%W$UySL zGiLCTdiE60G^L$|oZ!oW!+ zH66=`4)Z|-J6e?pyTXdID+6xE)+t_Aw2!*FCG)&nDhNQ9RB9h%g!nL3AR+e9!*c}M>$Nszmf7}Xmjl!C3CtGgu$ z!&OA?Or<1fc_VyH_ru_mnRdBe&EG5G*S}wR(p}T+cd=jp`X&0wF%h+8zWeZQi7gd( zzL_Q7d4ZNIC;DpSEZ0a8YH%q@AL$uvz!->7Ry3X0Ud=ytjeo$#nTd+F3y$A(mfu-D z@Cw6XQGh!)t35CXYb)Pa4JU#ubB&RgAUyTtkF6B!DOh{p{F05vS@AJ(emEa&iD5|_ zk(UUbp!kbC=qnL14mI9<6e$jw>BW_{?22MR`V43TQRW{F0&ye*%Y*FT50h2Rn@4q9 zAGbe`AL?|peoD!lSlt*;Vn`y4eLIr{ffIV~`s^k_{cJI+gCKD^%RU=vG2A+|G1C9d zsl9~Q`-#BMmkwSB8_UWF%YLx={`*#Vr~h#rh}kY<{*+e0xL*s~{9+hzxQ`sqJb$Jr zUdN+TI5f11F4w3ZV?XoUZyzNJ4+=AVvM_C`lp-8>tEyqZg-Bw3MS8BGpD#&h(0icP2+fYp# zc$u&3TEUe4=$ZNh7w_$F3ibt*SC#%c4URQ~d~ z*Ie>lhoNG9ZF3j`h)#FWFd6p);w6fJy`~N+p_fYpAdv2_EPSqP%5opOAu-eah@@i6 zho{JG^rZ9o>&0GZFv>D;&G%jP3esp-qV+&*sUXT^+Vk}F*9`YCHX7eV0$w=QY_zaW z#Jj~1sIYQOixH0v{vBOeub&Q+V!>Rk2R(&|uKHe+Cm5c}?oNF9Xk5poXQySo9=Kx8WJ9I~-jNFHk`QMe^W;4_7;smGK@#KEB>B_y@9LGOlVgq;sn(*M3Of0iJ5a9V ze+k(bp6%cg(9Q2JeDEUyF0LU+=IwUV{a) zFA-Jm>1`2bB#W1;D=gO=4R|b~C~n;^raDJJ7|~s&{UW5_A zYBmg6uGO+Lp?4jds%dXRmiUfrU*YJQX0NZ~X+E^GLqs>$WSeY*bQ+N*V~iAC4E7y} zegwqVMp==i(TVCQ(1bsXG$~rIIegv3x8GB{t;0w=AuP1a3$}=u;URXX3J!m4A1v06 zWq#jf1gWjimm~&tCUzITxJsVh2p+Q|dn)&sH^}@O>*E-`_HbNIPJ*6GxU&KgLV|^M z>C?e^;Ze#c0~qI<3R~yHSW|D?=&ztU6W?$j?G%Z%nysEI)=3)LXS?uA=EfRwBAosy ze!IhRM0dsml6qw=1LsIPbnU1@VJw?D8tFX%WwZ3FgUTEa#obn4l6^DGW-*vMl4wkD z&^U_8d;Wb~VTs&Vu_8ATwk=vb2Zg>~{UOd-lhH#D;OJA5*ukwjM8p zN+eRL#H$_N>|2L~JFCAtvv#z0bO@=N;~l#$JnrjCD-%h$aQSv>&Qw+L^d~$w1ywA9 z;o7vPZap5emIXif&Ti09TT?I9q7&<3j?*_2JI7nSTw1UQk!ameiK&mBj%70I@T%U< zmM*-A44>JMc(LX-Xrf25y0x>_O{&*gjo7a)KZxZv!!*~9;hcRh{uxI8A;rkO)(#;RoDm$O{AWR~fp*yeGkN7L~@1}y*%)GY&Ah9;UyEN`-gcof=p8zp|14{%pw6!9Fnhe4vt>3UVzJK4 zQ;4`i9S9w3^4qM#2s@Lm^?8zFx+^+@BI5p2-{~W-EYzr> zF$PgKd>X`I1-iUxl^|hhYWX!SotC=0UaX*HT`j4VU2E?72i=waT3VknCE2r|1|#Nl zRNEspm@30x>+GcJ6o|WgufbRNU~vd@2Q8*LuJNOH99nt7w|#b(4WO|BGY5USTCkZJ zYJvKK7KZk=rmAPB&vWX+Hsn$(vtslX!|HONMrhjUh;>_SpK#8%g2Ov&-gX+JkDm0>IMgRbbVX=X9nyrIiQ! zdJDJ9I?g^=m&lvo&571iU%~i{jZc#s)@RL7jfUk_d`nAn4PLglqxv4%R^-K1581L5 z^pkhm0{}UdSYsDO+L}Tpwn%W=)Ka{4O1w^A7ghuGOYR^Qaj=ELj%rO;i>`qnwO&Wz z+xtrhy&6ZHkf7g%D|a$luxd4tZR6i6b`T4fV}8f9euw0K+aRa2L9Xi*{Ep@o*N{IL za?jN4udGQ9XnTYE?hEHa*&A^i`Ss_~&>yXRZ0*s_dBuZk49I1mWTDdaNWiGP#cqpOp))~Hb&&AAz_%YK zRqej2&kbwX_{_gXw-wFC=69FxQeudYy`ePc&f(0O;F;LXoocrfI;n#>F4?W-oqf@~ zOR1)i!u~Qpq%9`T6brWAx&DYLC!fQCL4gC|Xu#xMxI$_b!^wqo>}4~OJPO6dy_%Q@ zRtC-!nO71ixvMXfeDnE$DeqO|2ts%-l`?uTT_%wa-acfhZDI0G_pt6( zKoOlK^Ndc>G_GL#YAc=vQi4ef6XtA`2OetJ-&u+U{9Z`;GcC*wnFlOfE9e4=GaPd$3xMfR>> zr49Z1Ps8C_`7*vr-HEkIng37?dsK>DJJH7tGa?_o<93gxg7s5jN zxI|(NchjX}jhL`IE{Oryqo!X3*U<=GRcQD|VQCv@u6b)jyloN$Y^aSb=$jIo;VJU- z)$x-pe_k6&KNYw8!70$wstw)=)I0_&HMBLx%wRmF#g-C-j7l_5jG}{jXV3$cPk3l! z^jg9Rg4?cFW$6X&w5xUojLJNEbF)(t(h|VsB8ORtjtNWv+@L)^ZP@2wE|ki5q(8Jp z{T_c1OJ)|e+150J&s~C=9Qo%gZGiuZ1+RM}aD-q#5qe|F_y;%;{%E4iwii~GU_$1N zaT=6u_RV}18*=DVw~7QC>YPQlkO4VgD?&hVdL0 zZB7|9$q%5dBslDcnGGLj#)Qa&!Z^^^Ps_uuJ!O2gx|u!*MwE)eYP~{XQ-zLD(M*Su z>YV>`kGlPW9z8F65?Z~-07$B?!0ZPNomfaK|Ckw?SF!>meDLQOpc;5|NgBYEptV5o zna>@8i0cM^Tor>(>Lg5aeQW31pGEU6T5Go-ELg@`g0$ce@y88Mxt)wa(_~QyzZLsj zfX>6*Y2ScY~?bZV~6s`0WTv`t8>oIqt1DQS=_e zS+}?RSoSebOD_{r2O3EDm z!=L_$1%IfPejR{X#;z?{Z~unH1R9>LA#@Fy)#e!DhXnYtn$J4R?evqY5!_1+ARh>)udK6aZPYxA1Rbyylqa2(k6`#h<6e_ZuX8>%<`@4#MD; zuVY zs~_fQqqU~j%5##$EIz;H)@Q;#A!*!NEXKLR_6__gTKHoCwQ0S&v5U6-ntE^eD^PY! z^c!fcT-CU_5L#=_TzD|hC8=doT|^6UXo?~?bh|7 z8s4dAWr=1!H6}4nFC0dwAJYtAzH!tSFnsw|3=Hy_qo7eIJuz%XQz>B^fOS`Dr}cW9 z)Fn`#@rB*z4J(r9n666MIog097)(_9#HwYsy;IfFE-nNEKGYP5p^pnk+h3=&F16Cm=y0^- zV?RM*F+8xQFeXW{#G<9j{oNI#n-0fiiR@!sDYxr1@T!hq-vuC|rV?!ASN@8cU3XYj z_PDDw6hcw#kVATiZSmF}H`CgCk~Qbg%zV zo-+)UcoG#En0rhxgH^ir`c3Ecd^M$^`fu*VjxPa9$d}vH^%~vh2m%>3#{YJ;t z%~RQ(0b~7x`6~zDdY=p>84;CqPRNe?-k^u_k=sYxTm@8De{~09f>`5~5X5Up0^TiM zzYz|}7$DF2Y{;~0Y#uJybIcXu1*jwiiz@*6;a!Bt)XQ=Jk+F()$Un2oI+UQ79%jxM zFzTFZ-JODa0_z^)Z7c(57XEpvH%E_)2y*l8$IOAF4d$aaKQV=KE;Dqp--u*EO$zsY5k}_&$jOmk378}n3jj1`QgEC8JRPx( zPt?60K(@)sl8nU}1GFmW{A<<@LKOVqh8&9kWW%EqNUmRZ)52%ouO=KyjXZvKz6YrP z7!`neA7~@HjBr&mYvBfER++6#KHMOl{8a$CVW8WZq2@m%ZCb0Gj+lYjCq-b@B-WM? z_5S-`ZpLPSk;7JXN3;fR{W`q{*2y~DksAQVU{q<%jZqIL%G*_4(h`+dd^=_OK&)AO zO?(`u77Zf(EF3Pg73sg7-dABi==Ny&bzaOja>V=3%1j4gGzor?tBqU{l?5VbbXKQxD-nT7{h5KWj$~JG0NJ(@T5P4DFCT&4FDmwY8xiGF(t$9I5C; z0{*_XNBT5{Dm9zmyD?up27p$Ltl9^Se0HD{DdHKea6kSE&Qr^*mDNY9=*$5gBW+Pr z6Dziu2;5xup}|#G%-i1cvB^;>UQZs<6UNTuT4TFxTM>@NVLN#Cs|j6I+X+=ydywHO zkNa{ony*wi4BsKQY|-mg&<7V*474?tYTR?V2L|XLwjH$98 zk_++HbCO%AQ5R(~0Ej8YDCA&AUAtAAUYu9f$h=b*QwJHZGnn9|D3O1OO>*rr`07;p z)X>ZF^Ij?O(2*~`A_hMhJ!H|1n@L3(?D<82{>=5q=Ku(Bptlb&d z1`@2Sv09((WREe?LcnnAAaiZ4dNP2_rrOr>m2-;83@j|L!=L`E&1$C zhV%*xRBe5?mi@v2YIWg^|;c)TYs=QvO4zH(auF$%1V>Qi3J@#UCITJb2Jp;igyD=pqZj+(Jl#UD zELOSNQDBV=V-(wXudo_bQ0mz6fM~BRaaE03?XXe_MB@Jod>@eHu1)(jyh{+j^Tj`} zU~i`5S)_Cnz+~DTjy2`dAsG{J)Aw?eSunz{yq(If2|sdjvC|SmkZunsRPWSDXF8gQ zWpxf1v7=2$0=K?GaEI(_DR2Fq2_`cz73$B8wp0lwklGL3j@l*M2#YHZGz2%FQAm9b z^6vk_+Hs{@rJNM!r%N_2A18P}Xof~8T{?zwvlEhamYO{)hm`>gWcmw0WZOaP4J4B7 z$SWdFk9DbpjovRu4h4`ba#na!JkUXt&VeiXYZiN{;@VH<&Y-&!L_$I0@ewd3a~)03shq;$o3!_u25x4b(z(D3LJ9Q(Br8?gys+EO%21%@rw-);5uze%YLU@-Rdw4VqcSEX>+P>d zw@f`23^J7vJY|0VYx5_M$$|O>yNO4BENmKUDBH$Cfw6 zFm$3Khch36w2A9>#-uafn2+%x!;8l$4!7!iDbx;hb>E=oZ>fHAX7*i<-$qMI#a}qu zFFNL|B*+L4ntH*6SjNHEH!3!^FW7p!Wo2%hU9{$t31|HbdX_W1zyo30Hl#YI@;2PsN1*O z72Kj)X1M*h!M7ij4LG5~t%j2n831{yeCQ~M&CHj7mJa00zXC9{3?7M4)X${vhp%F@U^q zi+o?6rel+=Zj$OmE$N7SCZ^eThrgv+v0h3H zRg533+pQ?a0c@7QE#Ic0qnA|IH6>cjTf)B3=^cc*zI^Se{V9Ci5h$PMk>I9dPc(i9 zW~khse=sXv1W=x^m^fx14e6#^d0>TNFQ6Qzyb-|z**JuSqBNe@jMn)kEA>uh{w2Js zET5{F%c_JqqA3n+H9U-bii7STE;~$I8NsL;Ha z^KOkRBS^K{Dv!dDly8>q3R-#QHTKD*VAo>;btr+tZl zMdsyD^}w7!B>kMvt5`{5&up+(8gg`e=$67;Ob!xV7K7Rxv-N0gsQPWvS*^p^gEA`4 z4)Z!$gWNy)qoj33wJY&W=Dwy0MC7YTa&u+|suJSt*Uqkhb|f3923 zGmh+m)}&8)MaJ zIS{{Bz6ojNhMU@*w4XRhJ}Pv(81sX7eH=_a_PPk9(gK=Chpt>2<3P230Z2`yyiexH(Y|9-8 z7k&vZwa%sM+;Co6q0+N7jts-6+{FIvT7Py*|6Umhd~xyDn|LXQ@Rwz^ z|Ja|+Il#GvPjZT#`N7fn0XF^DL7xWRSO~stD9-lZ$Mx@h{k+y6S1a)68va3D|Bq#( zlfFq&nt&MX4I58|C*^Bp(^)L5%R%A29^Jf_JH1XH!u})Zh)kx~L2PF3o?& z{YWWo9-TP*_Vi4J>u;4QFKV0dJlhe=$7k-LXI2`oK+>sS7W)jkuar*U&1JJQBD1?~ zp>y-We^`e9cc*}@$5H9q;;!Vq`JvhLrZPjw$#BNNhBQ)uCz_)Cm%#py?zmNfqFH9{ z+R(2ypyAHV;(OyloM>Jxy-$xxJ7`{h1xvu`|JVHV4T(Er1_Bv>)a8o{&K6+GFr`8_ zrmx9NCkdpZ#aUL96i?$Y5cW&-;IePgBTLmOsX##ji zqpK?$a0|^|(du;M48y@>sPN?=F~)yn758ZNJWnY;t^sV9-lT&t(ZGWq?}XC+S>KenatjwEh>B|>VpT(?VfJo$fKo<{I2$i@iRI51Ns^<+aOW8`ox-KcJOXHXT zjku&MGl48l@%~40KK~eyb4G{znEz=h9t#9Su z!=(RV;C@c)U(5CLZv7!v`zeI~^67y;b?Xm_)c>u?Xd_1_kNt2Dj0&k~X{>p9d8`C( zF0LgJ;aRmGhyE}?%ApKmRaMn*LqnH$c6Q>sRlQ48M{&9pH2eG;14uaap`pDvQr%bizOB;g3M6*edWX@c1FJz{|sV+1A#8|C2*C5{VQ! zZGGw2tI331%K3lTd(Wt*wyq8I*cC)n1f;77A_z$D#fnH%X-X(6B2p4WdPyR35R|4! z5vkH!=p>XtEEMS_QbR!LJyHXKBzJL+sPB9H+Mhedz2p7ki0r-B-mA?y*DTMInOXlQ zRB5ES?DX%Xb)WVzCZd>WX?}CA@h8UMzPEyxm-58!MNv+uCo=6cM-++ia&)WGz0#T7 zO`rU|;DjE7f;vXY%JA^;5l=f}3v}i-6Dv%q=g;!*hS}}mU7%8kEg~W!I;7+3kx9Lk zD1>a4o61i?_EVX(weRXcKF}R}6G2OHXcrb04PILu$7B-_-C{(`Yd1Q(&OcUPXSw3L zAftI{N+~{}o3`7b`ukA&oM00Y9V+11vXK*;cXc$NZF*#xdSs=gs|&3f|AZ2}*-T&j z+$dYhMtz;_N`iP=D;wTA$VLf1_FC1;UR=wh*Qf_w*%aw`_-3U##Z8`CVSju};t0h8 zjJL06mcQo@6g&AmfBsy%DEC^!*(ke~AVyMc*6womRLIosIU9!Agpu{g>0 zo27KbSDh0ytdOR)!f{U`$WF)dD7tfDJjJfhL229eS*>@2lPfY7m$m+0GDk3=6OOH+ z?ccqPP@xwnv6t{w;?pSC-!2cueD#%R%gv?-r{0aoEU|6hsTlGYhv%^tBkudVyZLLt z7?7iLAKmu%|F50gZe?W^{W691)R|w`{Es;o3jf~bTMF?A^|O&EQn&mxrR&tT?NISA zBxgcQ#fiULYI6iFE6w$nOZ{%;{$?=#T3|lg0pbeVAJ^G``|=-O@oztPjDhtu+=5d2 zKbcQLkHL6uJLvM?I`e+6hW~Wy9~1eX+4_4?{3T}ovj~6L)c^19t#I~4X0zWZs4e-w zDKC6nk6*iC!fC}Cm+aaWFwt)pBQ)JFl7y9P(0Y^XG5I7TK}CkG*;|yYHU6+@vrcUf{^7O6*P7QW9sClrqZ-Kth&zX?h~K`T z@}Y#Lg6yBY>j?*^zL*=vga3nw%o)h4tyT7hYV$3+ON&Fwdr38a{4%#a z%9|fhM>PE5cKYSwFOnIUAX#4f15~{dj)=nDf<21NgUiIJN{SJYwP@en7xUtY$!T^` z85u&MW03)r)MW{$uKuIz3nKF~_}1Ed9&{j_SzZXuLnFEmB_N+WhMICUPO+D~&oKLL z%KSB{cY)hn6wM*Ad5HcwM!$T;_lXk{RO?{Yvh%DP3yF6%=+9}ZwZ!2eyyJSrsqB5_#OMgBP{H%3=i>XbdgASh_bX#UTb{e2%3(owx;I;eQI{TVxjv@#jUH zyhS=(G2`~&Or~AHEf(`D2cQUo<)iIB&BwoezPN3^`Rm-9zxtEN&v?eHT-wP?AbQXg zf=EXZc$NnYOJ_5rrmMDk^h?Ko8UB1fhVV$ki-RvUE?;PkdzC+H){a5zb3b~gl;mW1 z>u|WvbFq~7k58VBX>1alZfn$1E>=Le zLkf+~3kjLbQ!VnFDu@0YH%OZLWTXdS?tj{fidpJW1B8pC2Q=zFJBDhwOcu)D9;{4K z+($@z+c%c-e73N*wn-0PI3l%Xb4A!$23VjSsgtc8545xTBTv33P$=aYdQUK3bCSwv z4(YRV*u{_s_NJT!zK3_ijSXB3RLQ>pu)nhf$a%)TcUgYX4!;|xVm+U*j)jRL{7VUB zds0S>%;}XLm-LKT6ILC~0CZ-i1m`PtsQ%$nC=B*2?d0Q%oXpdU(ffu4r*-Nng(E$q ztPWaI+XxTL*}P^XC0S}g)thya7Y>?CM)UWbdU5@i=w|-8?W0`Ik*|K4wNLwEA1!D) zF8He+b#ZZ-Cz9xA&AsPS`&F5Kj_%Ko?lVd(M;ja11E?3|O8Z22y0yJjqQ&8SRA^*M zA=K$`T5x1QSXh{LD#4l17r9jGY-4|ulUQz4_X3J}W^C?x+S8fDLBwzz!kfcoCmm+t zIVgHC(HNiXu)o)1u*Y+Cu05HQ_*%~Lsy45jqB)XQaPzEnZLRCzofi5khJJ7dX7IF= z8eTBy*ffc6Y8NccWQ+_}z8?(Jq-^ zdjCT}Jb?J9D$Q^)MoM4&_{2uyZZ|b4Njmc`;q^}FD}mtJ`-p-2S7e#SA}>1~F6BAG zB8WRQTo)WzC8Lt8wNT{#enxu`x~7pnB{uIPZg$vLV=m6E7pgJCTEX+^{Cx=VgNGxv zwTkUko$@QUrpVG8=GUY9R~EiG-}0!5yz(XfhX7?bcFp9ms`F1v^mZVt{I|!{#kop- zD=X*OJ{gA?Ktl3xx|trJL8spKrrKHbF0ni9`o~=PB(Y8OgRLE_B$K6Nc(Ik2n3P&( z;{`V{hUkW>#MP zm_|*O%)C)RUAZ7PTeGD5iw^yJXIxv_9wAc+RNu@*Uzwt!VWft>zW&Ku1Z^uqFsFBi z#wCwiW9)P6;^y3pGt~~UE$ox1dq3r4>SMmkjpk%#ulkiiP)b3?m3s2t92?w9axVIlx z8YlH*QS809leW-})1X-PDsNX}=!fyT8*jm({gAasGSxMmE?jhSy3vUixO!Df@);q8 zLqO9hIWomJZR`r-O;S~rD%+(COBtH7#a|0Q^6nYUMW68?bn%HR^S_A{AXjuO%v``! zPiVjb=|0zqYvspJDQw~I{AJ_RoX97-UI?@js{N%0->so*JGYCv zEG8#mrKiG#i*t?;xDe>j)y}-U0J_TZlI{8| zvBKE&(fpWY`feR=|Y0aHq%?O6yxp)#L=diDzi z(_$6XFOK^rJGr>(xOVQbRH0NF~6{ zJ^bfzXkc)kI7QYLw|VXLlNJfy|bjihpQ|B~_B@XS}G( z-NR2v-pG==R4#nkmGP5iGztb+r$Qb`ut`U9BYKWI_SNa?n263#4{pfvdTl(L7^sAJ zPj5I>!|L6NouXO_?rEBBOuzLXt{AKkDsrd}QL2r9cE@!RpRR|c!yD_uh_3V<%(YmL z#iH!rfZ-^Xs(;+DX-_Q|yssU{!PFResaw~o{k2gAG2<|1b0f34Fg4yC%ehtH{`JWN z;p~t|D`;SEtU-6P7}1m5C@Z&GM1OIpU^-*??iW`j4RX~EsmqJjl^hPb?gG5nm8gPy zU;9f|;+{s66^Ez=v!5!HNwP{8bwX9!W0i;F<%WZgt}lI@{}ybVyRz|7S5f5YOtHfm zt*k}baABTccQpIt%>fsRoTQ;gV}nST`r^iFt0*p%PIRLR!|&C?+bS&Ixhh$Oh-;1s z@{o(~^|vZNw8To#)(l&2d0fCj{p;rZt4^Ugs=USqqPj#wZt0tc){!>sg7~Nj5zLsM z()ZZaFyxGG(!rX_;uM=;Oys89QMRIfYttnj+ir7B+$>Ve%;W`a0CtMp@8Tsm@;Y8l zW*;*CTRd|PI*??(IxD~OI{DGMuFC9^`&xuV*|I%96JGV4b(_2p0^ifI%!> z*Qnh!NV|Vy^6d!>bhH+`wm6j2n!p3n@60@mH<*ezK=q9X_c0Fd*<#Z{z`Vu=_j^$Xh(gZ5v^R$=R>YaYq zb)IZOWi51a8M&C<`0DIJh@Ga?R*tpocs!ejK-^jaaB&V^(-BtnYT6rL z{MAAr4i%NlW7_K-T8Jb5K_)ce3I(U}+Us@PmPRxqn?S!j=$;Tef88_Z*6Myx>*s$8a1i8 zXsr{NjdQvTtQ7vdP(5!_UO^}Nqa=a1bZp_Z6!ekz7cI3GB|$R}%bAH%N=3pa0%C@) zB)6ix0rwynnR`qYcnytNB=Ffp3_9DuE2AB-oOvqro7mx=&>U|Q7<}mhrgqjCRn~K9 z?wxB#>B3iUx~ru9$M2~R&u`v-|74WTRk|!*QUYV2Z5!7o!a@`xg8+po!+o+HRgac0aS4dZpTp!8>oAxgJs_!WlnNd$zJ5S=-bY+8T}L!e0pm@c{!ykrufIW z{4}6PcHYNHh*6xyG_zV|YqMDdHNuTATUp(3KX!U4T=ZMGlDi7mXubGnag#poR-CkK znqJ)D&QU9gMCe6`+{x1Q zs#c5QKB`SkUst0w!uzA`2efEGPQlydI}(p@$wNCVu<{NN*VNX;StABQ8o6R9+SRik z<{x`dX%;u6V7p@aGanIx1`y1VD)hPUIgLUmd~h4Hq_Xz#lP+w!@-*V6%tLj(G0KHj zazA{BKp8vDCWm@j=TZT()~UQP6W%o9o%PuvI7vYQBhF-npeOOwY)d{6Og*4{@_@?F z#7&Pg7W6*jF3x*8N?I4t##9>fd`t2m>pFHgQCpzX{+nwk(XG+&Baf7;DYwha{Cvoc z10ltIb|%eo6-#rSN@b*tsSKMoDTtpO&oqjl1Z2lQ35KiV|J%uIjkbqN``oG$wb`OVo8N(`H1kY4%EVfh(730;S z%V^+B12yRDH|Hc%>+O1~Tn6MGO;6iyd|787+f{r@JND?QxQ&-V^Rzv@Z!#k{Hje<# zQle$8N+hfjUJOKn7OU2lM+oSo+&VQ_>1iqdNw?!v1^N@xNR`s0CP{H@;;6#iWvb9%$z7%V zxi1O71SEAD`Z!JU?(<&8DF{{&WrP^aa#1%Rp$3xAqcv8e(WeO9jmhl;PbY} zt+r3@sjaaNYKV<_ioj1{-7G38@1SVkVmi`vrE~S1H&X-B^ypdYj+mCjh>0-`K$* zsPcQj2Q>7kNXNlSw~L&TI#Cyxc~~(6=p;@Oj@MH@w{#(^$1?^sypTYb+$?@q!YO$0 z^pp*57|oP7wiI+izBX;10$}th&dH;ylmfhEUok6lYPv35N_Xv(jmNP3)F-!EC}yyr zTujy$!s$(G=xzx{(#P9P)tH!=q90E1Ur3_ag8+l)(Rz1R4;*7=IUeWQz#~an z1N9bq-inxb*^X(!vg8D~ z7_9tj-xZOOv_@uein(BQjM76E*^Yx`hul)z5@YwV-uCF(cF}sLkDB7jZ2T)~$IU%Q->;H~>4D^`>41#6ewi{-4G2}g-ZzlD9D&i4=@&Y! z$#BTvqRl14pg3jzIpnwZH_y5m0r(El-7B+fPWP1)xNp2!ilDQhbb{B@NeJPVn>sGN z(gv|ct~yAzrg%0t0Ux|$t8$oJY?fGw%z%iTCv#&H4H4d#g4Y>^}%CxLC?|9a_ zaBZ$-4>t>oxu>MpCtFp>&=g~9fLyH_?hRb?$j9}mk7x}951-A1R% zqT^^kTtGc1b{UisPoxudzI)7Sguf+d&||pzzJ2}pXx4uCg)ei1tmQ^_-dG^i$w^qK~eYdFbr3QCAGkFuQ7Z9t`e{TdN9NSkAxM>!x*iQ5BU1*AZy zZjlyX6)0@(L?CF47A=f~`^;DCUK(w05!>MFC`_Z{%8m-M%D3AvJaE$RQ+q#a zah|Zy?{U?)fY5iI+AE*SFf^Quls7L4)_X1}{?Zs&H1a zmJZaw*w`9Tri^lq$#jho)WDCTmYpFs3ytH3hH=R``r}8{taSSy5qKm#KG;bJc_2I< zENr;+nEO|Mc#e?BmhcEMHjmpkAV#`}rz;@4KCjkWhc+2FLAA56xvJC9t}?`(4(YsyZx(f&6|h5C_8?(v@VWkN7c|EDZ1_>fyc+XbL-*uTHw`VXYn**? zQqa4uGW!Y-G?y56yN|t(={}0q2_0Pj^h)ym;7l2_IXN2)jjI<+>lMPN+U0>m$~-2w?3;I?*eob+`SBmUULOrFt5JSjqx>R$fB#D zh+MzB6HMP^R2CJx?ix9tR~6~Dy4Z?)jfpplR)t?ia}dL(4m!Bm@bt`n&cvJOIkc!M zTQpw>#d@NclJ(s|{B8>-oXyP+Dp-qV3Dgdp4S=zlhw)rP$jrw}So)3HioGO+ub7z` z#zAmjYe(PC^goT@RIAvC@_@J!;N95e^LZ&>zZR)t#{8*%Rq?cctbv`1k?Kwhu6fT| zRXCOQ&v5MUa?^=-893^ux=Om)fAg@RS%pTov^$~9X~8I?LAz8IZf;~`9)BxOSGdOY zYSz~-OnBWZaV#$qw?a9(xWHIn)Ho+`Z(>Eldqh`)vK;M5wREV3wzdRIFjidFw}Qqz zh2eXzW|x_7JOih@1aAdF?CL#fQOLY&_Kf|30hhB61zJC8+H2T&$WIN$uW6n3HFM9+4i} zPa!~aP$%Y_PKz*@rBGLRw z5^~UMsGhD8VS}7W=4fgEa+E#EQ#^n~AV|S!>|RK()p*>a zx&g;=V%Z9)ZjQA}_o*#@G}#wvY|ilt<24e%GwjE1(Lg|>BPit*ERm62v;oqZyBU@t zXrE7Ow2+7-6UhKO|N_gi~m$w)ahn7IxOc}X>$v& zh)dw|VjBM?n(*Bh=WOruG=(yqtvA5#KjU(9V;Y%PjglLT#VX7!%e#NxCgI%nZo<@z zCE}&Q1*lDndJ0ZtFnpsRZ`D@T-Fh<&iBi#AH&J(n&SKr97JNtJYbk z^qkqU*(VCqVkcg#M43&oi+_@3q?J9g>JRHEd}49I|3_3|b~DL@+7kEj`$+H@d?~0) z2;e`UB<Yek`oth`b zygz*IvfY$+Fw%CPq8%+EY->-q#<){b$M0_RNEFO|c`I?^^x3v_x4e`NsLSE<;EZet zXVLxEXY+YF0qhp;#|K_ZA8)uCHkC^(zYK*&J;<<#J#xWaT2LpR4PcKxhhlh-dd*Z? z7vf|Ac29gjSYb~#k}Q;&5XCr;E@>`eCLT`aD-%_nC*m#+LX9>$s0S)SpF3N)MD<~h zm*k8F-$pT;p7rva?lkpUHTSQj)xpnDmlxF z!Sla@;13sUT>JYDeJ6Nml`xpsybD&**>xGvl}L3@c4ixoInkc%n(v!tk(@>LKhzg{ z=ry7g`e`Q&6!-0jhEMY8hy5{@WMpV%-Fj>OSfRZNLJFrro-3>Bs0~W-{5W>Ah1S6i z3{md~5nAc2#!;dWwr0)FXZ8o3BYYKCpN^$aF576@jEPm`Nn6-eECW_>z8B<)c78!r z@_Cp??{nJ&PUFoG2zg~oZ2Tfog*bg`7{{u6=mV^T*(ON?xn%@)`Smvl^hDXyXKsa~~@&Et}lGoN}9eD!MneD*52yioZ~ zq*#cAxEh~~jG1L!Tv*cHdZ}_RQk6*Acn6qWvJf%oEur}8^s?HzZLG^=bD2VqYqfdw zyV<0*BBxG=bRBmAgc~ih%yK}NAGP8I(6X(cptIwnlrcICs^NmIELz>e3QJkzdF56% z#G(Gu?)1L7ER~+05f_j_2y)5>t}$=<@SiXQ@ls7ccXw-`ug>~|fJ??qankci{?H92 zw@Lt!D<>vTkGUSHT*@tfTitoGLtw?LuBwbm?)S3DjgvJ;tVOtYOK4c5Q^yUAj4qm# zIO{aJ5}29^%QF-09@Ef*M>IJcFK{$_&jD`tRsiklbu1T0dusY^b<BwtxJ3-ewP9F zTqm*2<`$OHZ`od!<~1Yz;K6>9nowG+Lx2KfWc3FDmwKt*+KIl@lN5n&hP79Xcb$K6p?C zZ8ER?s4KjC*ze@$jiw!PHDP{@jB4H!u?e*+6?{uwGO{gqT9)d|rVURy-TRRoc`RQ6 z#H;1}%k8$xp}LNL!==ZE_#RL`=JffkKQDJ@XJ?rdZD|}g*4M0=`oy?4=oygDP4-H| zOZX(~8=2A-DV>iX;;pJNe6MwUvuq;zWkgBJL*M#yL6qjToC5+@Dax6u83E=4={9#G zltwPtJkQso>@I4@sH(7+^2plPhzxaEy)shO&EAoIuFu(H90W*oQ?f(C#1R`_CWO?6+&NwFGL4tHp5`kq4+rZsb0pSwo&ilPsxiogE`6 zljg=L%Xw_QW`^szvC`rxiq(N2E(8zh0p*jG@d5}T8+(hXlOI@{V#aw~{rcmGIud~UEyzgnF zpf~CehBHXAJ;c1d|pKbRVJ&uo($d;~#r@Tsm{ zC|e1Nma?4d_b6K~mbgDt`oKGT>U=q^UN1Htk>i>PVqVl0$aPV2@M(P`ul}_DQu2V; zWt#GY45PN@OLTI1@mKe;?+&v7MtlPK^!dR&u=+k*<1o6{XvLOPo%~bdh1|%CHY&A z>x65;z51aC_Vz(mHZPx)ISoap#|QZHmdcrX%$Hpm(vlUu%mn483HWuQdm^QBAD}v`_Y$Sd!CVs}c-u`-Y0hJ@%FFqa$pL&aZTe%*zxX^|A5qdrNfYFC_(hptw#_q@8a-!Z@hN>L` zq3~$S#xUD`y`zJ44{1UZd;r7^+WR|VZ?zhU=os_5f3b*$qUcvdhRhvDNsnSYmuEO| zxT)tEIZe#x(tPTt^VT8ZC+YQKgYqN-fCYmChMbK~%U;F3@$bUx?vn5Zfx#Un2RP8rD<9AeI+K6!bRxf@?b z(~unBJVM5Yt!ZcPx0s(!(8x2dd_+Lf>(s2WhVRP(6nwG3Sqv|mX)(DXV&N>>-i68Z6#ob%; zIUY6WWd|LPWxv;yzQ8h;-Lv_2IbzNP;PhMFXoZD3(N{O~Rd~yWf9dd%^S9U5Eg9Qi zss7lp48mtUmlg|J2fRj?*TzA()Ir5eGdnnhi)_1}4}D>vN{u?|;4$4Bp=M4UmtVWU z7cfxiX)QYoyjAmGsN`xu`N8Hi))I_>Kv{h;L|LN)ln@RnS;D0lcnBBW7SI);9<2v9 zA~}sWR@@{6GSN!6-#wO}|8w~6r!ViJvhjDZ*A(e$Ym=k%%}#W2DeUJdCH7dp1l2_r z3E9jCu~o9L>Hr=m!!W#Xsl~>JTl2nwVl4(*y1u;{+=!cF{d2_fx@I|Zc2L$I0s_K8 z#g87EyyRCoRnZiqCZ4N3mbkp|AyB*~2A_6`j-X1$_%m~{kq5mrl<6CR(W>Y{SVcxw zmM#41IReY8`LymUQO`&CxOlPj+}HAsH-fkoPB_u|6xWggv5eTnAI|?oiUBU%u(sJG z1&7*qux7`m_g*zBsR9zR`?~K(jzpVsmN(~|!VSi&z9JxcLLBcMF0UL$6NcYP1P;A8 zUYUgWIurcpjgsZn{WhH!NGDAx1&hd-%y)!q7@-D{Y{@(QM*bJ|7ix>_#Hcr>bsPz- z?A7@y%=Nph@GHj1^=nP>ipR%V-1%+2V62-umSwIv-hCsQz1jiic=i5r$vB;By>dD^ z+7(15yvOR~s&TaW>8272Gw-3zydMKMvqeI2A-sy%$|X+s^qwn(yux3VOrJwcJd^My zU9jw{me9O3wAOC@?#0BbAf*a!dc8wUUe&_DOx7>JXI!HBQ+b(C=P1P=8cyiXcgytB z<9RWDfozvK)y;^H2($Dig0fdjEI5T;9zb`AqYrQN=i$CxY>JjW-E9rMVMzW{N<4@hzwFyXBBocdqM^^C z5^i4Clym!bS$eEBo{e5QV;6nf0UaaVqjWDFZaJb90%C+MS3i72V!tiT-1#MW;mAdB z>^v5vxMi*#G5_MThp)jPuX$yIY?s?AYrKY?Pm4(gX+9V#2$s|X@78N2H}k(@->nE* zqqZT){Tjo5?8wTrsp$~+o{U|^Ikg6kjg&mFgMf6FF0>LR4^|&$>ZKE0TWjS}fpDJ} za0LFzQ9p&EJx%c{N>z>nn7_jI;#I4U?mKDSu(=Cu46B*u{n*!H(Op$e+3+Wd@L5D* zZDIOn)PM_rcsLy?oTeSe3F@RgqOOcP^({?0wix4h2d`{LqsFD63G`XUVSEDBd#t~9 zgl~_D_@o;@%GRp}PzdbNr95nUtx&W)XSxmuHJ`oGQ*bF+$1l#P{9MVW~qeJW39 z<=|Ann=CCRQiHkOhqE1?e zJ~xgpRpT^b7`V@Dmtk?ZRn=L`lrrg7n_?W_0&7{11x~}#8K=5x0EzWt=OcE(bt6RX z8-t}dIT4T`!ao11m6wBYY=qstl%ix^&1I=EzFg*=DsW$ym(Muf>uUe%qLY)QJ*)xg z+D)l0W*||-EaNH08#9Y_wc+#PBfA{%i+JmgT5L_h8V>80rt?U?AOXhlTr>gWRN3iz zn}6%r|Bg-MT1Sy}YXm*Ysr^pz0iAnsa=wb3ilo= zFV0L{+0o@-J^9jL0HhKT?|%66*~_Q52Ip?vx^>8Fw#*thgllm0#Rt;TIrJTi7%x;; zT~uV`{VIMcg&YVFW^1zZs=7QevRhxi<*>M2#Na&j`Lq)?+HTcvtXZ+th@JlVJsg6v z$<<6e=}~dRLx=PlTWoDgZruZ1NR!til$k|DvacYnCTWD47Z4A8l9Ug!8U8#1`1}g9K2t4ZTeKegh~Hgm`{&_5J#@ zGH@%`4aog>ir_5Wt@(NGz^6Z96)VrJ?;F*?LpS8cPWo-n%2E{YAuMF%WCTo!nccm- zAXqRw=%GHNbT+9#40Y1(ICwY6jCGiM{?|b~F`3am(}&OzqFOK)x;4yO;`EnS{&ney z$uZQ)3j6k%9=qEBM6%~xd$uttBhMjVY%DFq!h}y>Q13b1m5bMlDJ!6sa>=g>`>U7u zfh8z~lils6u;n-X_u2ja+KHpvZ6?rn=2ChpEc9a^Rx2gB<;54=n;*&m&W?{{f@nx@ ziC*#N=D-IwlSk!d#C{l8d+pzEABB9YtoSuI_2<EmP zo8|G*+dzf6{eVxY;_qZX&(&k=O%m(-3tv0H&QU?dbB*$4OMdm+)Lk2K=138ZAC5=? z5MmWOzW%rG$Vc>YVnKm~QywT$hBT>ET>qVVk*)l@KzSq$H}urv4k*57QtOQd2rF@* z^7)dSz?K9q-qca9${tU@C&nHzN(3e}{to4v62vhn-?)wIcOMRUqfW_@;3{oa^*wXn zw*bFcnl&cD3GST+<Xmr(lYtix7%0|R*s;d@StY)So4lI;yPqh!Nx0I%aYXd7f!>~8=bB*OO)4DiEuhu zw=Vv)+utzBicjA~a+Zpcj^f9ESRj7vSNQ(Kko~{<8Mptix_{NSkT7-5ewG13*!}*> ztpdv_A-t{-3tzSgu*8Fc-JqJsddH$Qrzqypp2KH0Qm!4nh?EV*nsQ#tP z?cd-1o5r_33tW0<0`^q*6HE53P4>Td3wQ&Vp#R$g+y65`n+xs#cN5fb=vU>qx%O&A zuU)@>2#Ca&h{%WtR`TuOkbkVH+j0MbDdQ6V<&UlH?$ay=lwfcAyI*UtHy7%gUADHi zK+?j<^DnWe}->{mnxX?Fr;piBN1 zOFlyY5m0oX><4uC->>L7ze`wHSTc`A+W}WlaJ|iyk;+^8OP%mvPbUsDrraScfg~3L zL&HlH(@#HQ*4JXeNx4Qr{PMp_7f8N3B~)ax^7qk9yaHSRfzEgL2mZ@wqD_4Y3k#c?(>ry36Q|~}IJV9$v~HR)JXoN#l{8wc z24;Ol&ibB#o1kB#}o%H|rwf^ItS-s6{ndaz2|I8cuFP{OZI&T3a3)kI> zBU>x!U%LEXC?)_g1fX+~PWQKS$ zh8s-(rFejZ4~{4esJ!g!H*OpTTx@qicvKQ(`EhQtfPk#2yy;?{LL}h1n}5%YI1AL= z(0~^y*gD?h{wve;9wp-a80cL<-qVgl(kDQ!8_;bv06p#Q!brX2+Gtds}HZdVPUM(fJ`L(R5U!ttNBH+P_{01UZd;>0KyDg>IbU znsr};NZ!mFS?Cnq2yi?&^aEBEsTCBU{DCFFSLX2`@nLF{)hB3C@~g2AAWZ3omVSLo z3#P%`LBVL^xj(k;JgENLe|&Ze0}bZG>+Z_+{T@k1P}A8sTheXbzJItb)NOIRHFUsO zuC2n&fln9j4FdLPyY{3@x6b=B(BhE;9=V#re~KDqitS4{bT#yV~>CT50mj@ zx_;ZkP!+F`?>EStOcZv%qyHj@8yaC~^y~u~4L5ucxCbUPSi^2HbL2!BVD2QQXuh&v z!CI8??s^4s_^jldC)%)4;>+6^_6RR=qjxc~l>(q?%E4to$^AidzxAPOsUuJfvCB9M z3udyYsXnFe;I)8_jO36<3{s$hQCf*0nu~e)bWVB#A1F;viOELIh8N>=a$5El+jX~W zGLuvluBnjwUm16L&ZcD5`0MZqwuR>6`e5bkfZ=4yCdQBzu0miFGo1h>LJ_jTa?!h- znGIdONLbdEZqoEE25J8{D`MNu$bAP(M-6_gm#b&Kfe2;!S!am81HI5 zeldbTM|~q*gQh27pJQNz`D?3&ch=r8&~#$uC7QL*5pMWHOMLqJbo*Mq31+_oOc7tZ zOzcqA9tJgv`{AIJHb~#8A)3k$I7aKO26VYm&(r1GEwNa zJuxkDO6g_Oq(H!$@*Wv*QdYzv`%oKPpYPxeJ3tyI<0QrLUv3LQJ5lTHTkGZ8 z-EDprM{ai-JBp+%0ve(Scg8XlY_cPD4sawn1G0z!{i7>@OT$g-ep5!_!!&in2##!y z>siYNMbWXR$h~%X4+elwsUikee%iBDowi*BReXcSSa30T-)AFrdqC9%d-r%7O=N~$ z)MRA$0q&dp>jn@)=F66Dd;|iBGhH=Joz`%?o|?*=B|sHX3TPrOlSH8E5&eNSS^MdL z5*PrB7=7{X$-h&Rll#TW(5k-=AO!R$hpO5-cr@$Z2CPSoPW$d_{8kKnABb4~hmE&> zY>)7p>gT$TUwFEja5ztq)R~!tI*;i!$$U}>WPmHW`SVoq zDj7ZCP*^Vrt6?>EhV~U}#-xHAVH?t`fu=a6Zk;#Mr)_TN4m+DxxJ-}94!B!l-tXor z1rXn*prB)w+GdQ>OHfrwU+&TFivl!q6#`n3rRRKiD=h1EGGY2`MKGh0kn+KeF*!t+ z4L+@GAB&*8p^|~isJ2e7q99;OU8LF(%S-U{oeP^JNPT7Zr`uEk&?mL9OWwu2E)>=B z@f$bBW7d$+QI;{BKc_fdN@73rFso_<@P6Nyu>f+C2!?m8)g#Wb4;{zlP`Ml#qwG-# zJ&|V|M}E}*AUSwLA$`^xfN>z;4mhf7mu2d(2r@3ub@tOWIERvJP9xhBCBRV@mkY+O zcq)9#H`mKdEjvATzIPBY-O6E>O=(!o&-{>@D;hU=r{<0*9U%Q*E<%urZqLX&c^ZLi zS*IEanRP#pO9tcS03Yn@=I zU`-}C;2vC3lyl*0{_LzWrFabwp9NQz$rsEV6iFpeyK=XwDqHBeDa2Bzu|+Q-C{M+6 zDL^$b$t#z_ElbQU*7J1jl_}JnLRh!%H0TD{?9qiO*6ri4{&!@rgYgig(dVRgH#Y$yQT`*S^e(i__AL-B!E%XojB@wn4kS1`|Ju^S? z_s&)4Iebkh-%|L6wa(j|vq2euGy;=x?373bFd30*TkFj^GbkAHiJ1q8DPSw z=48Bp9p&usJhH0)_|jVfkaazR$;N&RPzb|}$(NM?{*Z@Y*x}L%Ob<-u&9}9HtdVX( zV-F(0qakuw$6mL>Za3UCW&2i<)M*RD?N>oUa5}+@REb~FVyxGGn*m60*B%ZL0belN zPF;xOw=uvay697TJDe|wETC#eVjaOwWo3s68Y<-iy7jq~SGo&6Z4dAJxdXDt3mCkv z(wgN`HH+Rorg^`{hPIHn5Z@5uE_TxwD-lC)Eba(Vh4SHe9l5pq>!rNFm`WQ?d2t=v zyP!0a?^^*jp!W;HSlQR7T=r)@4cpGnMNe+v&ojLBd#@0TUqd|%KVK@2{q|&?grsM; z+vt2v2g;?gfhK&?HjP1+>FC*G=}sSwau;>pFT3McmXc}0d();*?>7}rNwvFnhv1H1 z%d$H+jR2aL2uLnj6KZhXCBkYv#=E>i6&F4gd->hBeN}kIexIQ*zP4zQSc=ZjQ5 z+GYMR?b|n*Zc~=v4!Gr}^}5bBa6#I)g^4O;pz`gdM*k;+9_fK2(grVdbf(c~-!>c1 zAbLG*?Uc$7AjlPi0_Mz$kqqY=rT6EH1bBfe21@SSi*h~Q_;UZONnd7ArlYlS)+fQo z!d(4p^$up`vx=cXm-u?x=C6G*eGlJ-V|{I)-*cVs>~*|M9y5>72!{jMQwTyCidk-= zuX8!e>mhcMlQ|}27Cd_}>Ceewu@ss(p7n}&ISmT(2%&X?njb##5j4{d^S(g9J=eQuO;`TwpF%H^JcbrezveW0jnX{^ z=|oROGNrQ@#WRXy+m>eua(&_`Sx0G6r&{zaRlwXeMBvoqx0cL8!{g73Bl%4UtTy9yP2scL--%OuI+;{e%oJ*s9{nh>&5t`&VeB>Nva;bb1!u#9i@>aZ9%*z< z5-U4u@6-Jt?ejaJwE0vtoRRr|Al>u!j^_p6Q7QVE58Y6G%h2gb^COpPQ*V@F&@mrU z7$p4f7#Th^^c(nQo|<2IKF_Zh5DvCaB5cl0rnpS>rhj>a&2*qVzR-h984sk1-QYt- z48^t;N$w{ILX9JeTn6y}5Sm+4eo#G;25cKNjYofF?|0*G>hL2SO+q7804Hvei_n)NMhEx% z%4kj-`r&|q*k!z||JuO9EiWw#9;!xj?>m7{(+M2NK7a4%v!0Thp-tP$E$Zia#%#^3h8$DY51VKFBB%vEMv)*zk={W>M0!H#h=m?N>Ah&gu^<*iL+>OZ1StVR2}MOgIw5pK zqy_1O7Rq;L-<@$+-F^4{^SiF~uV6xWp8L7WIp^5b%q_bh6xF&pZj&8&jg+|&{Q#DQvmi?&hN40}G}_?;z0(si?kdCp`}b7L^i06? z$0XIk3-TKqDTY|gT86`=N+G}3V=p#sqMs!uoi(~>s_)Y@{>vd;>fwRmuY8?LMb?ND z$hTI~{l~or3j;|tuW>x$q8kFKfyGgeYbs5*n=cQ7+-YrO3c1qwtBiOMwL*Q_Zr?9xq5Sxuz$lU`Q_8e`CLV zYxTYhbZ#+a(7czR?;&G+;+9!Bd8%84?C&;%W60S9qTQ)t9xB$IqY;q7@oddd0 zb*KJ8v@qTNG7l?ZS5=>h&A)MG3d9W$d66#>L&GJMh)WO-^LxhXAHe8~TZq%bB`83h zx{$PW*|Y6T`7vnzp5~Ze_Q)L(^T2;9ht7rFGAZwC zEI;)3JBX0~EJ(|g9v6`%+QgaO5q=CdHrV={3ONu8_? z$KwMTH_0a#_fu>N^*Kj+@-srHMLB`)eicsf(`U#es5637_19njjp&i(WR=qee-(0&&0m3yZ;X=RNn%vo`gVKDZB-Ie;mBPmt?fL!tsxRR?2{ys7j5o6{u zwEA0!Seah)GGZ(qah{s5AowaG?<^!?X(#NUOL;CWJ=5tIjy(@gia2J_U%$d=B+Mnh zY{VbQmPYs7M)fF{?V z5|q8X`2Rew%fet!En*r#LjL=7F2cFs4@i9%4c1$7DUeIl5x15JgW5ae)Ut4B(BQf> z>8;Y)M%%dI;h0^}eN^NnByCZemFDZ@l*Boiv**{&8U|Gs4~F!jKpnZ&F<6g;D;e!s z^d7@~!DSM!NFW|?e5hr-!%Nfqikv^-x}2*oCP;t+->Y_7l`y)g*4v(MPjl%Btmh>J z)Dz{xp?)Rd!K(UBXAE!Ee;a2=!H-iV+eCeza zOaP~kb2?ipP(3CQ>Tlp84mVb*T?hwZv@*(KtSKQO3gD$m!}#O*1c!+TYN*S?f1^o#2H^Vc}MWUHV`BNC88JlQlC5DDTf z)4#M2+x7JXB)$mJHaq%nig4F?j(Eg9xx4GzAuN4#?_K6-Q-bBx$(n7CVdEo~0;C=; z9y!f*(Zb>FZI|%~KZ~K)#w0%vc|p^5Qctn_OaOyEqTrhUhl}yuBgQIBMVHRg%f!%) zhJ*k*R{to>MPXAw(PvQ=GX~-)ueE>~ItE6vXc&nv@Gq*6?22u;*}f*`80W?B+F!JR zJA!4)v@Y{u9G!ISB{m;@4SIvuaX62pTCvbzq?p3!w9K_EcB_2qEE#A6#n+A;%!L__pE0>7w>uYU?YVia z2G&a!7EwFQ-9A|>XX*MHy(JUox=e6wpPxCT`@j0~)P1J{O)bQ@`Kr}8slxp$- z6>BHC2SP8h*e*i^VOAD8sJ3*S>8HBlH(7`k@ObgUo#MZn$&(th3PoByDZ&t!oT?+( zn`(%-={Oe?cBez#KAz?>@!DenCklP0dP+T;Pj%k+1dkwT=F3pII!O>w!;_l~!zMB53x27y1>XNKfd z{`Z>Ew;}t-S8pMJd}A6t@~!$bzt2#s4M1YO5^2QX+}t8(Dh#7l{o#@ms6^iAfFc^; z9uhQIacjg0zMY~a&M~Z9r!!~>eSi#l$EyYqk4##+S5CZpC@^_?Z@^-!HY?8%$7C7r z_=2UUtr^|87MxIC`MIwq1p*Oum33@M&av*4ci1uKajTQvWWRS)_tNJkorb$(i!|HN zgmb!tD3g}8k5bJKBOD-4qrg&((@#{Ar$2x}EKRNuREmLodL@srbW;cBk(-HY=G&Bk z?gQsc{9y&JY?DtI(~>Zpa%8x7e*-61AD!F}+JL7ujdz)?_zXXi^#L_z@1a%x#`kJA zY(pG6Ud>`-o?_+5$x0A`^noM2Q+5A2{jn}kFc?)?{jxuFPnYM)o&EYArmu@D2irg1 zMgHrpa&NZ(cD7<^_m8~aGE=s27H$agzMjXe$P&?yFU9U;c*GY0tfco!w{2||K_QL) z0CM+5n)h^{d{0izg;8uYmR(Q!HtaG`3ZKLji*sf7d(sDNkgO?xGkfa=% zylB?G*0*zeaM%1lo~iSj)51Cz$7aI%O)pWu@+ooElbqR45T2G!k0ga|`l|=ae+v60 zb-}D|5`C0R1w~h+y@7O*XQcC;!=1c;ncpK_0Y&T$c5(E z_FTjybx86azS17jYjH%}Lb4$YSO20w=SA%!Q z@J(+)7N|7*5wtdcq!Er0v630qIPo%iD!>xd;Zwzwz=`ySU2jlSXkosBLUK!CaN|0p z5woh6Qqk-X>qT@0__)f0bMO6Yxlf)dKQz$n$v)AV7TF#tm7~1yQA(dyVMCaxEChwJ z?%o_?cW!JBr%c!%w~Fe=dip_a=K@U^>uU@3k}Beo?Q5C%Wp^jMy0hoPVbt~8`p{mf zV83HY4hWTn3x_4HsP&qoim3bayoL5OFL*F;9WF!j9!mc~Rek(}Mv_}uQw+~>Eg&j)`+Xj>LK4i$>KfWn`z(68Y-!Fql(0~M%S zi#WqZr>q3t3ffu{$opKvsuMkhPQ$XRZMqVr0Iu#D?H9?4|E!5=y?5gmNahr%ShtRItFE`8?P?u0 zcI~Lybo93SWKnl~w?iat86+R(HzsjB>#>ye6R4o0+dB%O@Y%x%Mbb&(1P8LXd&y>i zZ=*D=1c1afw)i@s&~l3Dv)oq##>=M>5YvnsVw!uK&f_ch9G3Yg2JF5t9>6hPct?zP zXb&j1_sfsP53>j)jv)yJL#rDfgp=f$hT(}PK$!1z&b^m}vOf5(aF<;ee7NQk6`~hO zdmz>xZCg8*Grg=}uQOIM9UCd&^HSA*&Es;VUh{7P3x4ej#zHoEOD1&p=d5FUU@fnx zLI;u!>j(gX<4lJ9L?Um9*|mOeS`lLH{zri0IWJbie^F5NrWm176?cON?IH#Guvv+8 zuff*EJc>5|%{z)iclNIrIDlYS1mSDO{cl1Uo>PVc^Kf<_%-cT~cz6#_$r>Gx@9zVl z+-DGclsk{%-y9lkiW@t9Z#iyo{hc+)QYvc_?joRwl(SQ|-g+q)#L_x{M+_~2_yuoL zqNmP}*3K=Tug~7sAI2d#t1iu{Fh$wgtb97~<-@ZL5F8KbZ~Q#PaGJNn9DZR-78F=d0`3$P;MM#;(FE2%V>53n$LJR(|O{Q~-HMG-t< zSYf$VGNW_9Oz?ZnhH*h0GbuMR&%#a4U6a348QJ_BX9_*>R-2A+=^-h5IRRM!tfkdf zIReX)w%jLH{X8Kyp&N{Z&5#yPoym^Uy#vn%{DvPDI)rw~GBi`Ht&_;eNpk;LM)>{N z(wA6?o&&wwjiK`&gqfagD(6#~o8=vY+8NH|9j=tZ3J`xZRm|3KhA@UAFT%I`4tGSp z@Uo%Hi-o%M$SN;f*V6n}D*pae_&h+~#2zbJYW>eU;Q=SFRJW2#EOGW(hOeYKlgBG+ zuH!-!e7>5+#m^zCvm^~uKRsl7*16R0YwG~DL!4m%?`UtZ@tN}U7|n|0&J80W!CySsya5DFc759C{pA?nM%=FYxsrNIXTA@#a-$HF|ZuGyd z6FiLA)#<&@MpT9vUzkHen&{PCPO-pW&e@ARc!cW59*gMq{8SY_y}r=AY~30JC@I)B zF|=WkKAJ`kG>L9(5}U#|6^&wBN}9^vVTmQhYVq>p1G&r&tpnCycvdbu>mWRyjk;tH zzk7IS82{d9Wg3kdA|sacOqL5J(+`XH?u}$r?`AjmuE?HHFdQ-8coSEX#Hz>#c{R;=6Z5Cu z956Ox0*F%YFu}Q)Txb5?qWR5=r_mT1cGSUwXqvr{51`3bd8}t+Vhm;gG}w4*N_{+N zncpv)ulInc9h~tkB>5pFQJVr>B7(9D>CWHdYcBW^lZy>Kv=|mvh@lxG&gC zlc2I^X_&1W+>Y!@0$FrrJ)YgIBa209xbG_gf=A=!J`^^LSea@OGgp&&10jZtu|=Fg zRGT1zF5}{}{M{>8?QKV-ZGJ;iHN5+tS!8;OJJ}r0O2*-Sor%V2lpVIofk)xmf=->HO{r-wsj3{;X>reH7%EAVPnKDaL8gAn z&uz5ApJt*Dk4qqOs1+J98PGzmq~DIU`lm5B-ak1WY-Zhjdp0p6Is@@MYCm0t*Hp~Z z(YU$LBP969`IH_%KilOvjp+tz!WdQApeFbtxw3XbhJVmryx~UK3si*;k-i01;*_df zYM^FYu$fSNYvgZ>t_=>Ms6cY)WFmMNWEp}JWzi}SpeMm-&%^FSGRMU2U)N^Ca7K}O zv?7%w^Oxv+RF3nD)d!SSpKk7G@iecq8M}VagSrIhlN%3d-ba}@75Zi?ASVu5qcq0~ zr4uNCShMWzJ<};q$gHOTSAyAQ`wE)0@%U1a64&2LXMdi)|M=tm17_k3)l*NO{qmMr zcHL#?miAMw$Sn!hFFa|)X-hA9;nLZU+0n6VerwKw z?B(-LWPMiX#s%eXV90$bcw{w7RT(Eg`OtwiDG)S4x1S?M1s-L_>xRPo1rcAr_7)Ro zQZ*tVVh%1W&Mlm34mE-H6lN|MRU5Gn<2aA@o?Wf9I5Duov2)(q;6xKKuWZR+S%zH* zI*{`ybBbOv5zs2F=6A-|TUl|@)#QlRbYCfZ!g4_7L?t$pISNw4(MYHtb&yMe#_-k5 z)eDu#DILYANaAO`R2q6@79X~TU~9kv2*zVG_vTI42E2GXbC@i+7;pMsCMeO&+pdx5 z`Qkf6Tdc6dR=2tx=lYOZCL7)Gx^46Q&T8n%wubX}!5ygp6_fPfm~y>#T8nMK zL`Lq-VO!NCoWa;Ab32>m0pho++0S1YhW?uEVHp~ABJex*U9|d@FYlk^F6Wk!N3p~x zq~dt;?Y`|C{GUW+B&~!i*`*lwQMZ9h^Ros^s;z!M9OB*BR=VRy#$3K{i(wVTFGtf00BA3r2l!41{hQGLh@sY%Qn++d2I8G**S!qgEt=NhPGoS~KaCFNEQB)h?4m=szo0@Tf3ox0ze%NUA=%w)K60OiOm+6nEL} zKi~g;3jOO5RMTPK+4ti4vzUK#vj2;3?T`fp9>&zYeAREG{-3@&0X^bjX{>Mh-4^h# zuk){KFa%v<`#Ot{*KhvkH~Hr;KZgS`mX5snp?~-AetHdR!TZ4l4@RA0{@=&g&=`!< ziIM9!{?ozv_BnQPyG?Lp%}eUW~gIYf9c!Kd5I-)NsrIj{oT0~{+XRu!saV7b*uF% zRqwv7sLRjTrrGB~pQ*>}Zc~G3*z2UlU4MRw<2c)|Zim+nRc(HMrSV~~S6y3HPHpMC zQhM(zYIyz0u=;jMdrv(It0Ao|3rTMT?uEMP4%b`!`DQp~ucOs|(HjZhR{Y;z8OB$E z{M0(_!XqnCaM@^XR^9r#SOBceKAV1Q`{C1I_--7?!;wt8mq69cYi;=m-=BjVrZxf) z4np5G&E`M<>fi5*ucWH4)YBShmaPly8`o)&o~0fvM{p}7D*6zPpm2dgogN2X5P(%maO`4RJDCQk z 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 L+kVd5wEx6^*B&Bw literal 0 HcmV?d00001 diff --git a/image-2.png b/image-2.png new file mode 100644 index 0000000000000000000000000000000000000000..cc63740ff156b324ddcefce17d0a934369f6819c GIT binary patch literal 68576 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

vJ|=M++To{J~4du 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

yIu$uGHX}~Ws(hl9WnoEllywsCFe`7t4 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

8_wtiHbL*!D?PX42eU}5_I(7bBG9(^dGpAcJ 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 literal 0 HcmV?d00001 diff --git a/src/backend/api/routes/images.py b/src/backend/api/routes/images.py index 9b6ee06..88dbdb1 100644 --- a/src/backend/api/routes/images.py +++ b/src/backend/api/routes/images.py @@ -41,9 +41,11 @@ async def get_image_by_id( ): path_str = doc["metadata"]["paths"]["processed"] if doc["metadata"]["remote"]: - s3_client = boto3.session.Session().client('s3') + s3_client = boto3.session.Session().client("s3") local_dir = f"{doc['metadata']['processed_dir']}/{path_str}" - helpers.download_file(s3_client, doc["metadata"]["bucket"], path_str, local_dir) + helpers.download_file( + s3_client, doc["metadata"]["bucket"], path_str, local_dir + ) path_str = local_dir else: raise HTTPException( diff --git a/src/backend/api/routes/search.py b/src/backend/api/routes/search.py index 2f6736e..2ea049c 100644 --- a/src/backend/api/routes/search.py +++ b/src/backend/api/routes/search.py @@ -1,3 +1,4 @@ +import datetime import logging from io import BytesIO @@ -7,6 +8,7 @@ from ...models.schemas import SearchResponse, SearchResult from ...services.clip_service import clip_service from ...services.embedding_service import embedding_service +from ...services.metadata_search_service import metadata_search_service logger = logging.getLogger(__name__) router = APIRouter(prefix="/api/search", tags=["search"]) @@ -17,6 +19,7 @@ async def search_by_text( query: str, limit: int = Query(30, description="Number of results per page"), page: int = Query(1, description="Page number for pagination"), + filepath_search_term: str = Query("", description="Substring to filter file paths"), ): """Search for similar content using text query.""" offset = (page - 1) * limit @@ -28,7 +31,11 @@ async def search_by_text( text_embedding = clip_service.encode_text(query) logit_scale = clip_service.model.logit_scale.exp().item() raw_results = embedding_service.search( - text_embedding, logit_scale=logit_scale, limit=limit, offset=offset + text_embedding, + logit_scale=logit_scale, + limit=limit, + offset=offset, + filepath_search_term=filepath_search_term, ) search_results = [ @@ -70,3 +77,30 @@ async def search_by_image( except Exception as e: logger.error(f"Error in image search: {str(e)}") return SearchResponse(results=[]) + + +@router.get("/date", response_model=SearchResponse) +async def search_by_date( + query: datetime.date, + limit: int = Query(30, description="Number of results per page"), + page: int = Query(1, description="Page number for pagination"), + searchNearDate: bool = Query( + False, description="Whether to search for dates near the target date" + ), +): + """Search for similar content using date query.""" + offset = (page - 1) * limit + + try: + raw_results = metadata_search_service.date_search( + query, limit=limit, offset=offset, search_near_date=searchNearDate + ) + + search_results = [ + SearchResult(id=result["id"], score=1, metadata=result["metadata"]) + for result in raw_results + ] + return SearchResponse(results=search_results) + except Exception as e: + logger.error(f"Error in date search: {str(e)}") + return SearchResponse(results=[]) diff --git a/src/backend/main.py b/src/backend/main.py index 97d7d3b..aa7778a 100644 --- a/src/backend/main.py +++ b/src/backend/main.py @@ -21,6 +21,7 @@ REMOTE_FILES = False + @asynccontextmanager async def lifespan(app): logger.info("Initializing services...") @@ -34,7 +35,7 @@ async def lifespan(app): # Clean up cached files downloaded from S3 if REMOTE_FILES: - os.system(f'rm -rf {str(settings.processed_data_dir)}/*') + os.system(f"rm -rf {str(settings.processed_data_dir)}/*") app = FastAPI( diff --git a/src/backend/services/embedding_service.py b/src/backend/services/embedding_service.py index 104786a..87d5767 100644 --- a/src/backend/services/embedding_service.py +++ b/src/backend/services/embedding_service.py @@ -5,6 +5,7 @@ from typing import Any, Dict, List, Optional import torch +import numpy as np from ..core.config import settings @@ -99,16 +100,45 @@ def get_document_by_id(self, doc_id: str) -> Optional[Dict[str, Any]]: return None + def filepath_filter(self, filepath_substring: str) -> torch.Tensor: + """Create a metadata filter for file path substring matching""" + metadata_arr = np.array( + [ + self.metadata[item_id].get("paths", {}).get("original", "") + for item_id in self.item_ids + ] + ) + matching_indices = np.where( + np.char.find(metadata_arr.astype(str), filepath_substring) != -1 + )[0] + return torch.tensor(matching_indices, dtype=torch.long) + def search( self, query_embedding: torch.Tensor, logit_scale: Optional[float] = None, limit: int = 20, offset: int = 0, + filepath_search_term: str = "", ) -> List[Dict[str, Any]]: """Search for similar items using query embedding with pagination""" try: - similarities = torch.matmul(self.embeddings, query_embedding.t()).squeeze() + if filepath_search_term != "": + valid_indices = self.filepath_filter(filepath_search_term) + + if len(valid_indices) == 0: + return [] # No items match the filter + + # Filter embeddings to only valid ones + filtered_embeddings = self.embeddings[valid_indices] + similarities = torch.matmul( + filtered_embeddings, query_embedding.t() + ).squeeze() + else: + valid_indices = None + similarities = torch.matmul( + self.embeddings, query_embedding.t() + ).squeeze() if logit_scale is not None: similarities = similarities * logit_scale @@ -127,7 +157,14 @@ def search( for idx, score in zip( paginated_indices.tolist(), paginated_scores.tolist() ): - idx_int = int(idx) + # Map back to original index if we filtered + if valid_indices is not None: + original_idx = valid_indices[idx].item() + else: + original_idx = idx + + idx_int = int(original_idx) + if idx_int >= len(self.item_ids): logger.warning( f"Index {idx_int} out of range for item_ids of length {len(self.item_ids)}" diff --git a/src/backend/services/metadata_search_service.py b/src/backend/services/metadata_search_service.py new file mode 100644 index 0000000..8a6527b --- /dev/null +++ b/src/backend/services/metadata_search_service.py @@ -0,0 +1,71 @@ +from datetime import datetime +import json +import logging +from pathlib import Path + +from ..core.config import settings + +logger = logging.getLogger(__name__) + + +class MetadataSearchService: + def __init__(self): + self.embeddings_dir = Path(settings.embeddings_dir) + self.embeddings = None + self.item_ids = None + self.metadata = None + self.is_loaded = False + + def load_metadata(self) -> None: + """Load metadata from the embeddings directory""" + if self.is_loaded: + logger.info("Metadata already loaded") + return + + try: + metadata_path = self.embeddings_dir / "metadata.json" + + logger.info(f"Looking for metadata at {metadata_path}") + + if metadata_path.exists(): + with open(metadata_path, "r") as f: + self.metadata = json.load(f) + logger.info(f"Loaded metadata for {len(self.metadata)} items") + else: + self.metadata = {} + logger.warning("Metadata file not found, proceeding without metadata.") + + except Exception as e: + logger.error(f"Error loading metadata: {str(e)}") + raise + + def date_search(self, target_date, limit=30, offset=0, search_near_date=False): + """Search for items matching the target date""" + if not self.is_loaded: + self.load_metadata() + + results = [] + for item_id, data in self.metadata.items(): + item_date_str = data.get("date") + if item_date_str: + try: + item_date = datetime.strptime( + item_date_str, "%Y-%m-%d %H:%M:%S" + ).date() + if search_near_date: + delta = abs((item_date - target_date).days) + if delta <= 30: # within a month + results.append({"id": item_id, "metadata": data}) + elif item_date == target_date: + results.append({"id": item_id, "metadata": data}) + except ValueError: + logger.error( + f"Failed to parse date for item {item_id}: {item_date_str}" + ) + + # Apply offset and limit + results = results[offset : offset + limit] + return results + + +metadata_search_service = MetadataSearchService() diff --git a/src/backend/utils/helpers.py b/src/backend/utils/helpers.py index ac777d4..54022bd 100644 --- a/src/backend/utils/helpers.py +++ b/src/backend/utils/helpers.py @@ -27,17 +27,14 @@ def load_config(config_path=None): return config -def download_file( - client: Any, - bucket: str, - filename: str, - destination: str): + +def download_file(client: Any, bucket: str, filename: str, destination: str): # Get the directory path (everything except the filename) directory = os.path.dirname(destination) - + # Create the directory structure if it doesn't exist # exist_ok=True means no error if directory already exists if directory: # Only create if there's actually a directory path os.makedirs(directory, exist_ok=True) - + client.download_file(bucket, filename, destination) diff --git a/src/frontend/photographs/src/App.jsx b/src/frontend/photographs/src/App.jsx index dd1885a..5e96abb 100644 --- a/src/frontend/photographs/src/App.jsx +++ b/src/frontend/photographs/src/App.jsx @@ -2,20 +2,22 @@ import React, { useState, useEffect, useCallback, useRef } from 'react'; import SearchBar from './components/SearchBar'; import { ResultsPerPageDropdown } from './components/Pagination'; import SearchResults from './components/SearchResults'; -import { searchByText, searchByImage, getEmbeddingStats } from './services/api'; +import { searchByText, searchByImage, getEmbeddingStats, searchByDate } from './services/api'; import './App.css'; function App() { const [photos, setPhotos] = useState([]); const [searchQuery, setSearchQuery] = useState(''); + const [filepathSearchTerm, setFilepathSearchTerm] = useState(''); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const searchInputRef = useRef(null); - const [searchMode, setSearchMode] = useState('text'); // 'text' or 'image' + const [searchMode, setSearchMode] = useState('text'); // 'text', 'image', 'date' const [uploadedImage, setUploadedImage] = useState(null); const [hasMore, setHasMore] = useState(false); const [currentPage, setCurrentPage] = useState(1); const [resultsPerPage, setResultsPerPage] = useState(50); + const [searchNearDate, setSearchNearDate] = useState(false); const [embeddingCount, setEmbeddingCount] = useState(null); useEffect(() => { @@ -51,7 +53,7 @@ function App() { })); }; - const handleSearchByText = useCallback(async (query) => { + const handleSearchByText = useCallback(async (query, filepathSearchTerm) => { if (!query.trim()) { setError('Please enter a search term'); return; @@ -61,9 +63,10 @@ function App() { setError(null); setSearchMode('text'); setSearchQuery(query); + setFilepathSearchTerm(filepathSearchTerm); try { - const results = await searchByText(query, resultsPerPage, currentPage); + const results = await searchByText(query, resultsPerPage, currentPage, filepathSearchTerm); setPhotos(formatPhotosForGallery(results)); setHasMore(results.length >= resultsPerPage); } catch (error) { @@ -91,13 +94,39 @@ function App() { } }, [resultsPerPage, currentPage]); + const handleSearchByDate = useCallback(async (query, searchNearDate) => { + if (!query.trim()) { + setError('Please enter a search term'); + return; + } + + setIsLoading(true); + setError(null); + setSearchMode('date'); + setSearchQuery(query); + setSearchNearDate(searchNearDate); + + try { + const results = await searchByDate(query, resultsPerPage, currentPage, searchNearDate); + setPhotos(formatPhotosForGallery(results)); + setHasMore(results.length >= resultsPerPage); + } catch (error) { + console.error('Error performing search:', error); + setError('Date search failed. Please try again.'); + } finally { + setIsLoading(false); + } +}, [resultsPerPage, currentPage]); + useEffect(() => { if (searchMode === 'text' && searchQuery.trim()) { - handleSearchByText(searchQuery); + handleSearchByText(searchQuery, filepathSearchTerm); } else if (searchMode === 'image' && uploadedImage) { handleSearchByImage(uploadedImage); + } else if (searchMode === 'date' && searchQuery.trim()) { + handleSearchByDate(searchQuery, searchNearDate); } - }, [currentPage, resultsPerPage, searchMode, searchQuery, uploadedImage, handleSearchByText, handleSearchByImage]); + }, [currentPage, resultsPerPage, searchMode, searchQuery, searchNearDate, uploadedImage, filepathSearchTerm, handleSearchByText, handleSearchByImage, handleSearchByDate]); const handleSearchModeChanged = useCallback((mode) => { setSearchMode(mode); @@ -121,10 +150,15 @@ function App() { setSearchMode={handleSearchModeChanged} searchQuery={searchQuery} setSearchQuery={setSearchQuery} + searchNearDate={searchNearDate} + setSearchNearDate={setSearchNearDate} uploadedImage={uploadedImage} setUploadedImage={setUploadedImage} + filepathSearchTerm={filepathSearchTerm} + setFilepathSearchTerm={setFilepathSearchTerm} onSearchByText={handleSearchByText} onSearchByImage={handleSearchByImage} + onSearchByDate={handleSearchByDate} /> + <> +
Limit to file paths containing:
+ setFilepathSearchTerm(e.target.value)} + /> + + + ) +} + +export default FilterBar; \ No newline at end of file diff --git a/src/frontend/photographs/src/components/SearchBar.css b/src/frontend/photographs/src/components/SearchBar.css index 85b75c3..a5c9fd6 100644 --- a/src/frontend/photographs/src/components/SearchBar.css +++ b/src/frontend/photographs/src/components/SearchBar.css @@ -19,6 +19,7 @@ transition: border-color 0.3s; background-color: #2c2c2c; color: #f8f5f0; + width: 90%; } .search-input::placeholder { @@ -193,6 +194,33 @@ color: #fff; } +.date-search-block { + display: flex; + flex-direction: column; + width: 100%; + align-items: flex-start; + justify-content: center; + gap: 12px; +} + +.near-date-checkbox-container { + display: flex; + flex-direction: row; + align-items: flex-start; + justify-content: flex-start; +} + +.include-near-date { + display: flex; + align-items: center; + justify-content: center; + accent-color: #8b5a2b; + font-size: 2rem; + margin: 5; + width: 20px; + height: 20px; +} + @media (max-width: 600px) { .search-bar form { flex-direction: column; @@ -203,3 +231,10 @@ padding: 12px; } } + +.vertical-stack { + display: flex; + flex-direction: column; + gap: 10px; + width: 100%; +} diff --git a/src/frontend/photographs/src/components/SearchBar.jsx b/src/frontend/photographs/src/components/SearchBar.jsx index 02ea3d4..c6ac32b 100644 --- a/src/frontend/photographs/src/components/SearchBar.jsx +++ b/src/frontend/photographs/src/components/SearchBar.jsx @@ -1,5 +1,6 @@ import React, { useState } from 'react'; import './SearchBar.css'; +import FilterBar from './FilterBar'; function SearchBar({ inputRef, @@ -9,8 +10,13 @@ function SearchBar({ setSearchQuery, uploadedImage, setUploadedImage, + filepathSearchTerm, + setFilepathSearchTerm, onSearchByText, onSearchByImage, + onSearchByDate, + searchNearDate, + setSearchNearDate, }) { const [previewUrl, setPreviewUrl] = useState(null); @@ -18,9 +24,11 @@ function SearchBar({ e.preventDefault(); if (searchMode === 'text') { - onSearchByText(searchQuery); + onSearchByText(searchQuery, filepathSearchTerm); } else if (searchMode === 'image' && uploadedImage) { onSearchByImage(uploadedImage); + } else if (searchMode === 'date') { + onSearchByDate(searchQuery, searchNearDate); } }; @@ -48,13 +56,14 @@ function SearchBar({ }; const switchMode = (mode) => { + if (mode === searchMode) return; setSearchMode(mode); - if (mode === 'text') { + if (mode !== 'image') { clearImage(); - } else { - setSearchQuery(''); - } + } + setSearchQuery(''); + }; return ( @@ -74,26 +83,40 @@ function SearchBar({ > Image Search +
{searchMode === 'text' ? ( - <> - setSearchQuery(e.target.value)} - placeholder="Search historical photographs..." - className="search-input" - aria-label="Search photographs" +
+
+ setSearchQuery(e.target.value)} + placeholder="Search historical photographs..." + className="search-input" + aria-label="Search photographs" + /> + +
+ - - - ) : ( +
+ + ) : (searchMode === 'image' ? (
{!previewUrl ? (
@@ -130,7 +153,36 @@ function SearchBar({ Find Similar
- )} + ) : ( + <> +
+ setSearchQuery(e.target.value)} + placeholder="Search historical photographs..." + className="search-input" + aria-label="Search photographs" + /> +
+ setSearchNearDate(e.target.checked)} + id="near-date-checkbox" + className="include-near-date" + aria-label="Include photographs taken near this date" + /> + +
+
+ + + ))} {searchMode === 'text' && ( diff --git a/src/frontend/photographs/src/services/api.js b/src/frontend/photographs/src/services/api.js index 388be29..f170a77 100644 --- a/src/frontend/photographs/src/services/api.js +++ b/src/frontend/photographs/src/services/api.js @@ -5,12 +5,13 @@ const API_URL = import.meta.env.API_BASE_URL; * @param {string} query - The text query * @param {number} limit - Maximum number of results to return (default: 50) * @param {number} page - Page number for pagination (default: 1) + * @param {string} filepathSearchTerm - Substring to filter file paths (default: '') * @returns {Promise} - Array of search results */ -export const searchByText = async (query, limit = 50, page = 1) => { +export const searchByText = async (query, limit = 50, page = 1, filepathSearchTerm = '') => { try { const pageParam = Math.max(1, parseInt(page) || 1); - const response = await fetch(`${API_URL}/api/search/text?query=${encodeURIComponent(query)}&limit=${limit}&page=${pageParam}`); + const response = await fetch(`${API_URL}/api/search/text?query=${encodeURIComponent(query)}&limit=${limit}&page=${pageParam}&filepath_search_term=${encodeURIComponent(filepathSearchTerm)}`); if (!response.ok) { throw new Error(`API error: ${response.status}`); @@ -74,3 +75,28 @@ export const getEmbeddingStats = async () => { throw error; } }; + +/** + * Search for similar photographs by date + * @param {string} query - The date query + * @param {number} limit - Maximum number of results to return (default: 50) + * @param {number} page - Page number for pagination (default: 1) + * @returns {Promise} - Array of search results + */ +export const searchByDate = async (query, limit = 50, page = 1, searchNearDate = false) => { + try { + const pageParam = Math.max(1, parseInt(page) || 1); + console.log('searchByDate called with searchNearDate:', searchNearDate); + const response = await fetch(`${API_URL}/api/search/date?query=${encodeURIComponent(query)}&limit=${limit}&page=${pageParam}&searchNearDate=${searchNearDate}`); + + if (!response.ok) { + throw new Error(`API error: ${response.status}`); + } + + const { results } = await response.json(); + return results; + } catch (error) { + console.error('Error searching photos:', error); + throw error; + } +}; \ No newline at end of file diff --git a/src/models/clip/generate_embeddings.py b/src/models/clip/generate_embeddings.py index 39d54e7..f04ec01 100644 --- a/src/models/clip/generate_embeddings.py +++ b/src/models/clip/generate_embeddings.py @@ -16,6 +16,9 @@ import PyPDF2 import base64 import argparse +from PIL import Image +from datetime import datetime + from transformers import CLIPModel, CLIPProcessor @@ -72,7 +75,7 @@ def process_pdf( timing_info: Dict[str, float], use_remote=False, bucket="", - file="" + file="", ): """Process a PDF file and generate embeddings for each page""" try: @@ -96,6 +99,13 @@ def process_pdf( with open(file_path, "rb") as f: pdf = PyPDF2.PdfReader(f) n_pages = len(pdf.pages) + metadata = pdf.metadata + if metadata and "/CreationDate" in metadata: + pdf_date = datetime.strptime( + metadata["/CreationDate"], "%Y:%m:%d %H:%M:%S" + ) + else: + pdf_date = None except Exception as e: logger.error(f"Error reading PDF metadata: {file_path}, error: {e}") return None @@ -153,15 +163,19 @@ def process_pdf( "type": "pdf_page", "page": i, "n_pages": n_pages, + "date": pdf_date.strftime("%Y-%m-%d %H:%M:%S") if pdf_date else None, "paths": { "original": str(file_path), - "processed": str(pdf_processed_dir / f"{i}.jpg") - if not use_remote else f"{file}", + "processed": ( + str(pdf_processed_dir / f"{i}.jpg") + if not use_remote + else f"{file}" + ), "thumbnail": str(pdf_thumbnails_dir / f"{i}.jpg"), }, "remote": use_remote, "bucket": bucket, - "processed_dir": str(processed_dir) + "processed_dir": str(processed_dir), } results.append((item_id, embedding, metadata)) @@ -182,7 +196,7 @@ def process_image( timing_info: Dict[str, float], use_remote=False, bucket="", - file="" + file="", ): """Process an image file and generate its embedding""" try: @@ -193,7 +207,7 @@ def process_image( thumbnail.thumbnail((400, 400), Image.Resampling.LANCZOS) thumbnail_path = thumbnails_dir / f"{file_path.stem}.jpg" thumbnail.save(thumbnail_path, "JPEG", quality=80) - + if not use_remote: processed_image = image.copy() processed_image.thumbnail((1920, 1920), Image.Resampling.LANCZOS) @@ -213,19 +227,39 @@ def process_image( .decode("utf-8") .rstrip("=") ) + image_date = None + + with Image.open(file_path) as img: + img.verify() # Verify that it is, in fact, an image + exif_data = img._getexif() + if exif_data: + # Exif tag 36867 corresponds to 'DateTimeOriginal' + datetime_original_tag = 306 + if datetime_original_tag in exif_data: + datetime_str = exif_data[datetime_original_tag] + # Convert the string to a datetime object + try: + image_date = datetime.strptime( + datetime_str, "%Y:%m:%d %H:%M:%S" + ) + except ValueError: + logger.error( + f"Failed to parse date from {image}: {datetime_str}" + ) + image_date = None metadata = { "file_name": file_path.name, "type": "image", + "date": image_date.strftime("%Y-%m-%d %H:%M:%S") if image_date else None, "paths": { "original": str(file_path), - "processed": str(processed_image_path) - if not use_remote else f"{file}", + "processed": str(processed_image_path) if not use_remote else f"{file}", "thumbnail": str(thumbnail_path), }, "remote": use_remote, "bucket": bucket, - "processed_dir": str(processed_dir) + "processed_dir": str(processed_dir), } return [(item_id, embedding[0], metadata)] @@ -319,15 +353,17 @@ def process_files( ) -def process_remote_files(model: Any, - processor: Any, - device: str, - raw_data_dir: Path, - processed_dir: Path, - thumbnails_dir: Path, - bucket: str, - prefix: str, - timing_info: Dict[str, float]) -> ProcessingResult: +def process_remote_files( + model: Any, + processor: Any, + device: str, + raw_data_dir: Path, + processed_dir: Path, + thumbnails_dir: Path, + bucket: str, + prefix: str, + timing_info: Dict[str, float], +) -> ProcessingResult: """Process all files in the raw data directory""" logger.info(f"Looking for files in {bucket}/{prefix}") @@ -337,47 +373,71 @@ def process_remote_files(model: Any, file_paths = [Path(file) for file in files] supported_extensions = { - 'pdf': ['pdf'], - 'image': ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'tiff', 'webp'] + "pdf": ["pdf"], + "image": ["jpg", "jpeg", "png", "gif", "bmp", "tiff", "webp"], } - + files_to_process = [] skipped_items_count = 0 failed_items_count = 0 for file_path in file_paths: - ext = file_path.suffix.lower().lstrip('.') - is_image = ext in supported_extensions['image'] - is_pdf = ext in supported_extensions['pdf'] + ext = file_path.suffix.lower().lstrip(".") + is_image = ext in supported_extensions["image"] + is_pdf = ext in supported_extensions["pdf"] - if is_image or is_pdf and settings.collection_type != 'photographs': + if is_image or is_pdf and settings.collection_type != "photographs": files_to_process.append(file_path) else: skipped_items_count += 1 - + logger.info(f"Found {len(files_to_process)} eligible files to process.") - + if not files_to_process: logger.warning(f"No files found in {bucket}") return ProcessingResult({}, {}, skipped_items_count, failed_items_count) - + embeddings = {} metadata = {} - + for i, file_path in enumerate(file_paths): try: - ext = file_path.suffix.lower().lstrip('.') - is_image = ext in supported_extensions['image'] - is_pdf = ext in supported_extensions['pdf'] + ext = file_path.suffix.lower().lstrip(".") + is_image = ext in supported_extensions["image"] + is_pdf = ext in supported_extensions["pdf"] (raw_data_dir / prefix).mkdir(parents=True, exist_ok=True) local_dir = f"{raw_data_dir}/{files[i]}" util.download_file(client, bucket, files[i], local_dir) if is_pdf: - results = process_pdf(local_dir, raw_data_dir, model, processor, device, processed_dir, thumbnails_dir, timing_info, True, bucket, files[i]) + results = process_pdf( + local_dir, + raw_data_dir, + model, + processor, + device, + processed_dir, + thumbnails_dir, + timing_info, + True, + bucket, + files[i], + ) elif is_image: - results = process_image(local_dir, raw_data_dir, model, processor, device, processed_dir, thumbnails_dir, timing_info, True, bucket, files[i]) + results = process_image( + local_dir, + raw_data_dir, + model, + processor, + device, + processed_dir, + thumbnails_dir, + timing_info, + True, + bucket, + files[i], + ) Path.unlink(raw_data_dir / file_path) - + if results: for item_id, embedding, metadata_item in results: embeddings[item_id] = embedding @@ -387,22 +447,36 @@ def process_remote_files(model: Any, except Exception as e: logger.error(f"Error processing {file_path}: {e}") failed_items_count += 1 - - return ProcessingResult(embeddings, metadata, skipped_items_count, failed_items_count) + + return ProcessingResult( + embeddings, metadata, skipped_items_count, failed_items_count + ) + def parse_args(): parser = argparse.ArgumentParser() - parser.add_argument("--use_remote", action='store_true', - help="Whether to use a remote set of inputs.") - parser.add_argument("--bucket", type=str, default="", help="The name of the bucket where the images are stored") - parser.add_argument("--prefix", type=str, default="", help="The prefix where the images are stored") + parser.add_argument( + "--use_remote", + action="store_true", + help="Whether to use a remote set of inputs.", + ) + parser.add_argument( + "--bucket", + type=str, + default="", + help="The name of the bucket where the images are stored", + ) + parser.add_argument( + "--prefix", type=str, default="", help="The prefix where the images are stored" + ) args = parser.parse_args() return args.use_remote, args.bucket, args.prefix + def main(): start_time = time.time() - + # Get command line arguments USE_REMOTE, BUCKET, PREFIX = parse_args() @@ -428,20 +502,20 @@ def main(): model = CLIPModel.from_pretrained(MODEL_ID).to(DEVICE) processor = CLIPProcessor.from_pretrained(MODEL_ID) - - embedding_timing_info = {'total_duration': 0.0} + + embedding_timing_info = {"total_duration": 0.0} if USE_REMOTE: result = process_remote_files( - model, - processor, - DEVICE, - RAW_DATA_DIR, - PROCESSED_DIR, - THUMBNAILS_DIR, - BUCKET, - PREFIX, - embedding_timing_info + model, + processor, + DEVICE, + RAW_DATA_DIR, + PROCESSED_DIR, + THUMBNAILS_DIR, + BUCKET, + PREFIX, + embedding_timing_info, ) else: result = process_files( diff --git a/src/models/clip/util.py b/src/models/clip/util.py index 6213736..fdbe3fd 100644 --- a/src/models/clip/util.py +++ b/src/models/clip/util.py @@ -2,36 +2,30 @@ from typing import Any import os + def create_client(): - client = boto3.session.Session().client('s3') + client = boto3.session.Session().client("s3") return client -def get_file_names( - client: Any, - bucket: str, - prefix: str): - - paginator = client.get_paginator('list_objects_v2') + +def get_file_names(client: Any, bucket: str, prefix: str): + + paginator = client.get_paginator("list_objects_v2") pages = paginator.paginate(Bucket=bucket, Prefix=prefix) filenames = [] for page in pages: - for obj in page['Contents']: + for obj in page["Contents"]: filenames.append(obj["Key"]) return filenames -def download_file( - client: Any, - bucket: str, - filename: str, - destination: str): + +def download_file(client: Any, bucket: str, filename: str, destination: str): # Get the directory path (everything except the filename) directory = os.path.dirname(destination) - + # Create the directory structure if it doesn't exist # exist_ok=True means no error if directory already exists if directory: # Only create if there's actually a directory path os.makedirs(directory, exist_ok=True) - - client.download_file(bucket, filename, destination) - + client.download_file(bucket, filename, destination) From f443287870c4e6da90d655b51d17b46691bf4d15 Mon Sep 17 00:00:00 2001 From: EC2 Default User Date: Tue, 9 Dec 2025 00:20:33 +0000 Subject: [PATCH 4/4] fix: fixed aws access in backend --- .gitignore | 3 +++ src/backend/api/routes/images.py | 10 +++++++--- src/models/clip/generate_embeddings.py | 26 ++++++++++++++++++++++++++ src/models/clip/util.py | 5 +++-- 4 files changed, 39 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index e09d756..781c782 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,9 @@ data/thumbnails/* !data/processed/.gitkeep !data/embeddings/.gitkeep !data/thumbnails/.gitkeep +data--aip +data--SephardicStudies + # Model files *.pth *.pt diff --git a/src/backend/api/routes/images.py b/src/backend/api/routes/images.py index 9b6ee06..b16e37a 100644 --- a/src/backend/api/routes/images.py +++ b/src/backend/api/routes/images.py @@ -4,6 +4,7 @@ from fastapi.responses import FileResponse import boto3 +import os from src.backend.services.embedding_service import embedding_service import src.backend.utils.helpers as helpers @@ -41,10 +42,13 @@ async def get_image_by_id( ): path_str = doc["metadata"]["paths"]["processed"] if doc["metadata"]["remote"]: - s3_client = boto3.session.Session().client('s3') local_dir = f"{doc['metadata']['processed_dir']}/{path_str}" - helpers.download_file(s3_client, doc["metadata"]["bucket"], path_str, local_dir) - path_str = local_dir + if os.path.exists(local_dir): + path_str = local_dir + else: + s3_client = boto3.session.Session().client('s3') + helpers.download_file(s3_client, doc["metadata"]["bucket"], path_str, local_dir) + path_str = local_dir else: raise HTTPException( status_code=404, detail="Image path not found in document metadata" diff --git a/src/models/clip/generate_embeddings.py b/src/models/clip/generate_embeddings.py index 39d54e7..8d3eddb 100644 --- a/src/models/clip/generate_embeddings.py +++ b/src/models/clip/generate_embeddings.py @@ -16,6 +16,9 @@ import PyPDF2 import base64 import argparse +from PIL import Image +from datetime import datetime + from transformers import CLIPModel, CLIPProcessor @@ -96,6 +99,11 @@ def process_pdf( with open(file_path, "rb") as f: pdf = PyPDF2.PdfReader(f) n_pages = len(pdf.pages) + metadata = pdf.metadata + if metadata and "/CreationDate" in metadata: + pdf_date = datetime.strptime(metadata["/CreationDate"], '%Y:%m:%d %H:%M:%S') + else: + pdf_date = None except Exception as e: logger.error(f"Error reading PDF metadata: {file_path}, error: {e}") return None @@ -153,6 +161,7 @@ def process_pdf( "type": "pdf_page", "page": i, "n_pages": n_pages, + "date": pdf_date.strftime('%Y-%m-%d %H:%M:%S') if pdf_date else None, "paths": { "original": str(file_path), "processed": str(pdf_processed_dir / f"{i}.jpg") @@ -213,10 +222,27 @@ def process_image( .decode("utf-8") .rstrip("=") ) + image_date = None + + with Image.open(file_path) as img: + img.verify() # Verify that it is, in fact, an image + exif_data = img._getexif() + if exif_data: + # Exif tag 36867 corresponds to 'DateTimeOriginal' + datetime_original_tag = 306 + if datetime_original_tag in exif_data: + datetime_str = exif_data[datetime_original_tag] + # Convert the string to a datetime object + try: + image_date = datetime.strptime(datetime_str, '%Y:%m:%d %H:%M:%S') + except ValueError: + logger.error(f"Failed to parse date from {image}: {datetime_str}") + image_date = None metadata = { "file_name": file_path.name, "type": "image", + "date": image_date.strftime('%Y-%m-%d %H:%M:%S') if image_date else None, "paths": { "original": str(file_path), "processed": str(processed_image_path) diff --git a/src/models/clip/util.py b/src/models/clip/util.py index 6213736..1b2988f 100644 --- a/src/models/clip/util.py +++ b/src/models/clip/util.py @@ -12,11 +12,12 @@ def get_file_names( prefix: str): paginator = client.get_paginator('list_objects_v2') - pages = paginator.paginate(Bucket=bucket, Prefix=prefix) + pages = paginator.paginate(Bucket=bucket, Prefix=prefix, Delimiter='/') filenames = [] for page in pages: for obj in page['Contents']: - filenames.append(obj["Key"]) + if not obj["Key"].endswith("/"): + filenames.append(obj["Key"]) return filenames def download_file(