From f4cd86da363855c906c39158fa38be5cf13cd34b Mon Sep 17 00:00:00 2001 From: Harlan Date: Thu, 3 Oct 2024 16:46:50 -0700 Subject: [PATCH 01/11] Pumped polars --- Cargo.toml | 31 +- src/io/hdus/bintable/bintable.rs | 852 ++++++++++++++++++------------- src/io/hdus/bintable/buffer.rs | 353 +++++++------ src/io/hdus/image/image.rs | 144 +++--- src/io/hdus/table/buffer.rs | 82 ++- src/io/hdus/table/table.rs | 540 ++++++++++++-------- 6 files changed, 1167 insertions(+), 835 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 47635d2..b55163a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,11 +1,15 @@ [package] -name = "astrors" -version = "0.1.8" -authors = ["Gustavo Schwarz gustavo.b.schwarz@gmail.com", "Vincenzo Alberice alberice.vincenzo@gmail.com", "Thales Lopes thales.t.lopes@gmail.com"] # A list of the package authors +authors = [ + "Gustavo Schwarz gustavo.b.schwarz@gmail.com", + "Vincenzo Alberice alberice.vincenzo@gmail.com", + "Thales Lopes thales.t.lopes@gmail.com", +] # A list of the package authors edition = "2021" +name = "astrors" +version = "0.1.9" -repository = "https://github.com/schwarzam/astrors" license = "BSD-3-Clause" # The license your package is under +repository = "https://github.com/schwarzam/astrors" readme = "README.md" @@ -16,17 +20,18 @@ include = ["/src", "LICENSE", "README.md"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rayon = "1.8.0" -ndarray = { version = "0.15.6", features = ["rayon"] } -ndarray-stats = "0.5.1" -memmap = "0.7" -byteorder = "1.5.0" -polars = { version = "0.38.3", features=["dtype-u8", "dtype-i8", "dtype-i16"] } +ndarray = "0.15.6" num_cpus = "1.0" -chrono = "0.4.35" -regex = "1.10.3" +polars = {version = "0.43.1", features = ["dtype-u8", "dtype-i8", "dtype-i16"]} rand = "0.8.5" +rayon = "1.8.0" +regex = "1.10.3" [build-dependencies] +byteorder = "1.5.0" cc = "1.0.79" - +chrono = "0.4.35" +memmap = "0.7" +ndarray = {version = "0.15.6", features = ["rayon"]} +ndarray-stats = "0.5.1" +num_cpus = "1.0" diff --git a/src/io/hdus/bintable/bintable.rs b/src/io/hdus/bintable/bintable.rs index 50ecb9e..15e2eef 100644 --- a/src/io/hdus/bintable/bintable.rs +++ b/src/io/hdus/bintable/bintable.rs @@ -2,37 +2,44 @@ use core::panic; use std::io::Write; use std::{fs::File, io::Read}; -use crate::io::{hdus::bintable::buffer::Buffer, header::card::Card, utils::pad_buffer_to_fits_block, utils::pad_read_buffer_to_fits_block, Header}; use crate::io::hdus::bintable::*; +use crate::io::{ + hdus::bintable::buffer::Buffer, header::card::Card, utils::pad_buffer_to_fits_block, + utils::pad_read_buffer_to_fits_block, Header, +}; +use crate::io::hdus::table::table_utils::*; use polars::prelude::*; use rayon::iter::{IntoParallelIterator, ParallelIterator}; -use crate::io::hdus::table::table_utils::*; - -extern crate num_cpus; - +// extern crate num_cpus; #[derive(Debug)] pub struct Column { - pub ttype: String, + pub ttype: String, pub tform: String, pub tunit: Option, pub tdisp: Option, pub start_address: usize, - pub type_bytes : usize, + pub type_bytes: usize, pub type_letter: String, } impl Column { - pub fn new(ttype: String, tform: String, tunit: Option, tdisp: Option, start_address: usize) -> Self { + pub fn new( + ttype: String, + tform: String, + tunit: Option, + tdisp: Option, + start_address: usize, + ) -> Self { let tform2 = tform.clone(); let column = Column { ttype, tform, tunit, tdisp, - start_address: start_address, + start_address: start_address, type_bytes: get_data_bytes_size(&tform2), type_letter: get_first_letter(&tform2).to_string(), }; @@ -72,15 +79,18 @@ pub fn read_tableinfo_from_header(header: &Header) -> Result, String Ok(columns) } -pub fn read_table_bytes_to_df(columns : &mut Vec, header: &Header, file: &mut File) -> Result { +pub fn read_table_bytes_to_df( + columns: &mut Vec, + header: &Header, + file: &mut File, +) -> Result { let nrows = header["NAXIS2"].value.as_int().unwrap_or(0); let mut n_chunks: u16 = 1; let mut n_threads: u16 = num_cpus::get() as u16; if nrows > n_threads as i64 * 10 { n_chunks = n_threads; - } - else { + } else { n_threads = 1; } @@ -90,9 +100,9 @@ pub fn read_table_bytes_to_df(columns : &mut Vec, header: &Header, file: let mut buffer = vec![0; buffer_size]; file.read_exact(&mut buffer)?; - + //TODO read suplemental data here - if header.get_card("THEAP").is_some(){ + if header.get_card("THEAP").is_some() { // Skip theap bytes let theap = header.get_card("THEAP").unwrap().value.as_int().unwrap(); let mut theap_buffer = vec![0; theap as usize]; @@ -100,50 +110,63 @@ pub fn read_table_bytes_to_df(columns : &mut Vec, header: &Header, file: drop(theap_buffer); } let mut pcount_buffer; - if header.get_card("PCOUNT").is_some(){ + if header.get_card("PCOUNT").is_some() { // Skip pcount bytes let pcount = header.get_card("PCOUNT").unwrap().value.as_int().unwrap(); pcount_buffer = vec![0; pcount as usize]; file.read_exact(&mut pcount_buffer)?; } - //use rayon pool install //let pool = rayon::ThreadPoolBuilder::new().num_threads(4).build().unwrap(); - let pool = rayon::ThreadPoolBuilder::new().num_threads(n_threads as usize).build().unwrap(); - let results : Vec> = pool.install(|| { - limits.into_par_iter().map(|(start, end)| { - let local_buffer: &[u8] = &buffer[start..end]; - let nbuffer_rows = (end - start) / bytes_per_row; - - let mut local_buf_cols : Vec = Vec::new(); - columns.iter().for_each(|column: &Column| { - local_buf_cols.push(Buffer::new(&column.tform, nbuffer_rows as i32)); - }); - - (0..nbuffer_rows).into_iter().for_each(|i| { - let row_start_idx = i * bytes_per_row; - let row = &local_buffer[row_start_idx..row_start_idx + bytes_per_row]; - columns.iter().enumerate().for_each(|(j, column)| { - let buf_col = &mut local_buf_cols[j]; - let col_bytes = &row[column.start_address..column.start_address + column.type_bytes]; - buf_col.write_on_idx(col_bytes, i as i64); }); - }); - - let df_cols = columns.iter().enumerate().map(|(i, column)| { - if (get_first_letter(&column.tform) == "P") | (get_first_letter(&column.tform) == "Q") { - &local_buf_cols[i].read_var_len_cols(); - } - - let buf_col = &local_buf_cols[i]; - let series = buf_col.to_series(&column.ttype); - local_buf_cols[i].clear(); - series - }).collect(); - - let local_df = unsafe { DataFrame::new_no_checks(df_cols) }; - Ok(local_df) - }).collect() + let pool = rayon::ThreadPoolBuilder::new() + .num_threads(n_threads as usize) + .build() + .unwrap(); + let results: Vec> = pool.install(|| { + limits + .into_par_iter() + .map(|(start, end)| { + let local_buffer: &[u8] = &buffer[start..end]; + let nbuffer_rows = (end - start) / bytes_per_row; + + let mut local_buf_cols: Vec = Vec::new(); + columns.iter().for_each(|column: &Column| { + local_buf_cols.push(Buffer::new(&column.tform, nbuffer_rows as i32)); + }); + + (0..nbuffer_rows).into_iter().for_each(|i| { + let row_start_idx = i * bytes_per_row; + let row = &local_buffer[row_start_idx..row_start_idx + bytes_per_row]; + columns.iter().enumerate().for_each(|(j, column)| { + let buf_col = &mut local_buf_cols[j]; + let col_bytes = + &row[column.start_address..column.start_address + column.type_bytes]; + buf_col.write_on_idx(col_bytes, i as i64); + }); + }); + + let df_cols = columns + .iter() + .enumerate() + .map(|(i, column)| { + if (get_first_letter(&column.tform) == "P") + | (get_first_letter(&column.tform) == "Q") + { + local_buf_cols[i].read_var_len_cols(); + } + + let buf_col = &local_buf_cols[i]; + let series = buf_col.to_series(&column.ttype); + local_buf_cols[i].clear(); + series + }) + .collect(); + + let local_df = unsafe { DataFrame::new_no_checks(df_cols) }; + Ok(local_df) + }) + .collect() }); drop(buffer); @@ -159,112 +182,113 @@ pub fn read_table_bytes_to_df(columns : &mut Vec, header: &Header, file: pub fn polars_to_columns(df: &DataFrame) -> Result, std::io::Error> { let mut start_address = 0; let mut sum_to_address = 0; - - let columns : Vec = df.get_columns().into_iter().map(|series| { - let ttype = series.name(); - let tform = match series.dtype() { - DataType::Boolean => { - sum_to_address = byte_value_from_str("L"); - "L".to_string() - }, - DataType::UInt8 => { - sum_to_address = byte_value_from_str("X"); - "X".to_string() - }, - DataType::Int8 => { - sum_to_address = byte_value_from_str("B"); - "B".to_string() - }, - DataType::Int16 => { - sum_to_address = byte_value_from_str("I"); - "I".to_string() - }, - DataType::Int32 => { - sum_to_address = byte_value_from_str("J"); - "J".to_string() - }, - DataType::Int64 => { - sum_to_address = byte_value_from_str("K"); - "K".to_string() - }, - DataType::Float32 => { - sum_to_address = byte_value_from_str("E"); - "E".to_string() - }, - DataType::Float64 => { - sum_to_address = byte_value_from_str("D"); - "D".to_string() - }, - DataType::String => { - let data = &series.str().unwrap(); - let mut max_length = data.iter().map(|item| item.unwrap_or("").len()).max().unwrap(); - - //Max length should be even number - if max_length % 2 != 0 { - max_length += 1 as usize; + + let columns: Vec = df + .get_columns() + .into_iter() + .map(|series| { + let ttype = series.name(); + let tform = match series.dtype() { + DataType::Boolean => { + sum_to_address = byte_value_from_str("L"); + "L".to_string() + } + DataType::UInt8 => { + sum_to_address = byte_value_from_str("X"); + "X".to_string() + } + DataType::Int8 => { + sum_to_address = byte_value_from_str("B"); + "B".to_string() + } + DataType::Int16 => { + sum_to_address = byte_value_from_str("I"); + "I".to_string() } - sum_to_address = max_length; - format!("{}A", max_length) - }, - DataType::List(dtype ) => { - // Get list shape - let list_shape = series.list().unwrap().get(0).unwrap().len(); - - match dtype.to_physical() { - DataType::Float64 => { - sum_to_address = list_shape * byte_value_from_str("D"); - format!("{}D", list_shape) - }, - DataType::Float32 => { - sum_to_address = list_shape * byte_value_from_str("E"); - format!("{}E", list_shape) - }, - DataType::Int64 => { - sum_to_address = list_shape * byte_value_from_str("K"); - format!("{}K", list_shape) - }, - DataType::Int32 => { - sum_to_address = list_shape * byte_value_from_str("J"); - format!("{}J", list_shape) - }, - DataType::Int16 => { - sum_to_address = list_shape * byte_value_from_str("I"); - format!("{}I", list_shape) - }, - DataType::Int8 => { - sum_to_address = list_shape * byte_value_from_str("B"); - format!("{}B", list_shape) - }, - DataType::UInt8 => { - sum_to_address = list_shape * byte_value_from_str("X"); - format!("{}X", list_shape) - }, - DataType::Boolean => { - sum_to_address = list_shape * byte_value_from_str("L"); - format!("{}L", list_shape) - }, - _ => { - panic!("Unsupported data type for array column"); + DataType::Int32 => { + sum_to_address = byte_value_from_str("J"); + "J".to_string() + } + DataType::Int64 => { + sum_to_address = byte_value_from_str("K"); + "K".to_string() + } + DataType::Float32 => { + sum_to_address = byte_value_from_str("E"); + "E".to_string() + } + DataType::Float64 => { + sum_to_address = byte_value_from_str("D"); + "D".to_string() + } + DataType::String => { + let data = &series.str().unwrap(); + let mut max_length = data + .iter() + .map(|item| item.unwrap_or("").len()) + .max() + .unwrap(); + + //Max length should be even number + if max_length % 2 != 0 { + max_length += 1 as usize; + } + sum_to_address = max_length; + format!("{}A", max_length) + } + DataType::List(dtype) => { + // Get list shape + let list_shape = series.list().unwrap().get(0).unwrap().len(); + + match dtype.to_physical() { + DataType::Float64 => { + sum_to_address = list_shape * byte_value_from_str("D"); + format!("{}D", list_shape) + } + DataType::Float32 => { + sum_to_address = list_shape * byte_value_from_str("E"); + format!("{}E", list_shape) + } + DataType::Int64 => { + sum_to_address = list_shape * byte_value_from_str("K"); + format!("{}K", list_shape) + } + DataType::Int32 => { + sum_to_address = list_shape * byte_value_from_str("J"); + format!("{}J", list_shape) + } + DataType::Int16 => { + sum_to_address = list_shape * byte_value_from_str("I"); + format!("{}I", list_shape) + } + DataType::Int8 => { + sum_to_address = list_shape * byte_value_from_str("B"); + format!("{}B", list_shape) + } + DataType::UInt8 => { + sum_to_address = list_shape * byte_value_from_str("X"); + format!("{}X", list_shape) + } + DataType::Boolean => { + sum_to_address = list_shape * byte_value_from_str("L"); + format!("{}L", list_shape) + } + _ => { + panic!("Unsupported data type for array column"); + } } } + _ => { + panic!("Unsupported data type"); + } + }; - }, - _ => { - panic!("Unsupported data type"); - } - }; - - let column: Column = Column::new( - ttype.to_string(), - tform, - None, - None, - start_address - ); - - start_address += sum_to_address; - column - }).collect(); + let column: Column = Column::new(ttype.to_string(), tform, None, None, start_address); + + start_address += sum_to_address; + column + }) + .collect(); Ok(columns) } @@ -282,152 +306,248 @@ pub fn create_table_on_header(header: &mut Header, columns: &Vec, nrows: clear_table_on_header(header); let tfields = columns.len(); let num_bytes = calculate_number_of_bytes_of_row(columns); - header.add_card_on_index(&Card::new("XTENSION".to_string(), "BINTABLE".to_string(), Some("Binary table".to_string())), 0); - header.add_card_after(&Card::new("BITPIX".to_string(), 8.to_string(), Some("Table BITPIX".to_string())), "XTENSION"); - header.add_card_after(&Card::new("NAXIS".to_string(), 2.to_string(), Some("2D table".to_string())), "BITPIX"); - header.add_card_after(&Card::new("NAXIS1".to_string(), num_bytes.to_string(), Some("Number of bytes in row".to_string())), "NAXIS"); - header.add_card_after(&Card::new("NAXIS2".to_string(), nrows.to_string(), Some("Number of rows".to_string())), "NAXIS1"); - header.add_card_after(&Card::new("PCOUNT".to_string(), 0.to_string(), Some("Parameter count".to_string())), "NAXIS2"); - header.add_card_after(&Card::new("GCOUNT".to_string(), 1.to_string(), Some("Group count".to_string())), "PCOUNT"); - header.add_card_after(&Card::new("TFIELDS".to_string(), tfields.to_string(), Some("Number of fields per row".to_string())), "GCOUNT"); + header.add_card_on_index( + &Card::new( + "XTENSION".to_string(), + "BINTABLE".to_string(), + Some("Binary table".to_string()), + ), + 0, + ); + header.add_card_after( + &Card::new( + "BITPIX".to_string(), + 8.to_string(), + Some("Table BITPIX".to_string()), + ), + "XTENSION", + ); + header.add_card_after( + &Card::new( + "NAXIS".to_string(), + 2.to_string(), + Some("2D table".to_string()), + ), + "BITPIX", + ); + header.add_card_after( + &Card::new( + "NAXIS1".to_string(), + num_bytes.to_string(), + Some("Number of bytes in row".to_string()), + ), + "NAXIS", + ); + header.add_card_after( + &Card::new( + "NAXIS2".to_string(), + nrows.to_string(), + Some("Number of rows".to_string()), + ), + "NAXIS1", + ); + header.add_card_after( + &Card::new( + "PCOUNT".to_string(), + 0.to_string(), + Some("Parameter count".to_string()), + ), + "NAXIS2", + ); + header.add_card_after( + &Card::new( + "GCOUNT".to_string(), + 1.to_string(), + Some("Group count".to_string()), + ), + "PCOUNT", + ); + header.add_card_after( + &Card::new( + "TFIELDS".to_string(), + tfields.to_string(), + Some("Number of fields per row".to_string()), + ), + "GCOUNT", + ); for (i, column) in columns.iter().enumerate() { - header.add_card(&Card::new(format!("TTYPE{}", i + 1), column.ttype.clone(), Some("Name of field".to_string()))); - header.add_card(&Card::new(format!("TFORM{}", i + 1), column.tform.clone(), Some("Format of field".to_string()))); + header.add_card(&Card::new( + format!("TTYPE{}", i + 1), + column.ttype.clone(), + Some("Name of field".to_string()), + )); + header.add_card(&Card::new( + format!("TFORM{}", i + 1), + column.tform.clone(), + Some("Format of field".to_string()), + )); if let Some(tunit) = &column.tunit { - header.add_card(&Card::new(format!("TUNIT{}", i + 1), tunit.clone(), Some("Unit of field".to_string()))); + header.add_card(&Card::new( + format!("TUNIT{}", i + 1), + tunit.clone(), + Some("Unit of field".to_string()), + )); } if let Some(tdisp) = &column.tdisp { - header.add_card(&Card::new(format!("TDISP{}", i + 1), tdisp.clone(), Some("Display format of field".to_string()))); + header.add_card(&Card::new( + format!("TDISP{}", i + 1), + tdisp.clone(), + Some("Display format of field".to_string()), + )); } } } -pub fn df_to_buffer(columns: Vec, df: &DataFrame, file: &mut File) -> Result<(), std::io::Error> { +pub fn df_to_buffer( + columns: Vec, + df: &DataFrame, + file: &mut File, +) -> Result<(), std::io::Error> { let nrows = df.height(); let bytes_per_row = calculate_number_of_bytes_of_row(&columns); - + let mut n_chunks: u16 = 1; let mut n_threads: u16 = num_cpus::get() as u16; if nrows > n_threads as usize * 10 { n_chunks = n_threads; - } - else { + } else { n_threads = 1; } let limits = split_buffer(nrows, n_chunks, 1); - let pool = rayon::ThreadPoolBuilder::new().num_threads(n_threads as usize).build().unwrap(); - let bufs : Vec> = pool.install(|| { - limits.into_par_iter().map(|(start, end)| { - let nbuffer_rows: usize = end - start; - let local_df = &df.slice(start as i64, nbuffer_rows); - let mut local_buffer : Vec = vec![0x00; nbuffer_rows * bytes_per_row]; - - columns.iter().for_each(|column| { - let series = &local_df.column(&column.ttype).unwrap(); - - match series.dtype() { - DataType::Boolean => { - series.bool() - .expect("series was not an bool dtype") - .into_iter() - .enumerate() - .for_each(|(j, item)| { - let bytes = item.unwrap() as u8; - let row_start_add = j * bytes_per_row; - let col_start_add = row_start_add + column.start_address; - local_buffer[col_start_add..col_start_add + column.type_bytes].copy_from_slice(&[bytes]); - }); - }, - DataType::UInt8 => { - series.u8() - .expect("series was not an u8 dtype") - .into_iter() - .enumerate() - .for_each(|(j, item)| { - let bytes = item.unwrap() as u8; - let row_start_add = j * bytes_per_row; - let col_start_add = row_start_add + column.start_address; - local_buffer[col_start_add..col_start_add + column.type_bytes].copy_from_slice(&[bytes]); - }); - }, - DataType::Int8 => { - series.i8() - .expect("series was not an i8 dtype") - .into_iter() - .enumerate() - .for_each(|(j, item)| { - let bytes = item.unwrap() as i8; - let row_start_add = j * bytes_per_row; - let col_start_add = row_start_add + column.start_address; - local_buffer[col_start_add..col_start_add + column.type_bytes].copy_from_slice(&bytes.to_be_bytes()); - }); - }, - DataType::Int16 => { - series.i16() - .expect("series was not an i16 dtype") - .into_iter() - .enumerate() - .for_each(|(j, item)| { - let bytes = item.unwrap() as i16; - let row_start_add = j * bytes_per_row; - let col_start_add = row_start_add + column.start_address; - local_buffer[col_start_add..col_start_add + column.type_bytes].copy_from_slice(&bytes.to_be_bytes()); - }); - }, - DataType::Int32 => { - series.i32() - .expect("series was not an i32 dtype") - .into_iter() - .enumerate() - .for_each(|(j, item)| { - let bytes = item.unwrap() as i32; - let row_start_add = j * bytes_per_row; - let col_start_add = row_start_add + column.start_address; - local_buffer[col_start_add..col_start_add + column.type_bytes].copy_from_slice(&bytes.to_be_bytes()); - }); - }, - DataType::Int64 => { - series.i64() - .expect("series was not an i64 dtype") - .into_iter() - .enumerate() - .for_each(|(j, item)| { - let bytes = item.unwrap() as i64; - let row_start_add = j * bytes_per_row; - let col_start_add = row_start_add + column.start_address; - local_buffer[col_start_add..col_start_add + column.type_bytes].copy_from_slice(&bytes.to_be_bytes()); - }); - }, - DataType::Float32 => { - series.f32() - .expect("series was not an f32 dtype") - .into_iter() - .enumerate() - .for_each(|(j, item)| { - let bytes = item.unwrap() as f32; - let row_start_add = j * bytes_per_row; - let col_start_add = row_start_add + column.start_address; - local_buffer[col_start_add..col_start_add + column.type_bytes].copy_from_slice(&bytes.to_be_bytes()); - }); - }, - DataType::Float64 => { - series.f64() - .expect("series was not an f64 dtype") - .into_iter() - .enumerate() - .for_each(|(j, item)| { - let bytes = item.unwrap() as f64; - let row_start_add = j * bytes_per_row; - let col_start_add = row_start_add + column.start_address; - local_buffer[col_start_add..col_start_add + column.type_bytes].copy_from_slice(&bytes.to_be_bytes()); - }); - }, - DataType::List(dtype) => { - match dtype.to_physical() { + let pool = rayon::ThreadPoolBuilder::new() + .num_threads(n_threads as usize) + .build() + .unwrap(); + let bufs: Vec> = pool.install(|| { + limits + .into_par_iter() + .map(|(start, end)| { + let nbuffer_rows: usize = end - start; + let local_df = &df.slice(start as i64, nbuffer_rows); + let mut local_buffer: Vec = vec![0x00; nbuffer_rows * bytes_per_row]; + + columns.iter().for_each(|column| { + let series = &local_df.column(&column.ttype).unwrap(); + + match series.dtype() { + DataType::Boolean => { + series + .bool() + .expect("series was not an bool dtype") + .into_iter() + .enumerate() + .for_each(|(j, item)| { + let bytes = item.unwrap() as u8; + let row_start_add = j * bytes_per_row; + let col_start_add = row_start_add + column.start_address; + local_buffer[col_start_add..col_start_add + column.type_bytes] + .copy_from_slice(&[bytes]); + }); + } + DataType::UInt8 => { + series + .u8() + .expect("series was not an u8 dtype") + .into_iter() + .enumerate() + .for_each(|(j, item)| { + let bytes = item.unwrap() as u8; + let row_start_add = j * bytes_per_row; + let col_start_add = row_start_add + column.start_address; + local_buffer[col_start_add..col_start_add + column.type_bytes] + .copy_from_slice(&[bytes]); + }); + } + DataType::Int8 => { + series + .i8() + .expect("series was not an i8 dtype") + .into_iter() + .enumerate() + .for_each(|(j, item)| { + let bytes = item.unwrap() as i8; + let row_start_add = j * bytes_per_row; + let col_start_add = row_start_add + column.start_address; + local_buffer[col_start_add..col_start_add + column.type_bytes] + .copy_from_slice(&bytes.to_be_bytes()); + }); + } + DataType::Int16 => { + series + .i16() + .expect("series was not an i16 dtype") + .into_iter() + .enumerate() + .for_each(|(j, item)| { + let bytes = item.unwrap() as i16; + let row_start_add = j * bytes_per_row; + let col_start_add = row_start_add + column.start_address; + local_buffer[col_start_add..col_start_add + column.type_bytes] + .copy_from_slice(&bytes.to_be_bytes()); + }); + } + DataType::Int32 => { + series + .i32() + .expect("series was not an i32 dtype") + .into_iter() + .enumerate() + .for_each(|(j, item)| { + let bytes = item.unwrap() as i32; + let row_start_add = j * bytes_per_row; + let col_start_add = row_start_add + column.start_address; + local_buffer[col_start_add..col_start_add + column.type_bytes] + .copy_from_slice(&bytes.to_be_bytes()); + }); + } + DataType::Int64 => { + series + .i64() + .expect("series was not an i64 dtype") + .into_iter() + .enumerate() + .for_each(|(j, item)| { + let bytes = item.unwrap() as i64; + let row_start_add = j * bytes_per_row; + let col_start_add = row_start_add + column.start_address; + local_buffer[col_start_add..col_start_add + column.type_bytes] + .copy_from_slice(&bytes.to_be_bytes()); + }); + } + DataType::Float32 => { + series + .f32() + .expect("series was not an f32 dtype") + .into_iter() + .enumerate() + .for_each(|(j, item)| { + let bytes = item.unwrap() as f32; + let row_start_add = j * bytes_per_row; + let col_start_add = row_start_add + column.start_address; + local_buffer[col_start_add..col_start_add + column.type_bytes] + .copy_from_slice(&bytes.to_be_bytes()); + }); + } + DataType::Float64 => { + series + .f64() + .expect("series was not an f64 dtype") + .into_iter() + .enumerate() + .for_each(|(j, item)| { + let bytes = item.unwrap() as f64; + let row_start_add = j * bytes_per_row; + let col_start_add = row_start_add + column.start_address; + local_buffer[col_start_add..col_start_add + column.type_bytes] + .copy_from_slice(&bytes.to_be_bytes()); + }); + } + DataType::List(dtype) => match dtype.to_physical() { DataType::Boolean => { - series.list() + series + .list() .expect("series was not an list dtype") .into_iter() .enumerate() @@ -435,17 +555,20 @@ pub fn df_to_buffer(columns: Vec, df: &DataFrame, file: &mut File) -> Re let array = item.unwrap(); let row_start_add = j * bytes_per_row; let col_start_add = row_start_add + column.start_address; - - array.iter().enumerate().for_each(|(k, it )| { + + array.iter().enumerate().for_each(|(k, it)| { if let AnyValue::Boolean(item) = it { let bytes = item as u8; - local_buffer[col_start_add + k..col_start_add + k + 1].copy_from_slice(&[bytes]); + local_buffer + [col_start_add + k..col_start_add + k + 1] + .copy_from_slice(&[bytes]); } }); }); - }, + } DataType::UInt8 => { - series.list() + series + .list() .expect("series was not an list dtype") .into_iter() .enumerate() @@ -453,17 +576,20 @@ pub fn df_to_buffer(columns: Vec, df: &DataFrame, file: &mut File) -> Re let array = item.unwrap(); let row_start_add = j * bytes_per_row; let col_start_add = row_start_add + column.start_address; - - array.iter().enumerate().for_each(|(k, it )| { + + array.iter().enumerate().for_each(|(k, it)| { if let AnyValue::UInt8(item) = it { let bytes = item as u8; - local_buffer[col_start_add + k..col_start_add + k + 1].copy_from_slice(&[bytes]); + local_buffer + [col_start_add + k..col_start_add + k + 1] + .copy_from_slice(&[bytes]); } }); }); - }, + } DataType::Int8 => { - series.list() + series + .list() .expect("series was not an list dtype") .into_iter() .enumerate() @@ -471,17 +597,20 @@ pub fn df_to_buffer(columns: Vec, df: &DataFrame, file: &mut File) -> Re let array = item.unwrap(); let row_start_add = j * bytes_per_row; let col_start_add = row_start_add + column.start_address; - - array.iter().enumerate().for_each(|(k, it )| { + + array.iter().enumerate().for_each(|(k, it)| { if let AnyValue::Int8(item) = it { let bytes = item as i8; - local_buffer[col_start_add + k..col_start_add + k + 1].copy_from_slice(&bytes.to_be_bytes()); + local_buffer + [col_start_add + k..col_start_add + k + 1] + .copy_from_slice(&bytes.to_be_bytes()); } }); }); - }, + } DataType::Int16 => { - series.list() + series + .list() .expect("series was not an list dtype") .into_iter() .enumerate() @@ -489,17 +618,20 @@ pub fn df_to_buffer(columns: Vec, df: &DataFrame, file: &mut File) -> Re let array = item.unwrap(); let row_start_add = j * bytes_per_row; let col_start_add = row_start_add + column.start_address; - - array.iter().enumerate().for_each(|(k, it )| { + + array.iter().enumerate().for_each(|(k, it)| { if let AnyValue::Int16(item) = it { let bytes = item as i16; - local_buffer[col_start_add + k * 2..col_start_add + k * 2 + 2].copy_from_slice(&bytes.to_be_bytes()); + local_buffer[col_start_add + k * 2 + ..col_start_add + k * 2 + 2] + .copy_from_slice(&bytes.to_be_bytes()); } }); }); - }, + } DataType::Int32 => { - series.list() + series + .list() .expect("series was not an list dtype") .into_iter() .enumerate() @@ -507,17 +639,20 @@ pub fn df_to_buffer(columns: Vec, df: &DataFrame, file: &mut File) -> Re let array = item.unwrap(); let row_start_add = j * bytes_per_row; let col_start_add = row_start_add + column.start_address; - - array.iter().enumerate().for_each(|(k, it )| { + + array.iter().enumerate().for_each(|(k, it)| { if let AnyValue::Int32(item) = it { let bytes = item as i32; - local_buffer[col_start_add + k * 4..col_start_add + k * 4 + 4].copy_from_slice(&bytes.to_be_bytes()); + local_buffer[col_start_add + k * 4 + ..col_start_add + k * 4 + 4] + .copy_from_slice(&bytes.to_be_bytes()); } }); }); - }, + } DataType::Int64 => { - series.list() + series + .list() .expect("series was not an list dtype") .into_iter() .enumerate() @@ -525,17 +660,20 @@ pub fn df_to_buffer(columns: Vec, df: &DataFrame, file: &mut File) -> Re let array = item.unwrap(); let row_start_add = j * bytes_per_row; let col_start_add = row_start_add + column.start_address; - - array.iter().enumerate().for_each(|(k, it )| { + + array.iter().enumerate().for_each(|(k, it)| { if let AnyValue::Int64(item) = it { let bytes = item as i64; - local_buffer[col_start_add + k * 8..col_start_add + k * 8 + 8].copy_from_slice(&bytes.to_be_bytes()); + local_buffer[col_start_add + k * 8 + ..col_start_add + k * 8 + 8] + .copy_from_slice(&bytes.to_be_bytes()); } }); }); - }, + } DataType::Float32 => { - series.list() + series + .list() .expect("series was not an list dtype") .into_iter() .enumerate() @@ -543,17 +681,20 @@ pub fn df_to_buffer(columns: Vec, df: &DataFrame, file: &mut File) -> Re let array = item.unwrap(); let row_start_add = j * bytes_per_row; let col_start_add = row_start_add + column.start_address; - - array.iter().enumerate().for_each(|(k, it )| { + + array.iter().enumerate().for_each(|(k, it)| { if let AnyValue::Float32(item) = it { let bytes = item as f32; - local_buffer[col_start_add + k * 4..col_start_add + k * 4 + 4].copy_from_slice(&bytes.to_be_bytes()); + local_buffer[col_start_add + k * 4 + ..col_start_add + k * 4 + 4] + .copy_from_slice(&bytes.to_be_bytes()); } }); }); - }, + } DataType::Float64 => { - series.list() + series + .list() .expect("series was not an list dtype") .into_iter() .enumerate() @@ -561,61 +702,64 @@ pub fn df_to_buffer(columns: Vec, df: &DataFrame, file: &mut File) -> Re let array = item.unwrap(); let row_start_add = j * bytes_per_row; let col_start_add = row_start_add + column.start_address; - - array.iter().enumerate().for_each(|(k, it )| { + + array.iter().enumerate().for_each(|(k, it)| { if let AnyValue::Float64(item) = it { let bytes = item as f64; - local_buffer[col_start_add + k * 8..col_start_add + k * 8 + 8].copy_from_slice(&bytes.to_be_bytes()); + local_buffer[col_start_add + k * 8 + ..col_start_add + k * 8 + 8] + .copy_from_slice(&bytes.to_be_bytes()); } }); }); - }, + } _ => panic!("Unsupported data type for array column"), + }, + DataType::String => { + series + .str() + .expect("series was not an string dtype") + .into_iter() + .enumerate() + .for_each(|(j, item)| { + let string = item.unwrap(); + let mut string = string.to_string(); + string.push_str(&" ".repeat(column.type_bytes - string.len())); + let row_start_add = j * bytes_per_row; + let col_start_add = row_start_add + column.start_address; + local_buffer[col_start_add..col_start_add + column.type_bytes] + .copy_from_slice(&string.into_bytes()); + }); + } + _ => { + series + .str() + .expect("series was not an string dtype") + .into_iter() + .enumerate() + .for_each(|(j, item)| { + let string = item.unwrap(); + let mut string = string.to_string(); + string.push_str(&" ".repeat(column.type_bytes - string.len())); + let row_start_add = j * bytes_per_row; + let col_start_add = row_start_add + column.start_address; + local_buffer[col_start_add..col_start_add + column.type_bytes] + .copy_from_slice(&string.into_bytes()); + }); } } - DataType::String => { - series.str() - .expect("series was not an string dtype") - .into_iter() - .enumerate() - .for_each(|(j, item)| { - let string = item.unwrap(); - let mut string = string.to_string(); - string.push_str(&" ".repeat(column.type_bytes - string.len())); - let row_start_add = j * bytes_per_row; - let col_start_add = row_start_add + column.start_address; - local_buffer[col_start_add..col_start_add + column.type_bytes].copy_from_slice(&string.into_bytes()); - }); - }, - _ => { - series.str() - .expect("series was not an string dtype") - .into_iter() - .enumerate() - .for_each(|(j, item)| { - let string = item.unwrap(); - let mut string = string.to_string(); - string.push_str(&" ".repeat(column.type_bytes - string.len())); - let row_start_add = j * bytes_per_row; - let col_start_add = row_start_add + column.start_address; - local_buffer[col_start_add..col_start_add + column.type_bytes].copy_from_slice(&string.into_bytes()); - }); - } - - } - - }); - - - local_buffer.to_owned() - }).collect() + }); + + local_buffer.to_owned() + }) + .collect() }); let mut bytes_written = 0; bufs.into_iter().for_each(|buffer| { bytes_written += file.write(&buffer).unwrap(); }); - + if bytes_written < nrows as usize * bytes_per_row { panic!("Error writing to file"); } diff --git a/src/io/hdus/bintable/buffer.rs b/src/io/hdus/bintable/buffer.rs index 4eb2c82..0cc51eb 100644 --- a/src/io/hdus/bintable/buffer.rs +++ b/src/io/hdus/bintable/buffer.rs @@ -1,24 +1,21 @@ -use num_cpus::get; -use rayon::{prelude::*, vec}; +use polars::datatypes::PlSmallStr; use polars::{prelude::NamedFrom, series::Series}; use crate::io::hdus::bintable::*; - - #[derive(Debug, PartialEq)] pub enum ColumnDataBuffer { - L(Vec), // Logical - X(Vec), // Bit - B(Vec), // Byte - I(Vec), // Short - J(Vec), // Int - K(Vec), // Long - A(Vec), // Char - E(Vec), // Float - D(Vec), // Double - C(Vec), // Complex - M(Vec), // Double complex + L(Vec), // Logical + X(Vec), // Bit + B(Vec), // Byte + I(Vec), // Short + J(Vec), // Int + K(Vec), // Long + A(Vec), // Char + E(Vec), // Float + D(Vec), // Double + C(Vec), // Complex + M(Vec), // Double complex P(Vec>), // Array descriptor Q(Vec>), // Array descriptor } @@ -26,98 +23,98 @@ pub enum ColumnDataBuffer { #[derive(Debug, PartialEq)] pub enum ColumnArrayBuffer { L(Vec>), // Logical - X(Vec>), // Bit - B(Vec>), // Byte - I(Vec>), // Short - J(Vec>), // Int - K(Vec>), // Long - E(Vec>), // Float - D(Vec>), // Double + X(Vec>), // Bit + B(Vec>), // Byte + I(Vec>), // Short + J(Vec>), // Int + K(Vec>), // Long + E(Vec>), // Float + D(Vec>), // Double } -enum BufferTypes -{ +enum BufferTypes { Scalar(ColumnDataBuffer), Vector(ColumnArrayBuffer), } pub struct Buffer { - tform : String, - size : i32, - buffer : BufferTypes, - sub_size : i32, - data_letter : String, + tform: String, + size: i32, + buffer: BufferTypes, + sub_size: i32, + data_letter: String, } impl Buffer { - pub fn new(tform : &str, size : i32) -> Self { + pub fn new(tform: &str, size: i32) -> Self { let tform = tform.to_string(); let data_letter = get_first_letter(&tform).to_string(); let mut sub_size = 1; let mut vec_column = false; - if (get_data_bytes_size(&tform) != byte_value_from_str(&tform)) - & (data_letter != "A") & (data_letter != "C") & (data_letter != "M") & (data_letter != "P") & (data_letter != "Q") + if (get_data_bytes_size(&tform) != byte_value_from_str(&tform)) + & (data_letter != "A") + & (data_letter != "C") + & (data_letter != "M") + & (data_letter != "P") + & (data_letter != "Q") { vec_column = true; - sub_size = (get_data_bytes_size(&tform)/byte_value_from_str(&tform)) as i32; + sub_size = (get_data_bytes_size(&tform) / byte_value_from_str(&tform)) as i32; } - let buffer : BufferTypes; + let buffer: BufferTypes; if vec_column { buffer = BufferTypes::Vector(ColumnArrayBuffer::new(&tform, size, sub_size)); - }else{ + } else { buffer = BufferTypes::Scalar(ColumnDataBuffer::new(&tform, size)); } - Buffer{ + Buffer { tform, size, buffer, sub_size, - data_letter + data_letter, } } - pub fn to_series(&self, col_name : &str) -> Series { + pub fn to_series(&self, col_name: &str) -> Series { match &self.buffer { BufferTypes::Scalar(data) => data.to_series(col_name), BufferTypes::Vector(data) => data.to_series(col_name), } } - pub fn clear(&mut self){ + pub fn clear(&mut self) { match &mut self.buffer { BufferTypes::Scalar(data) => data.clear(), BufferTypes::Vector(data) => data.clear(), } } - pub fn write_on_idx(&mut self, bytes : &[u8], idx : i64){ + pub fn write_on_idx(&mut self, bytes: &[u8], idx: i64) { match &mut self.buffer { BufferTypes::Scalar(data) => data.write_on_idx(bytes, &self.data_letter, idx), - BufferTypes::Vector(data) => data.write_on_idx(bytes, &self.data_letter, idx, self.sub_size), + BufferTypes::Vector(data) => { + data.write_on_idx(bytes, &self.data_letter, idx, self.sub_size) + } } } - pub fn read_var_len_cols(&mut self){ + pub fn read_var_len_cols(&mut self) { //TODO - - match &mut self.buffer { - BufferTypes::Scalar(data) => { - println!("buffer: {:?}", data); - }, - BufferTypes::Vector(data) => { - - }, - } + // match &mut self.buffer { + // BufferTypes::Scalar(data) => { + // println!("buffer: {:?}", data); + // } + // BufferTypes::Vector(data) => {} + // } } - - } impl ColumnArrayBuffer { - pub fn new(tform : &str, size : i32, sub_size : i32) -> Self { + pub fn new(tform: &str, size: i32, sub_size: i32) -> Self { let tform = tform.trim(); let tform_type = get_first_letter(tform); @@ -130,11 +127,11 @@ impl ColumnArrayBuffer { "K" => ColumnArrayBuffer::K(vec![vec![0; sub_size as usize]; size as usize]), "E" => ColumnArrayBuffer::E(vec![vec![0.0; sub_size as usize]; size as usize]), "D" => ColumnArrayBuffer::D(vec![vec![0.0; sub_size as usize]; size as usize]), - _ => panic!("Unsupported data type for array col"), + _ => panic!("Unsupported data type for array col"), } } - pub fn empty(tform : &str) -> Self { + pub fn empty(tform: &str) -> Self { let tform = tform.trim(); let tform_type = get_first_letter(tform); @@ -147,71 +144,80 @@ impl ColumnArrayBuffer { "K" => ColumnArrayBuffer::K(vec![vec![]]), "E" => ColumnArrayBuffer::E(vec![vec![]]), "D" => ColumnArrayBuffer::D(vec![vec![]]), - _ => panic!("Unsupported data type for array col"), + _ => panic!("Unsupported data type for array col"), } } - - pub fn to_series(&self, col_name : &str) -> Series { + pub fn to_series(&self, col_name: &str) -> Series { + let col = PlSmallStr::from_str(col_name); + let blank = PlSmallStr::from_str(""); let series = match self { - ColumnArrayBuffer::L(data) => Series::new(col_name, - data.iter().map(|vec| { - Series::new("", vec) - }).collect::>() + ColumnArrayBuffer::L(data) => Series::new( + col, + data.iter() + .map(|vec| Series::new(blank.clone(), vec)) + .collect::>(), ), - ColumnArrayBuffer::X(data) => Series::new(col_name, - data.iter().map(|vec| { - Series::new("", vec) - }).collect::>() + ColumnArrayBuffer::X(data) => Series::new( + col, + data.iter() + .map(|vec| Series::new(blank.clone(), vec)) + .collect::>(), ), - ColumnArrayBuffer::B(data) => Series::new(col_name, - data.iter().map(|vec| { - Series::new("", vec) - }).collect::>() + ColumnArrayBuffer::B(data) => Series::new( + col, + data.iter() + .map(|vec| Series::new(blank.clone(), vec)) + .collect::>(), ), - ColumnArrayBuffer::I(data) => Series::new(col_name, - data.iter().map(|vec| { - Series::new("", vec) - }).collect::>() + ColumnArrayBuffer::I(data) => Series::new( + col, + data.iter() + .map(|vec| Series::new(blank.clone(), vec)) + .collect::>(), ), - ColumnArrayBuffer::J(data) => Series::new(col_name, - data.iter().map(|vec| { - Series::new("", vec) - }).collect::>() + ColumnArrayBuffer::J(data) => Series::new( + col, + data.iter() + .map(|vec| Series::new(blank.clone(), vec)) + .collect::>(), ), - ColumnArrayBuffer::K(data) => Series::new(col_name, - data.iter().map(|vec| { - Series::new("", vec) - }).collect::>() + ColumnArrayBuffer::K(data) => Series::new( + col, + data.iter() + .map(|vec| Series::new(blank.clone(), vec)) + .collect::>(), ), - ColumnArrayBuffer::E(data) => Series::new(col_name, - data.iter().map(|vec| { - Series::new("", vec) - }).collect::>() + ColumnArrayBuffer::E(data) => Series::new( + col, + data.iter() + .map(|vec| Series::new(blank.clone(), vec)) + .collect::>(), ), - ColumnArrayBuffer::D(data) => Series::new(col_name, - data.iter().map(|vec| { - Series::new("", vec) - }).collect::>() + ColumnArrayBuffer::D(data) => Series::new( + col, + data.iter() + .map(|vec| Series::new(blank.clone(), vec)) + .collect::>(), ), }; series } - pub fn clear(&mut self){ + pub fn clear(&mut self) { match self { - ColumnArrayBuffer::L(data) => data.clear(), - ColumnArrayBuffer::X(data) => data.clear(), - ColumnArrayBuffer::B(data) => data.clear(), - ColumnArrayBuffer::I(data) => data.clear(), - ColumnArrayBuffer::J(data) => data.clear(), - ColumnArrayBuffer::K(data) => data.clear(), - ColumnArrayBuffer::E(data) => data.clear(), - ColumnArrayBuffer::D(data) => data.clear(), + ColumnArrayBuffer::L(data) => data.clear(), + ColumnArrayBuffer::X(data) => data.clear(), + ColumnArrayBuffer::B(data) => data.clear(), + ColumnArrayBuffer::I(data) => data.clear(), + ColumnArrayBuffer::J(data) => data.clear(), + ColumnArrayBuffer::K(data) => data.clear(), + ColumnArrayBuffer::E(data) => data.clear(), + ColumnArrayBuffer::D(data) => data.clear(), } } - pub fn write_on_idx(&mut self, bytes : &[u8], data_letter : &str, idx : i64, sub_size : i32){ + pub fn write_on_idx(&mut self, bytes: &[u8], data_letter: &str, idx: i64, sub_size: i32) { match data_letter { "L" => { // parse bytes to bool @@ -230,7 +236,16 @@ impl ColumnArrayBuffer { ColumnArrayBuffer::K(data) => { let mut stbyte = 0; (0..sub_size).for_each(|i| { - data[idx as usize][i as usize] = i64::from_be_bytes([bytes[stbyte], bytes[stbyte+1], bytes[stbyte+2], bytes[stbyte+3], bytes[stbyte+4], bytes[stbyte+5], bytes[stbyte+6], bytes[stbyte+7]]); + data[idx as usize][i as usize] = i64::from_be_bytes([ + bytes[stbyte], + bytes[stbyte + 1], + bytes[stbyte + 2], + bytes[stbyte + 3], + bytes[stbyte + 4], + bytes[stbyte + 5], + bytes[stbyte + 6], + bytes[stbyte + 7], + ]); stbyte += 8; }); } @@ -238,13 +253,12 @@ impl ColumnArrayBuffer { } } _ => panic!("Wrong data type"), - } } } impl ColumnDataBuffer { - pub fn new(tform : &str, size : i32) -> Self { + pub fn new(tform: &str, size: i32) -> Self { let tform = tform.trim(); let tform_type = get_first_letter(tform); @@ -262,50 +276,54 @@ impl ColumnDataBuffer { "M" => ColumnDataBuffer::M(vec![String::new(); size as usize]), "P" => ColumnDataBuffer::P(vec![vec![0; 2]; size as usize]), "Q" => ColumnDataBuffer::Q(vec![vec![0; 2]; size as usize]), - _ => ColumnDataBuffer::A(vec![String::new(); size as usize]), + _ => ColumnDataBuffer::A(vec![String::new(); size as usize]), } } - pub fn to_series(&self, col_name : &str) -> Series { + pub fn to_series(&self, col_name: &str) -> Series { + let col = PlSmallStr::from_str(col_name); + let blank = PlSmallStr::from_str(""); let series = match self { - ColumnDataBuffer::L(data) => Series::new(col_name, data), - ColumnDataBuffer::X(data) => Series::new(col_name, data), - ColumnDataBuffer::B(data) => Series::new(col_name, data), - ColumnDataBuffer::I(data) => Series::new(col_name, data), - ColumnDataBuffer::J(data) => Series::new(col_name, data), - ColumnDataBuffer::K(data) => Series::new(col_name, data), - ColumnDataBuffer::A(data) => Series::new(col_name, data), - ColumnDataBuffer::E(data) => Series::new(col_name, data), - ColumnDataBuffer::D(data) => Series::new(col_name, data), - ColumnDataBuffer::C(data) => Series::new(col_name, data), - ColumnDataBuffer::M(data) => Series::new(col_name, data), - ColumnDataBuffer::P(data) => { - let series_vec: Vec = data.into_iter().map(|vec| { - Series::new("", &vec) - }).collect(); - Series::new(col_name, series_vec) - }, - ColumnDataBuffer::Q(data) => { - let series_vec: Vec = data.into_iter().map(|vec| { - Series::new("", &vec) - }).collect(); - Series::new(col_name, series_vec) + ColumnDataBuffer::L(data) => Series::new(col, data), + ColumnDataBuffer::X(data) => Series::new(col, data), + ColumnDataBuffer::B(data) => Series::new(col, data), + ColumnDataBuffer::I(data) => Series::new(col, data), + ColumnDataBuffer::J(data) => Series::new(col, data), + ColumnDataBuffer::K(data) => Series::new(col, data), + ColumnDataBuffer::A(data) => Series::new(col, data), + ColumnDataBuffer::E(data) => Series::new(col, data), + ColumnDataBuffer::D(data) => Series::new(col, data), + ColumnDataBuffer::C(data) => Series::new(col, data), + ColumnDataBuffer::M(data) => Series::new(col, data), + ColumnDataBuffer::P(data) => { + let series_vec: Vec = data + .into_iter() + .map(|vec| Series::new(blank.clone(), &vec)) + .collect(); + Series::new(col, series_vec) + } + ColumnDataBuffer::Q(data) => { + let series_vec: Vec = data + .into_iter() + .map(|vec| Series::new(blank.clone(), &vec)) + .collect(); + Series::new(col, series_vec) } }; series } - pub fn clear(&mut self){ + pub fn clear(&mut self) { match self { - ColumnDataBuffer::L(data) => data.clear(), - ColumnDataBuffer::X(data) => data.clear(), - ColumnDataBuffer::B(data) => data.clear(), - ColumnDataBuffer::I(data) => data.clear(), - ColumnDataBuffer::J(data) => data.clear(), - ColumnDataBuffer::K(data) => data.clear(), + ColumnDataBuffer::L(data) => data.clear(), + ColumnDataBuffer::X(data) => data.clear(), + ColumnDataBuffer::B(data) => data.clear(), + ColumnDataBuffer::I(data) => data.clear(), + ColumnDataBuffer::J(data) => data.clear(), + ColumnDataBuffer::K(data) => data.clear(), ColumnDataBuffer::A(data) => data.clear(), - ColumnDataBuffer::E(data) => data.clear(), - ColumnDataBuffer::D(data) => data.clear(), + ColumnDataBuffer::E(data) => data.clear(), + ColumnDataBuffer::D(data) => data.clear(), ColumnDataBuffer::C(data) => data.clear(), ColumnDataBuffer::M(data) => data.clear(), ColumnDataBuffer::P(data) => data.clear(), @@ -313,7 +331,7 @@ impl ColumnDataBuffer { } } - pub fn write_on_idx(&mut self, bytes : &[u8], data_letter : &str, idx : i64){ + pub fn write_on_idx(&mut self, bytes: &[u8], data_letter: &str, idx: i64) { match data_letter { "L" => { // parse bytes to bool @@ -339,21 +357,31 @@ impl ColumnDataBuffer { "I" => { // parse bytes to i16 match self { - ColumnDataBuffer::I(data) => data[idx as usize] = i16::from_be_bytes([bytes[0], bytes[1]]), + ColumnDataBuffer::I(data) => { + data[idx as usize] = i16::from_be_bytes([bytes[0], bytes[1]]) + } _ => panic!("Wrong data type"), } } "J" => { // parse bytes to i32 match self { - ColumnDataBuffer::J(data) => data[idx as usize] = i32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]), + ColumnDataBuffer::J(data) => { + data[idx as usize] = + i32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]) + } _ => panic!("Wrong data type"), } } "K" => { // parse bytes to i64 match self { - ColumnDataBuffer::K(data) => data[idx as usize] = i64::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7]]), + ColumnDataBuffer::K(data) => { + data[idx as usize] = i64::from_be_bytes([ + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], + bytes[7], + ]) + } _ => panic!("Wrong data type"), } } @@ -361,7 +389,9 @@ impl ColumnDataBuffer { // parse bytes to String match self { ColumnDataBuffer::A(data) => { - let string = unsafe { String::from_utf8_unchecked(bytes.to_vec()) }.trim_end().to_string(); + let string = unsafe { String::from_utf8_unchecked(bytes.to_vec()) } + .trim_end() + .to_string(); data[idx as usize] = string; } _ => panic!("Wrong data type"), @@ -370,14 +400,22 @@ impl ColumnDataBuffer { "E" => { // parse bytes to f32 match self { - ColumnDataBuffer::E(data) => data[idx as usize] = f32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]), + ColumnDataBuffer::E(data) => { + data[idx as usize] = + f32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]) + } _ => panic!("Wrong data type"), } } "D" => { // parse bytes to f64 match self { - ColumnDataBuffer::D(data) => data[idx as usize] = f64::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7]]), + ColumnDataBuffer::D(data) => { + data[idx as usize] = f64::from_be_bytes([ + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], + bytes[7], + ]) + } _ => panic!("Wrong data type"), } } @@ -385,7 +423,9 @@ impl ColumnDataBuffer { // parse bytes to String match self { ColumnDataBuffer::C(data) => { - let string = unsafe { String::from_utf8_unchecked(bytes.to_vec()) }.trim_end().to_string(); + let string = unsafe { String::from_utf8_unchecked(bytes.to_vec()) } + .trim_end() + .to_string(); data[idx as usize] = string; } _ => panic!("Wrong data type"), @@ -395,7 +435,9 @@ impl ColumnDataBuffer { // parse bytes to String match self { ColumnDataBuffer::M(data) => { - let string = unsafe { String::from_utf8_unchecked(bytes.to_vec()) }.trim_end().to_string(); + let string = unsafe { String::from_utf8_unchecked(bytes.to_vec()) } + .trim_end() + .to_string(); data[idx as usize] = string; } _ => panic!("Wrong data type"), @@ -405,8 +447,10 @@ impl ColumnDataBuffer { // parse bytes to String match self { ColumnDataBuffer::P(data) => { - data[idx as usize][0] = i32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]); - data[idx as usize][1] = i32::from_be_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]); + data[idx as usize][0] = + i32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]); + data[idx as usize][1] = + i32::from_be_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]); } _ => panic!("Wrong data type"), } @@ -415,15 +459,20 @@ impl ColumnDataBuffer { // parse bytes to String match self { ColumnDataBuffer::Q(data) => { - data[idx as usize][0] = i64::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7]]); - data[idx as usize][0] = i64::from_be_bytes([bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15]]); + data[idx as usize][0] = i64::from_be_bytes([ + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], + bytes[7], + ]); + data[idx as usize][0] = i64::from_be_bytes([ + bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], + bytes[14], bytes[15], + ]); } _ => panic!("Wrong data type"), } } _ => panic!("Wrong data type"), - } } //no need for max_len on bintable -} \ No newline at end of file +} diff --git a/src/io/hdus/image/image.rs b/src/io/hdus/image/image.rs index 567e179..1d925b1 100644 --- a/src/io/hdus/image/image.rs +++ b/src/io/hdus/image/image.rs @@ -1,24 +1,18 @@ use std::fs::File; use std::io::Read; -use crate::io::header::{Header, card::CardValue}; +use crate::io::header::{card::CardValue, Header}; -use rayon::prelude::*; use ndarray::ArrayBase; -use std::io::{Write, BufWriter}; +use std::io::{BufWriter, Write}; use crate::io::hdus::image::utils::{ - get_shape, - pre_bytes_to_f64_vec, - pre_bytes_to_f32_vec, - pre_bytes_to_u8_vec, - pre_bytes_to_i16_vec, - pre_bytes_to_i32_vec, - vec_to_ndarray, - nbytes_from_bitpix + get_shape, nbytes_from_bitpix, pre_bytes_to_f32_vec, pre_bytes_to_f64_vec, + pre_bytes_to_i16_vec, pre_bytes_to_i32_vec, pre_bytes_to_u8_vec, vec_to_ndarray, }; use ndarray::ArrayD; +use rayon::prelude::*; pub enum ImageData { U8(ArrayD), @@ -58,28 +52,18 @@ impl ImageData { pub fn get_shape(&self) -> Vec { match self { - ImageData::U8(array) => { - array.shape().to_vec() - }, - ImageData::I16(array) => { - array.shape().to_vec() - }, - ImageData::I32(array) => { - array.shape().to_vec() - }, - ImageData::F32(array) => { - array.shape().to_vec() - }, - ImageData::F64(array) => { - array.shape().to_vec() - }, + ImageData::U8(array) => array.shape().to_vec(), + ImageData::I16(array) => array.shape().to_vec(), + ImageData::I32(array) => array.shape().to_vec(), + ImageData::F32(array) => array.shape().to_vec(), + ImageData::F64(array) => array.shape().to_vec(), _ => vec![0, 0], } } } pub struct ImData { - pub data : ArrayD + pub data: ArrayD, } use std::fmt; @@ -89,48 +73,49 @@ impl fmt::Debug for ImageData { match self { ImageData::U8(array) => { write!(f, "FitsData::U8({:?})", array) - }, + } ImageData::I16(array) => { write!(f, "FitsData::I16({:?})", array) - }, + } ImageData::I32(array) => { write!(f, "FitsData::I32({:?})", array) - }, + } ImageData::F32(array) => { write!(f, "FitsData::F32({:?})", array) - }, + } ImageData::F64(array) => { write!(f, "FitsData::F64({:?})", array) - }, + } _ => write!(f, "FitsData::EMPTY"), } } } - - pub struct ImageParser; impl ImageParser { //TODO: Find where to implement BZERO and BSCALE pub fn calculate_image_bytes(header: &Header) -> usize { - let bitpix : i32 = header["BITPIX"].value.as_int().unwrap_or(0) as i32; + let bitpix: i32 = header["BITPIX"].value.as_int().unwrap_or(0) as i32; let shape = get_shape(header).unwrap(); let dtype_bytes = nbytes_from_bitpix(bitpix); shape.iter().fold(1, |acc, x| acc * x) * dtype_bytes } - pub fn read_from_buffer(f: &mut File, header: &mut Header) -> Result { + pub fn read_from_buffer( + f: &mut File, + header: &mut Header, + ) -> Result { let _naxis: usize = header["NAXIS"].value.as_int().unwrap_or(0) as usize; - - let bitpix : i32 = header["BITPIX"].value.as_int().unwrap_or(0) as i32; + + let bitpix: i32 = header["BITPIX"].value.as_int().unwrap_or(0) as i32; let shape = get_shape(header)?; // Get data type from BITPIX let dtype_bytes = nbytes_from_bitpix(bitpix); let total_bytes = shape.iter().fold(1, |acc, x| acc * x) * dtype_bytes; - let mut databuf = vec![0; total_bytes]; + let mut databuf = vec![0; total_bytes]; let _ = f.read(&mut databuf)?; // Read until the end of the current FITS block @@ -141,10 +126,14 @@ impl ImageParser { // println!("Padding: {:?}", padding.len()); } - ImageParser::image_buffer_to_ndarray(&databuf, shape, bitpix) + ImageParser::image_buffer_to_ndarray(&databuf, shape, bitpix) } - pub fn image_buffer_to_ndarray(databuf: &Vec, shape: Vec, bitpix: i32) -> Result { + pub fn image_buffer_to_ndarray( + databuf: &Vec, + shape: Vec, + bitpix: i32, + ) -> Result { match bitpix { 8 => { let mut vect: Vec = vec![0; databuf.len() / 1]; @@ -152,38 +141,40 @@ impl ImageParser { let ndarray = vec_to_ndarray(vect, shape); let data: ImageData = ImageData::U8(ndarray); Ok(data) - }, + } 16 => { let mut vect: Vec = vec![0; databuf.len() / 2]; pre_bytes_to_i16_vec(&databuf, &mut vect); let ndarray = vec_to_ndarray(vect, shape); let data = ImageData::I16(ndarray); Ok(data) - }, + } 32 => { let mut vect: Vec = vec![0; databuf.len() / 4]; pre_bytes_to_i32_vec(&databuf, &mut vect); let ndarray = vec_to_ndarray(vect, shape); let data = ImageData::I32(ndarray); Ok(data) - }, + } -32 => { let mut vect: Vec = vec![0.0; databuf.len() / 4]; pre_bytes_to_f32_vec(&databuf, &mut vect); - let ndarray: ArrayBase, ndarray::Dim> = vec_to_ndarray(vect, shape); + let ndarray: ArrayBase, ndarray::Dim> = + vec_to_ndarray(vect, shape); let data = ImageData::F32(ndarray); Ok(data) - }, + } -64 => { let mut vect: Vec = vec![0.0; databuf.len() / 8]; pre_bytes_to_f64_vec(&databuf, &mut vect); let ndarray = vec_to_ndarray(vect, shape); let data = ImageData::F64(ndarray); Ok(data) - }, - _ => { - Err(std::io::Error::new(std::io::ErrorKind::Other, "Not implemented")) - }, + } + _ => Err(std::io::Error::new( + std::io::ErrorKind::Other, + "Not implemented", + )), } } @@ -191,24 +182,34 @@ impl ImageParser { match data { ImageData::U8(array) => { let vect = array.clone().into_raw_vec(); - vect.par_iter().flat_map(|&item| item.to_be_bytes().to_vec()).collect::>() - }, + vect.par_iter() + .flat_map(|&item| item.to_be_bytes().to_vec()) + .collect::>() + } ImageData::I16(array) => { let vect = array.clone().into_raw_vec(); - vect.par_iter().flat_map(|&item| item.to_be_bytes().to_vec()).collect::>() - }, + vect.par_iter() + .flat_map(|&item| item.to_be_bytes().to_vec()) + .collect::>() + } ImageData::I32(array) => { let vect = array.clone().into_raw_vec(); - vect.par_iter().flat_map(|&item| item.to_be_bytes().to_vec()).collect::>() - }, + vect.par_iter() + .flat_map(|&item| item.to_be_bytes().to_vec()) + .collect::>() + } ImageData::F32(array) => { let vect = array.clone().into_raw_vec(); - vect.par_iter().flat_map(|&item| item.to_be_bytes().to_vec()).collect::>() - }, + vect.par_iter() + .flat_map(|&item| item.to_be_bytes().to_vec()) + .collect::>() + } ImageData::F64(array) => { let vect = array.clone().into_raw_vec(); - vect.par_iter().flat_map(|&item| item.to_be_bytes().to_vec()).collect::>() - }, + vect.par_iter() + .flat_map(|&item| item.to_be_bytes().to_vec()) + .collect::>() + } _ => vec![], } } @@ -219,19 +220,18 @@ impl ImageParser { if shape.eq(&vec![0, 0]) { naxis = 0; } - - + let bitpix = data.get_bitpix(); header["BITPIX"].value = CardValue::INT(bitpix as i64); header["NAXIS"].value = CardValue::INT(naxis as i64); - + for i in 0..naxis { - let naxisn = format!("NAXIS{}", i+1); + let naxisn = format!("NAXIS{}", i + 1); header[naxisn.as_str()].value = CardValue::INT(shape[i] as i64); } //if other NAXISn keywords are present, remove them - for i in naxis+1..=7 { + for i in naxis + 1..=7 { let naxisn = format!("NAXIS{}", i); if header.contains_key(naxisn.as_str()) { header.remove(naxisn.as_str()); @@ -239,7 +239,10 @@ impl ImageParser { } } - pub fn write_to_buffer(data : &ImageData, mut writer: impl std::io::Write) -> std::io::Result<()> { + pub fn write_to_buffer( + data: &ImageData, + mut writer: impl std::io::Write, + ) -> std::io::Result<()> { let mut buffer = ImageParser::ndarray_to_buffer_parallel(&data); let remainder = buffer.len() % 2880; if remainder != 0 { @@ -260,28 +263,28 @@ impl ImageParser { writer.write_all(&bytes)?; bytes_written += bytes.len(); } - }, + } ImageData::I16(ndarray) => { for &item in ndarray.iter() { let bytes: [u8; 2] = item.to_be_bytes(); writer.write_all(&bytes)?; bytes_written += bytes.len(); } - }, + } ImageData::I32(ndarray) => { for &item in ndarray.iter() { let bytes: [u8; 4] = item.to_be_bytes(); writer.write_all(&bytes)?; bytes_written += bytes.len(); } - }, + } ImageData::F32(ndarray) => { for &item in ndarray.iter() { let bytes: [u8; 4] = f32::to_be_bytes(item); writer.write_all(&bytes)?; bytes_written += bytes.len(); } - }, + } ImageData::F64(ndarray) => { for &item in ndarray.iter() { let bytes: [u8; 8] = f64::to_be_bytes(item); @@ -300,4 +303,3 @@ impl ImageParser { writer.flush() } } - diff --git a/src/io/hdus/table/buffer.rs b/src/io/hdus/table/buffer.rs index 9b997b9..d74bf41 100644 --- a/src/io/hdus/table/buffer.rs +++ b/src/io/hdus/table/buffer.rs @@ -1,5 +1,5 @@ +use polars::{datatypes::PlSmallStr, prelude::NamedFrom, series::Series}; use rayon::prelude::*; -use polars::{prelude::NamedFrom, series::Series}; #[derive(Debug, PartialEq)] pub enum ColumnDataBuffer { @@ -11,7 +11,7 @@ pub enum ColumnDataBuffer { } impl ColumnDataBuffer { - pub fn new(tform : &str, size : i32) -> Self { + pub fn new(tform: &str, size: i32) -> Self { let tform = tform.trim(); let tform_type = tform.chars().next().unwrap(); match tform_type { @@ -26,15 +26,31 @@ impl ColumnDataBuffer { pub fn max_len(&self) -> usize { match self { - ColumnDataBuffer::I(data) => data.par_iter().map(|x| x.to_string().len()).max().unwrap_or(0), - ColumnDataBuffer::E(data) => data.par_iter().map(|x| x.to_string().len()).max().unwrap_or(0), - ColumnDataBuffer::D(data) => data.par_iter().map(|x| x.to_string().len()).max().unwrap_or(0), + ColumnDataBuffer::I(data) => data + .par_iter() + .map(|x| x.to_string().len()) + .max() + .unwrap_or(0), + ColumnDataBuffer::E(data) => data + .par_iter() + .map(|x| x.to_string().len()) + .max() + .unwrap_or(0), + ColumnDataBuffer::D(data) => data + .par_iter() + .map(|x| x.to_string().len()) + .max() + .unwrap_or(0), ColumnDataBuffer::A(data) => data.par_iter().map(|x| x.len()).max().unwrap_or(0), - ColumnDataBuffer::F(data) => data.par_iter().map(|x| x.to_string().len()).max().unwrap_or(0), + ColumnDataBuffer::F(data) => data + .par_iter() + .map(|x| x.to_string().len()) + .max() + .unwrap_or(0), } } - pub fn byte_value(&self) -> usize{ + pub fn byte_value(&self) -> usize { match self { ColumnDataBuffer::I(_data) => 4, ColumnDataBuffer::E(_data) => 4, @@ -44,7 +60,7 @@ impl ColumnDataBuffer { } } - pub fn byte_value_from_str(data_type : &str) -> usize { + pub fn byte_value_from_str(data_type: &str) -> usize { match data_type { "I" => 4, "E" => 4, @@ -55,18 +71,19 @@ impl ColumnDataBuffer { } } - pub fn to_series(&self, col_name : &str) -> Series { + pub fn to_series(&self, col_name: &str) -> Series { + let col_name = PlSmallStr::from_str(col_name); let series = match self { - ColumnDataBuffer::I(data) => Series::new(col_name, data), - ColumnDataBuffer::E(data) => Series::new(col_name, data), - ColumnDataBuffer::D(data) => Series::new(col_name, data), - ColumnDataBuffer::A(data) => Series::new(col_name, data), - ColumnDataBuffer::F(data) => Series::new(col_name, data), + ColumnDataBuffer::I(data) => Series::new(col_name, data), + ColumnDataBuffer::E(data) => Series::new(col_name, data), + ColumnDataBuffer::D(data) => Series::new(col_name, data), + ColumnDataBuffer::A(data) => Series::new(col_name, data), + ColumnDataBuffer::F(data) => Series::new(col_name, data), }; series } - pub fn clear(&mut self){ + pub fn clear(&mut self) { match self { ColumnDataBuffer::I(data) => data.clear(), ColumnDataBuffer::E(data) => data.clear(), @@ -76,46 +93,57 @@ impl ColumnDataBuffer { } } - pub fn write_on_idx(&mut self, bytes : &[u8], data_type : char, idx : i64){ - let string = String::from_utf8_lossy(&bytes).trim_end().trim_start().to_string(); + pub fn write_on_idx(&mut self, bytes: &[u8], data_type: char, idx: i64) { + let string = String::from_utf8_lossy(&bytes) + .trim_end() + .trim_start() + .to_string(); match data_type { 'I' => { // parse bytes to i32 match self { - ColumnDataBuffer::I(data) => data[idx as usize] = string.parse::().unwrap(), + ColumnDataBuffer::I(data) => { + data[idx as usize] = string.parse::().unwrap() + } _ => panic!("Wrong data type"), } - }, + } 'E' => { // parse bytes to f32 match self { - ColumnDataBuffer::E(data) => data[idx as usize] = string.parse::().unwrap(), + ColumnDataBuffer::E(data) => { + data[idx as usize] = string.parse::().unwrap() + } _ => panic!("Wrong data type"), } - }, + } 'D' => { // parse bytes to f64 match self { - ColumnDataBuffer::D(data) => data[idx as usize] = string.parse::().unwrap(), + ColumnDataBuffer::D(data) => { + data[idx as usize] = string.parse::().unwrap() + } _ => panic!("Wrong data type"), } - }, + } 'A' => { // parse bytes to String match self { ColumnDataBuffer::A(data) => data[idx as usize] = string, _ => panic!("Wrong data type"), } - }, + } 'F' => { // parse bytes to f32 match self { - ColumnDataBuffer::F(data) => data[idx as usize] = string.parse::().unwrap(), + ColumnDataBuffer::F(data) => { + data[idx as usize] = string.parse::().unwrap() + } _ => panic!("Wrong data type"), } - }, + } _ => panic!("Wrong data type"), } } //no need for max_len on bintable -} \ No newline at end of file +} diff --git a/src/io/hdus/table/table.rs b/src/io/hdus/table/table.rs index ac47082..736abb5 100644 --- a/src/io/hdus/table/table.rs +++ b/src/io/hdus/table/table.rs @@ -1,33 +1,41 @@ -use core::panic; -use std::{fs::File, io::{Read, Write}}; +use crate::io::hdus::table::table_utils::*; use crate::io::{ - Header, - header::card::Card, - utils::pad_buffer_to_fits_block, - utils::pad_read_buffer_to_fits_block, + header::card::Card, utils::pad_buffer_to_fits_block, utils::pad_read_buffer_to_fits_block, + Header, +}; +use core::panic; +use std::{ + fs::File, + io::{Read, Write}, }; -use crate::io::hdus::table::table_utils::*; use polars::prelude::*; use rayon::iter::{IntoParallelIterator, ParallelIterator}; -use crate::io::hdus::table::buffer::ColumnDataBuffer; use crate::io::hdus::bintable::split_buffer; +use crate::io::hdus::table::buffer::ColumnDataBuffer; #[derive(Debug)] pub struct Column { - pub ttype: String, + pub ttype: String, pub tform: String, pub tunit: Option, pub tdisp: Option, pub tbcol: Option, pub start_address: usize, - pub type_bytes : usize, + pub type_bytes: usize, pub char_type: char, } impl Column { - pub fn new(ttype: String, tform: String, tunit: Option, tdisp: Option, tbcol: Option, start_address: usize) -> Self { + pub fn new( + ttype: String, + tform: String, + tunit: Option, + tdisp: Option, + tbcol: Option, + start_address: usize, + ) -> Self { let tform2 = tform.clone(); let column = Column { ttype, @@ -35,7 +43,7 @@ impl Column { tunit, tdisp, tbcol, - start_address: start_address, + start_address: start_address, type_bytes: get_tform_type_size(&tform2).1, char_type: get_tform_type_size(&tform2).0, }; @@ -49,7 +57,12 @@ fn get_tform_type_size(tform: &str) -> (char, usize) { (tform.chars().next().unwrap(), 1) } else { let (type_char, size_str) = tform.split_at(1); - let size = size_str.split('.').next().unwrap().parse::().unwrap_or(1); + let size = size_str + .split('.') + .next() + .unwrap() + .parse::() + .unwrap_or(1); (type_char.chars().next().unwrap(), size) } } @@ -100,123 +113,145 @@ pub fn read_tableinfo_from_header(header: &Header) -> Result, String Ok(columns) } -pub fn read_table_bytes_to_df(columns : &mut Vec, nrows: i64, file: &mut File) -> Result { +pub fn read_table_bytes_to_df( + columns: &mut Vec, + nrows: i64, + file: &mut File, +) -> Result { let mut n_chunks: u16 = 1; let mut n_threads: u16 = num_cpus::get() as u16; if nrows > n_threads as i64 * 10 { n_chunks = n_threads; - } - else { + } else { n_threads = 1; } - + let bytes_per_row = calculate_number_of_bytes_of_row(columns); let buffer_size = bytes_per_row * nrows as usize; let limits = split_buffer(buffer_size, n_chunks, bytes_per_row as u16); - + let mut buffer = vec![0; buffer_size]; file.read_exact(&mut buffer)?; - let pool = rayon::ThreadPoolBuilder::new().num_threads(n_threads as usize).build().unwrap(); - let results : Vec> = pool.install(|| { - limits.into_par_iter().map(|(start, end)| { - let local_buffer = &buffer[start as usize..end as usize]; - let nbuffer_rows = (end - start) / bytes_per_row; - - let mut local_buf_cols : Vec = Vec::new(); - columns.iter().for_each(|column: &Column| { - local_buf_cols.push(ColumnDataBuffer::new(&column.tform, nbuffer_rows as i32)); - }); - - (0..nbuffer_rows).into_iter().for_each(|i| { - let row_start_idx = i * bytes_per_row; - let row = &local_buffer[row_start_idx..row_start_idx + bytes_per_row]; - columns.iter().enumerate().for_each(|(j, column)| { - let (data_type, size) = get_tform_type_size(&column.tform); - let data = &row[column.start_address..column.start_address + column.type_bytes + 1]; - local_buf_cols[j].write_on_idx(data, data_type, i as i64); + let pool = rayon::ThreadPoolBuilder::new() + .num_threads(n_threads as usize) + .build() + .unwrap(); + let results: Vec> = pool.install(|| { + limits + .into_par_iter() + .map(|(start, end)| { + let local_buffer = &buffer[start as usize..end as usize]; + let nbuffer_rows = (end - start) / bytes_per_row; + + let mut local_buf_cols: Vec = Vec::new(); + columns.iter().for_each(|column: &Column| { + local_buf_cols.push(ColumnDataBuffer::new(&column.tform, nbuffer_rows as i32)); }); - }); - let df_cols : Vec = columns.iter().enumerate().map(|(i, column)| { - let buf_col = &local_buf_cols[i]; - let series = buf_col.to_series(&column.ttype); - local_buf_cols[i].clear(); - series - }).collect(); - - let local_df = unsafe { DataFrame::new_no_checks(df_cols) }; + (0..nbuffer_rows).into_iter().for_each(|i| { + let row_start_idx = i * bytes_per_row; + let row = &local_buffer[row_start_idx..row_start_idx + bytes_per_row]; + columns.iter().enumerate().for_each(|(j, column)| { + let (data_type, _) = get_tform_type_size(&column.tform); + let data = &row + [column.start_address..column.start_address + column.type_bytes + 1]; + local_buf_cols[j].write_on_idx(data, data_type, i as i64); + }); + }); - Ok(local_df) - }).collect() + let df_cols: Vec = columns + .iter() + .enumerate() + .map(|(i, column)| { + let buf_col = &local_buf_cols[i]; + let series = buf_col.to_series(&column.ttype); + local_buf_cols[i].clear(); + series + }) + .collect(); + + let local_df = unsafe { DataFrame::new_no_checks(df_cols) }; + + Ok(local_df) + }) + .collect() }); drop(buffer); - let mut final_df = results[0].as_ref().unwrap().clone(); + let final_df = results[0].as_ref().unwrap().clone(); for i in 1..results.len() { - final_df.vstack(&results[i].as_ref().unwrap()); + final_df + .vstack(&results[i].as_ref().unwrap()) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?; } pad_read_buffer_to_fits_block(file, buffer_size)?; Ok(final_df.to_owned()) } - pub fn polars_to_columns(df: &DataFrame) -> Result, std::io::Error> { - let mut start_address : usize = 0; - let mut sum_to_address : usize = 0; + let mut start_address: usize = 0; + let mut sum_to_address: usize = 0; let mut max_length = None; - let columns : Vec = df.get_columns().into_iter().map(|series| { - let ttype = series.name().to_string(); - let tform = match series.dtype() { - DataType::Int32 => { - sum_to_address = 12 + 1; - "I12".to_string() - }, - DataType::Float32 => { - sum_to_address = 15 + 1; - "E15.7".to_string() - }, - DataType::Float64 => { - sum_to_address = 25 + 1; - "D25.17".to_string() - }, - DataType::String => { - let data = &series.str().unwrap(); - let mut lmax_length = data.iter().map(|item| item.unwrap_or("").len()).max().unwrap(); - if lmax_length % 2 != 0 { - lmax_length += 1 as usize; + let columns: Vec = df + .get_columns() + .into_iter() + .map(|series| { + let ttype = series.name().to_string(); + let tform = match series.dtype() { + DataType::Int32 => { + sum_to_address = 12 + 1; + "I12".to_string() } - sum_to_address = lmax_length + 1; - max_length = Some(lmax_length); - format!("A{}", lmax_length) - }, - _ => panic!("Unsupported data type"), - }; - let mut column = Column::new( - ttype, - tform, - None, - None, - Some(start_address as i32 + 1), - start_address - ); - - if max_length.is_some() { - column.type_bytes = max_length.unwrap(); - max_length = None; - } - - start_address += sum_to_address; - column - }).collect(); + DataType::Float32 => { + sum_to_address = 15 + 1; + "E15.7".to_string() + } + DataType::Float64 => { + sum_to_address = 25 + 1; + "D25.17".to_string() + } + DataType::String => { + let data = &series.str().unwrap(); + let mut lmax_length = data + .iter() + .map(|item| item.unwrap_or("").len()) + .max() + .unwrap(); + if lmax_length % 2 != 0 { + lmax_length += 1 as usize; + } + sum_to_address = lmax_length + 1; + max_length = Some(lmax_length); + format!("A{}", lmax_length) + } + _ => panic!("Unsupported data type"), + }; + let mut column = Column::new( + ttype, + tform, + None, + None, + Some(start_address as i32 + 1), + start_address, + ); + + if max_length.is_some() { + column.type_bytes = max_length.unwrap(); + max_length = None; + } + + start_address += sum_to_address; + column + }) + .collect(); Ok(columns) } - pub fn calculate_number_of_bytes_of_row(columns: &Vec) -> usize { let mut bytes = 0; for column in columns.iter() { @@ -228,35 +263,87 @@ pub fn calculate_number_of_bytes_of_row(columns: &Vec) -> usize { bytes } -pub fn create_table_on_header(header: &mut Header, columns: &Vec, nrows : i64) { +pub fn create_table_on_header(header: &mut Header, columns: &Vec, nrows: i64) { clear_table_on_header(header); let tfields = columns.len(); let num_bytes = calculate_number_of_bytes_of_row(columns); - header.add_card(&Card::new("BITPIX".to_string(), 8.to_string(), Some("Table BITPIX".to_string()))); - header.add_card(&Card::new("TFIELDS".to_string(), tfields.to_string(), Some("Number of fields per row".to_string()))); - header.add_card(&Card::new("NAXIS".to_string(), 2.to_string(), Some("2D table".to_string()))); - header.add_card(&Card::new("NAXIS1".to_string(), num_bytes.to_string(), Some("Number of bytes in row".to_string()))); - header.add_card(&Card::new("NAXIS2".to_string(), nrows.to_string(), Some("Number of rows".to_string()))); - header.add_card(&Card::new("PCOUNT".to_string(), 0.to_string(), Some("Parameter count".to_string()))); - header.add_card(&Card::new("GCOUNT".to_string(), 1.to_string(), Some("Group count".to_string()))); + header.add_card(&Card::new( + "BITPIX".to_string(), + 8.to_string(), + Some("Table BITPIX".to_string()), + )); + header.add_card(&Card::new( + "TFIELDS".to_string(), + tfields.to_string(), + Some("Number of fields per row".to_string()), + )); + header.add_card(&Card::new( + "NAXIS".to_string(), + 2.to_string(), + Some("2D table".to_string()), + )); + header.add_card(&Card::new( + "NAXIS1".to_string(), + num_bytes.to_string(), + Some("Number of bytes in row".to_string()), + )); + header.add_card(&Card::new( + "NAXIS2".to_string(), + nrows.to_string(), + Some("Number of rows".to_string()), + )); + header.add_card(&Card::new( + "PCOUNT".to_string(), + 0.to_string(), + Some("Parameter count".to_string()), + )); + header.add_card(&Card::new( + "GCOUNT".to_string(), + 1.to_string(), + Some("Group count".to_string()), + )); for (i, column) in columns.iter().enumerate() { - header.add_card(&Card::new(format!("TTYPE{}", i + 1), column.ttype.clone(), Some("Name of field".to_string()))); - header.add_card(&Card::new(format!("TFORM{}", i + 1), column.tform.clone(), Some("Format of field".to_string()))); + header.add_card(&Card::new( + format!("TTYPE{}", i + 1), + column.ttype.clone(), + Some("Name of field".to_string()), + )); + header.add_card(&Card::new( + format!("TFORM{}", i + 1), + column.tform.clone(), + Some("Format of field".to_string()), + )); if let Some(tunit) = &column.tunit { - header.add_card(&Card::new(format!("TUNIT{}", i + 1), tunit.clone(), Some("Unit of field".to_string()))); + header.add_card(&Card::new( + format!("TUNIT{}", i + 1), + tunit.clone(), + Some("Unit of field".to_string()), + )); } if let Some(tdisp) = &column.tdisp { - header.add_card(&Card::new(format!("TDISP{}", i + 1), tdisp.clone(), Some("Display format of field".to_string()))); + header.add_card(&Card::new( + format!("TDISP{}", i + 1), + tdisp.clone(), + Some("Display format of field".to_string()), + )); } if let Some(tbcol) = &column.tbcol { //TBCOL is the start byte of the field - header.add_card(&Card::new(format!("TBCOL{}", i + 1), tbcol.to_string(), Some("Starting byte of field".to_string()))); + header.add_card(&Card::new( + format!("TBCOL{}", i + 1), + tbcol.to_string(), + Some("Starting byte of field".to_string()), + )); } } } -pub fn df_to_buffer(columns: Vec, df: &DataFrame, file: &mut File) -> Result<(), std::io::Error> { +pub fn df_to_buffer( + columns: Vec, + df: &DataFrame, + file: &mut File, +) -> Result<(), std::io::Error> { //buffer should be written in utf8 let nrows = df.height(); let bytes_per_row = calculate_number_of_bytes_of_row(&columns); @@ -266,117 +353,135 @@ pub fn df_to_buffer(columns: Vec, df: &DataFrame, file: &mut File) -> Re if nrows > n_threads as usize * 10 { n_chunks = n_threads; - } - else { + } else { n_threads = 1; } let limits = split_buffer(nrows, n_chunks, bytes_per_row as u16); - let pool = rayon::ThreadPoolBuilder::new().num_threads(n_threads as usize).build().unwrap(); - - let bufs : Vec> = pool.install(|| { - limits.into_iter().map(|(start, end)| { - let nbuffer_rows = end - start; - let local_df = &df.slice(start as i64, nbuffer_rows); - let mut local_buffer = vec![0x00; nbuffer_rows * bytes_per_row]; - - columns.iter().for_each(|column| { - let series = &local_df.column(&column.ttype).unwrap(); - let (_, size) = get_tform_type_size(&column.tform); - - match series.dtype() { - - DataType::Int32 => { - series.i32() - .expect("Expected an i32 series") - .into_iter() - .enumerate() - .for_each(|(j, item)| { - let item = item.unwrap(); - let mut string = item.to_string(); - while string.len() <= column.type_bytes { - string.push(' '); - } - - let row_start_add = j * bytes_per_row; - let col_start_add = row_start_add + column.start_address; - local_buffer[col_start_add..col_start_add + column.type_bytes + 1].copy_from_slice(&string.as_bytes()); - }); - }, - DataType::Float32 => { - series.f32() - .expect("Expected a f32 series") - .into_iter() - .enumerate() - .for_each(|(j, item)| { - let item = item.unwrap(); - let mut string = format_scientific(item as f64, size); - while string.len() <= column.type_bytes { - string.push(' '); - } - println!("column.start_address: {:?} ", column.start_address); - println!("column.type_bytes: {:?} ", column.type_bytes); - println!("column.ttype: {:?} ", column.ttype); - println!("column.tform: {:?} ", column.tform); - println!("buffer len {:?} ", string.len()); - - let row_start_add = j * bytes_per_row; - let col_start_add = row_start_add + column.start_address; - local_buffer[col_start_add..col_start_add + column.type_bytes + 1].copy_from_slice(&string.as_bytes()); - }); - }, - DataType::Float64 => { - series.f64() - .expect("Expected a f64 series") - .into_iter() - .enumerate() - .for_each(|(j, item)| { - let item = item.unwrap(); - let mut string = format_scientific(item, size); - while string.len() <= column.type_bytes { - string.push(' '); - } - - println!("column.start_address: {:?} ", column.start_address); - println!("column.type_bytes: {:?} ", column.type_bytes); - println!("column.ttype: {:?} ", column.ttype); - println!("column.tform: {:?} ", column.tform); - println!("buffer len {:?} ", string.len()); - - let row_start_add = j * bytes_per_row; - let col_start_add = row_start_add + column.start_address; - local_buffer[col_start_add..col_start_add + column.type_bytes + 1].copy_from_slice(&string.as_bytes()); - }); - }, - DataType::String => { - series.cast(&DataType::String).unwrap().str() - .expect("Expected a string series") - .into_iter() - .enumerate() - .for_each(|(j, item)| { - let item = item.unwrap_or(""); - let mut buffer = item.as_bytes().to_vec(); - - while buffer.len() <= column.type_bytes { - buffer.push(b' '); - } - - println!("column.start_address: {:?} ", column.start_address); - println!("column.type_bytes: {:?} ", column.type_bytes); - println!("column.ttype: {:?} ", column.ttype); - println!("column.tform: {:?} ", column.tform); - println!("buffer len {:?} ", buffer.len()); - - let row_start_add = j * bytes_per_row; - let col_start_add = row_start_add + column.start_address; - local_buffer[col_start_add..col_start_add + column.type_bytes + 1].copy_from_slice(&buffer); - }); - }, - _ => panic!("Unsupported data type"), - } - }); - local_buffer.to_owned() - }).collect() + let pool = rayon::ThreadPoolBuilder::new() + .num_threads(n_threads as usize) + .build() + .unwrap(); + + let bufs: Vec> = pool.install(|| { + limits + .into_iter() + .map(|(start, end)| { + let nbuffer_rows = end - start; + let local_df = &df.slice(start as i64, nbuffer_rows); + let mut local_buffer = vec![0x00; nbuffer_rows * bytes_per_row]; + + columns.iter().for_each(|column| { + let series = &local_df.column(&column.ttype).unwrap(); + let (_, size) = get_tform_type_size(&column.tform); + + match series.dtype() { + DataType::Int32 => { + series + .i32() + .expect("Expected an i32 series") + .into_iter() + .enumerate() + .for_each(|(j, item)| { + let item = item.unwrap(); + let mut string = item.to_string(); + while string.len() <= column.type_bytes { + string.push(' '); + } + + let row_start_add = j * bytes_per_row; + let col_start_add = row_start_add + column.start_address; + local_buffer + [col_start_add..col_start_add + column.type_bytes + 1] + .copy_from_slice(&string.as_bytes()); + }); + } + DataType::Float32 => { + series + .f32() + .expect("Expected a f32 series") + .into_iter() + .enumerate() + .for_each(|(j, item)| { + let item = item.unwrap(); + let mut string = format_scientific(item as f64, size); + while string.len() <= column.type_bytes { + string.push(' '); + } + println!("column.start_address: {:?} ", column.start_address); + println!("column.type_bytes: {:?} ", column.type_bytes); + println!("column.ttype: {:?} ", column.ttype); + println!("column.tform: {:?} ", column.tform); + println!("buffer len {:?} ", string.len()); + + let row_start_add = j * bytes_per_row; + let col_start_add = row_start_add + column.start_address; + local_buffer + [col_start_add..col_start_add + column.type_bytes + 1] + .copy_from_slice(&string.as_bytes()); + }); + } + DataType::Float64 => { + series + .f64() + .expect("Expected a f64 series") + .into_iter() + .enumerate() + .for_each(|(j, item)| { + let item = item.unwrap(); + let mut string = format_scientific(item, size); + while string.len() <= column.type_bytes { + string.push(' '); + } + + println!("column.start_address: {:?} ", column.start_address); + println!("column.type_bytes: {:?} ", column.type_bytes); + println!("column.ttype: {:?} ", column.ttype); + println!("column.tform: {:?} ", column.tform); + println!("buffer len {:?} ", string.len()); + + let row_start_add = j * bytes_per_row; + let col_start_add = row_start_add + column.start_address; + local_buffer + [col_start_add..col_start_add + column.type_bytes + 1] + .copy_from_slice(&string.as_bytes()); + }); + } + DataType::String => { + series + .cast(&DataType::String) + .unwrap() + .str() + .expect("Expected a string series") + .into_iter() + .enumerate() + .for_each(|(j, item)| { + let item = item.unwrap_or(""); + let mut buffer = item.as_bytes().to_vec(); + + while buffer.len() <= column.type_bytes { + buffer.push(b' '); + } + + println!("column.start_address: {:?} ", column.start_address); + println!("column.type_bytes: {:?} ", column.type_bytes); + println!("column.ttype: {:?} ", column.ttype); + println!("column.tform: {:?} ", column.tform); + println!("buffer len {:?} ", buffer.len()); + + let row_start_add = j * bytes_per_row; + let col_start_add = row_start_add + column.start_address; + local_buffer + [col_start_add..col_start_add + column.type_bytes + 1] + .copy_from_slice(&buffer); + }); + } + _ => panic!("Unsupported data type"), + } + }); + local_buffer.to_owned() + }) + .collect() }); let mut bytes_written = 0; @@ -391,4 +496,3 @@ pub fn df_to_buffer(columns: Vec, df: &DataFrame, file: &mut File) -> Re pad_buffer_to_fits_block(file, bytes_written)?; Ok(()) } - From 70dca8ff5f429a97556ecb0165fe86f3da3403ca Mon Sep 17 00:00:00 2001 From: Harlan Date: Thu, 3 Oct 2024 17:07:21 -0700 Subject: [PATCH 02/11] pub --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b55163a..aeef73c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ authors = [ "Thales Lopes thales.t.lopes@gmail.com", ] # A list of the package authors edition = "2021" -name = "astrors" +name = "astrors_(fork)" version = "0.1.9" license = "BSD-3-Clause" # The license your package is under @@ -13,7 +13,7 @@ repository = "https://github.com/schwarzam/astrors" readme = "README.md" -description = "Astronomical package to deal with FITS (compressed also) and WCS, still in development." +description = "(FORK) Astronomical package to deal with FITS (compressed also) and WCS, still in development." include = ["/src", "LICENSE", "README.md"] From 50dc0fd1ceb5814129c605ac74157ea613cc7baf Mon Sep 17 00:00:00 2001 From: Harlan Date: Thu, 3 Oct 2024 17:07:39 -0700 Subject: [PATCH 03/11] pub --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index aeef73c..06b1aa3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ authors = [ "Thales Lopes thales.t.lopes@gmail.com", ] # A list of the package authors edition = "2021" -name = "astrors_(fork)" +name = "astrors-fork" version = "0.1.9" license = "BSD-3-Clause" # The license your package is under From 9d1f35e9c9b89636e7a2c1f6844e7358c5f0adb6 Mon Sep 17 00:00:00 2001 From: Harlan Date: Thu, 3 Oct 2024 17:32:20 -0700 Subject: [PATCH 04/11] pub --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 06b1aa3..53dca6f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ authors = [ ] # A list of the package authors edition = "2021" name = "astrors-fork" -version = "0.1.9" +version = "0.1.10" license = "BSD-3-Clause" # The license your package is under repository = "https://github.com/schwarzam/astrors" @@ -22,7 +22,7 @@ include = ["/src", "LICENSE", "README.md"] [dependencies] ndarray = "0.15.6" num_cpus = "1.0" -polars = {version = "0.43.1", features = ["dtype-u8", "dtype-i8", "dtype-i16"]} +polars = {version = "0.41.0", features = ["dtype-u8", "dtype-i8", "dtype-i16"]} rand = "0.8.5" rayon = "1.8.0" regex = "1.10.3" From af35fea69b83aaf217d85aa2fdf6f12f2cf0805a Mon Sep 17 00:00:00 2001 From: Harlan Date: Thu, 3 Oct 2024 17:34:46 -0700 Subject: [PATCH 05/11] pub --- src/io/hdus/bintable/buffer.rs | 9 ++++----- src/io/hdus/table/buffer.rs | 4 ++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/io/hdus/bintable/buffer.rs b/src/io/hdus/bintable/buffer.rs index 0cc51eb..c323676 100644 --- a/src/io/hdus/bintable/buffer.rs +++ b/src/io/hdus/bintable/buffer.rs @@ -1,4 +1,3 @@ -use polars::datatypes::PlSmallStr; use polars::{prelude::NamedFrom, series::Series}; use crate::io::hdus::bintable::*; @@ -149,8 +148,8 @@ impl ColumnArrayBuffer { } pub fn to_series(&self, col_name: &str) -> Series { - let col = PlSmallStr::from_str(col_name); - let blank = PlSmallStr::from_str(""); + let col = col_name; + let blank = ""; let series = match self { ColumnArrayBuffer::L(data) => Series::new( col, @@ -281,8 +280,8 @@ impl ColumnDataBuffer { } pub fn to_series(&self, col_name: &str) -> Series { - let col = PlSmallStr::from_str(col_name); - let blank = PlSmallStr::from_str(""); + let col = col_name; + let blank = ""; let series = match self { ColumnDataBuffer::L(data) => Series::new(col, data), ColumnDataBuffer::X(data) => Series::new(col, data), diff --git a/src/io/hdus/table/buffer.rs b/src/io/hdus/table/buffer.rs index d74bf41..4b22df2 100644 --- a/src/io/hdus/table/buffer.rs +++ b/src/io/hdus/table/buffer.rs @@ -1,4 +1,4 @@ -use polars::{datatypes::PlSmallStr, prelude::NamedFrom, series::Series}; +use polars::{prelude::NamedFrom, series::Series}; use rayon::prelude::*; #[derive(Debug, PartialEq)] @@ -72,7 +72,7 @@ impl ColumnDataBuffer { } pub fn to_series(&self, col_name: &str) -> Series { - let col_name = PlSmallStr::from_str(col_name); + let col_name = col_name; let series = match self { ColumnDataBuffer::I(data) => Series::new(col_name, data), ColumnDataBuffer::E(data) => Series::new(col_name, data), From c44b162c704d33916769b7f8e05927ee411ac590 Mon Sep 17 00:00:00 2001 From: Harlan Date: Thu, 16 Jan 2025 13:30:44 -0800 Subject: [PATCH 06/11] Fixed BITPIX 16 to properly point to uint 16's instead --- src/io/hdus/image/image.rs | 21 +++++-- src/io/hdus/image/utils.rs | 84 ++++++++++++-------------- tests/data/F0072_exps_85684-00001.fits | 4 ++ 3 files changed, 61 insertions(+), 48 deletions(-) create mode 100755 tests/data/F0072_exps_85684-00001.fits diff --git a/src/io/hdus/image/image.rs b/src/io/hdus/image/image.rs index 1d925b1..6c692b5 100644 --- a/src/io/hdus/image/image.rs +++ b/src/io/hdus/image/image.rs @@ -9,7 +9,7 @@ use std::io::{BufWriter, Write}; use crate::io::hdus::image::utils::{ get_shape, nbytes_from_bitpix, pre_bytes_to_f32_vec, pre_bytes_to_f64_vec, - pre_bytes_to_i16_vec, pre_bytes_to_i32_vec, pre_bytes_to_u8_vec, vec_to_ndarray, + pre_bytes_to_i32_vec, pre_bytes_to_u16_vec, pre_bytes_to_u8_vec, vec_to_ndarray, }; use ndarray::ArrayD; use rayon::prelude::*; @@ -17,6 +17,7 @@ use rayon::prelude::*; pub enum ImageData { U8(ArrayD), I16(ArrayD), + U16(ArrayD), I32(ArrayD), F32(ArrayD), F64(ArrayD), @@ -31,6 +32,7 @@ impl ImageData { pub fn get_bitpix(&self) -> i32 { match self { ImageData::U8(_) => 8, + ImageData::U16(_) => 16, ImageData::I16(_) => 16, ImageData::I32(_) => 32, ImageData::F32(_) => -32, @@ -42,6 +44,7 @@ impl ImageData { pub fn get_dtype(&self) -> String { match self { ImageData::U8(_) => String::from("uint8"), + ImageData::U16(_) => String::from("uint16"), ImageData::I16(_) => String::from("int16"), ImageData::I32(_) => String::from("int32"), ImageData::F32(_) => String::from("float32"), @@ -53,6 +56,7 @@ impl ImageData { pub fn get_shape(&self) -> Vec { match self { ImageData::U8(array) => array.shape().to_vec(), + ImageData::U16(array) => array.shape().to_vec(), ImageData::I16(array) => array.shape().to_vec(), ImageData::I32(array) => array.shape().to_vec(), ImageData::F32(array) => array.shape().to_vec(), @@ -74,6 +78,9 @@ impl fmt::Debug for ImageData { ImageData::U8(array) => { write!(f, "FitsData::U8({:?})", array) } + ImageData::U16(array) => { + write!(f, "FitsData::U16({:?})", array) + } ImageData::I16(array) => { write!(f, "FitsData::I16({:?})", array) } @@ -143,10 +150,10 @@ impl ImageParser { Ok(data) } 16 => { - let mut vect: Vec = vec![0; databuf.len() / 2]; - pre_bytes_to_i16_vec(&databuf, &mut vect); + let mut vect: Vec = vec![0; databuf.len() / 2]; + pre_bytes_to_u16_vec(&databuf, &mut vect); let ndarray = vec_to_ndarray(vect, shape); - let data = ImageData::I16(ndarray); + let data = ImageData::U16(ndarray); Ok(data) } 32 => { @@ -186,6 +193,12 @@ impl ImageParser { .flat_map(|&item| item.to_be_bytes().to_vec()) .collect::>() } + ImageData::U16(array) => { + let vect = array.clone().into_raw_vec(); + vect.par_iter() + .flat_map(|&item| item.to_be_bytes().to_vec()) + .collect::>() + } ImageData::I16(array) => { let vect = array.clone().into_raw_vec(); vect.par_iter() diff --git a/src/io/hdus/image/utils.rs b/src/io/hdus/image/utils.rs index 5c9204a..bc1f4b0 100644 --- a/src/io/hdus/image/utils.rs +++ b/src/io/hdus/image/utils.rs @@ -1,9 +1,9 @@ -use rayon::prelude::*; use ndarray::{ArrayD, IxDyn}; +use rayon::prelude::*; use crate::io::header::Header; -pub fn nbytes_from_bitpix(bitpix : i32) -> usize { +pub fn nbytes_from_bitpix(bitpix: i32) -> usize { match bitpix { 8 => 1, 16 => 2, @@ -39,69 +39,65 @@ pub fn bytes_to_f32_vec(bytes: &[u8]) -> Vec { .collect() } -pub fn bytes_to_f64_vec(bytes : &[u8]) -> Vec { +pub fn bytes_to_f64_vec(bytes: &[u8]) -> Vec { bytes .par_chunks(8) - .map(|b| f64::from_bits(u64::from_be_bytes([b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]]))) + .map(|b| { + f64::from_bits(u64::from_be_bytes([ + b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], + ])) + }) .collect() } -pub fn pre_bytes_to_f64_vec(bytes: &Vec, output: &mut Vec) { // Preallocated vect +pub fn pre_bytes_to_f64_vec(bytes: &Vec, output: &mut Vec) { + // Preallocated vect assert!(output.len() * 8 <= bytes.len()); - output.par_iter_mut() - .enumerate() - .for_each(|(i, item)| { - let chunk = &bytes[i * 8..(i+1) * 8]; - *item = f64::from_bits(u64::from_be_bytes([ - chunk[0], chunk[1], chunk[2], chunk[3], - chunk[4], chunk[5], chunk[6], chunk[7] - ])); - }); + output.par_iter_mut().enumerate().for_each(|(i, item)| { + let chunk = &bytes[i * 8..(i + 1) * 8]; + *item = f64::from_bits(u64::from_be_bytes([ + chunk[0], chunk[1], chunk[2], chunk[3], chunk[4], chunk[5], chunk[6], chunk[7], + ])); + }); } pub fn pre_bytes_to_f32_vec(bytes: &Vec, output: &mut Vec) { assert!(output.len() * 4 <= bytes.len()); - output.par_iter_mut() - .enumerate() - .for_each(|(i, item)| { - let chunk = &bytes[i * 4..(i+1) * 4]; - *item = f32::from_bits(u32::from_be_bytes([ - chunk[0], chunk[1], chunk[2], chunk[3] - ])); - }); + output.par_iter_mut().enumerate().for_each(|(i, item)| { + let chunk = &bytes[i * 4..(i + 1) * 4]; + *item = f32::from_bits(u32::from_be_bytes([chunk[0], chunk[1], chunk[2], chunk[3]])); + }); } pub fn pre_bytes_to_u8_vec(bytes: &Vec, output: &mut Vec) { assert!(output.len() <= bytes.len()); - output.par_iter_mut() - .enumerate() - .for_each(|(i, item)| { - *item = bytes[i] as u8; - }); + output.par_iter_mut().enumerate().for_each(|(i, item)| { + *item = bytes[i] as u8; + }); +} + +pub fn pre_bytes_to_u16_vec(bytes: &Vec, output: &mut Vec) { + assert!(output.len() * 2 <= bytes.len()); + output.par_iter_mut().enumerate().for_each(|(i, item)| { + let chunk = &bytes[i * 2..(i + 1) * 2]; + *item = u16::from_be_bytes([chunk[0], chunk[1]]); + }); } pub fn pre_bytes_to_i16_vec(bytes: &Vec, output: &mut Vec) { assert!(output.len() * 2 <= bytes.len()); - output.par_iter_mut() - .enumerate() - .for_each(|(i, item)| { - let chunk = &bytes[i * 2..(i+1) * 2]; - *item = i16::from_be_bytes([ - chunk[0], chunk[1] - ]); - }); + output.par_iter_mut().enumerate().for_each(|(i, item)| { + let chunk = &bytes[i * 2..(i + 1) * 2]; + *item = i16::from_be_bytes([chunk[0], chunk[1]]); + }); } pub fn pre_bytes_to_i32_vec(bytes: &Vec, output: &mut Vec) { assert!(output.len() * 4 <= bytes.len()); - output.par_iter_mut() - .enumerate() - .for_each(|(i, item)| { - let chunk = &bytes[i * 4..(i+1) * 4]; - *item = i32::from_be_bytes([ - chunk[0], chunk[1], chunk[2], chunk[3] - ]); - }); + output.par_iter_mut().enumerate().for_each(|(i, item)| { + let chunk = &bytes[i * 4..(i + 1) * 4]; + *item = i32::from_be_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]); + }); } pub fn get_shape(header: &Header) -> Result, std::io::Error> { @@ -118,4 +114,4 @@ pub fn get_shape(header: &Header) -> Result, std::io::Error> { pub fn vec_to_ndarray(data: Vec, shape: Vec) -> ArrayD { let shape_ix = IxDyn(&shape); ArrayD::from_shape_vec(shape_ix, data).unwrap() // handle the error appropriately in your code -} \ No newline at end of file +} diff --git a/tests/data/F0072_exps_85684-00001.fits b/tests/data/F0072_exps_85684-00001.fits new file mode 100755 index 0000000..2b074ac --- /dev/null +++ b/tests/data/F0072_exps_85684-00001.fits @@ -0,0 +1,4 @@ +SIMPLE = T / file does conform to FITS standard BITPIX = 8 / number of bits per data pixel NAXIS = 0 / number of data axes EXTEND = T / FITS dataset may contain extensions COMMENT = 'F0072_exps_85684-00001.fits' / F0072_exps_85684-00001.fits COMMENT and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359EXPOSURE= 0.00100000004749745 / [S] Total Exposure Time TEMP = -49. / [C] Temperature RINGCRNT= 485.793463665506 / [mA] Ring Current DATE = '2024-12-13T22:14:08' / Date ROI_L = 1309 / [Pix] ROI Left ROI_T = 526 / [Pix] ROI Top ROI_R = 2539 / [Pix] ROI Right ROI_B = 1627 / [Pix] ROI Bottom HIERARCH EPU Polarization = 100. / [Counts] Motor HIERARCH Coolstage Temp C = 0. / Analog HIERARCH CCD Temperature = -49. / Analog HIERARCH Beam Current = 485.813598632813 / Analog HIERARCH TEY signal = -0.00171053952723293 / Analog IZERO = -0.0591141192154288 / Analog HIERARCH Photodiode = -0.000216364667963878 / Analog HIERARCH AI 0 = 0.0559638038907707 / Analog HIERARCH AI 3 Izero = -0.0184368382240574 / Analog HIERARCH AI 5 = -0.0165136428644282 / Analog HIERARCH AI 6 BeamStop = -1.03495551629581 / Analog HIERARCH AI 7 = 4.32005104223393E-05 / Analog HIERARCH Temperature Controller = 0. / [K] Motor HIERARCH PZT Shutter = 0. / [sec] Motor HIERARCH Pause Trigger = 0. / Analog HIERARCH LV Memory = 988220. / Analog HIERARCH Time Stamp Error = -0.00471401214599609 / Analog HIERARCH Time Stamp Transmit Time = 0.989241361618042 / Analog HIERARCH Time Stamp Server Time = 0.010758638381958 / Analog HIERARCH Camera Temp Setpoint = -50. / [Degrees] Motor HIERARCH Sample Azimuthal Rotation = 0. / [Degrees] Motor HIERARCH Piezo Vertical = 0. / [Micron] Motor HIERARCH Piezo Horiz = 0. / [Micron] Motor HIERARCH Sample X = 3. / [mm] Motor HIERARCH Sample Y = 18.58 / [mm] Motor HIERARCH Sample Z = -5. / [mm] Motor HIERARCH Sample Theta = 0. / [Degrees] Motor HIERARCH Sample Y Scaled = 6.35473426299093 / [Counts] Motor HIERARCH CCD Theta = 0.001 / [Degrees] Motor HIERARCH Beam Stop = 12. / [mm] Motor HIERARCH Pollux CCD X = 0. / [mm] Motor HIERARCH Pollux CCD Y = 0. / [mm] Motor HIERARCH CCD X = 100. / [mm] Motor HIERARCH CCD Y = 100. / [mm] Motor T-2T = 0. / [Degrees] Motor HIERARCH Beamline Energy = 280.000818200511 / [eV] Motor HIERARCH Mono 101 Grating = -37.3445849873692 / [mm] Motor HIERARCH Beamline Energy Goal = 0. / [eV] Motor HIERARCH Entrance Slit width = 35.0078125 / [eV] Motor HIERARCH Exit Slit Left = 4548.0078125 / [Micron] Motor HIERARCH Exit Slit Right = 6470. / [Micron] Motor HIERARCH Horizontal Exit Slit Size = 2999.9921875 / [Micron] Motor HIERARCH Horizontal Exit Slit Position = 990.00390625 / [Micron] Motor HIERARCH Vertical Exit Slit Size = 28.9387499999998 / [Micron] Motor HIERARCH Vertical Exit Slit Position = 0.00593749999984539 / [Micron] Motor HIERARCH EPU Gap = 27.3178625 / [mm] Motor HIERARCH EPU Z = 4.99984741211173E-05 / [mm] Motor HIERARCH Mono Energy = 280.000818200511 / [eV] Motor HIERARCH M103 Yaw = 2.7158 / [mm] Motor HIERARCH M103 Bend Up = 0.5731 / [mm] Motor HIERARCH M103 Bend Down = 1.0225 / [mm] Motor HIERARCH M101 Feedback = 0. / [mm] Motor HIERARCH M101 Horizontal Deflection = 2.333 / [milliradians] Motor HIERARCH M101 Vertical Deflection = -10.427 / [milliradians] Motor HIERARCH Vertical Slit Position = 0.00593749999984539 / [Micron] Motor HIERARCH Vertical Slit Size = 28.9387499999998 / [Micron] Motor HIERARCH Horizontal Slit Position = 990.00390625 / [Micron] Motor HIERARCH Mono 101 Vessel = 24.9998633333333 / [mm] Motor HIERARCH Horizontal Slit Size = 2999.9921875 / [Micron] Motor HIERARCH Diag 106 = 95. / [mm] Motor HIERARCH M121 Translation = 17.999719921875 / [mm] Motor HIERARCH PiezoShutter Trans = 18.8570033482143 / [mm] Motor HIERARCH Higher Order Suppressor = 8.99842710485057 / [mm] Motor HIERARCH AO 0 = 0. / [Counts] Motor HIERARCH AO 1 = 0. / [Counts] Motor HIERARCH OSP Adjustment = 0. / [Counts] Motor HIERARCH CCD Shutter Control = 0. / [Counts] Motor HIERARCH Upstream JJ Vert Aperture = 0.1 / [mm] Motor HIERARCH Upstream JJ Vert Trans = -0.147618140243902 / [mm] Motor HIERARCH Upstream JJ Horz Aperture = 0.1 / [mm] Motor HIERARCH Upstream JJ Horz Trans = -0.141164888211382 / [mm] Motor HIERARCH Middle JJ Vert Aperture = 0.45 / [mm] Motor HIERARCH Middle JJ Vert Trans = 2.53048145325203 / [mm] Motor HIERARCH Middle JJ Horz Aperture = 0.45 / [mm] Motor HIERARCH Middle JJ Horz Trans = 3.95181021341463 / [mm] Motor HIERARCH In-Chamber JJ Vert Aperture = 0.8001016002032 / [mm] Motor HIERARCH In-Chamber JJ Vert Trans = -2.94081788163576 / [mm] Motor HIERARCH In-Chamber JJ Horz Aperture = 0.8001016002032 / [mm] Motor HIERARCH In-Chamber JJ Horz Trans = 1.60223520447041 / [mm] Motor HIERARCH Sample Number = 7. / [Counts] Motor HIERARCH Coolstage = 0. / Motor HIERARCH MCS_axis0 = 0. / [Degrees] Motor HIERARCH MCS_axis1 = 0. / [Degrees] Motor HIERARCH MCS_axis2 = 0. / [Degrees] Motor HIERARCH MCS_axis3 = 0. / [Degrees] Motor HIERARCH MCS_axis4 = 0. / [Degrees] Motor HIERARCH CCD Camera Shutter Inhibit = 0. / [Counts] Motor HIERARCH Camera ROI X = 0. / [Counts] Motor HIERARCH Camera ROI Y = 720. / [Counts] Motor HIERARCH Camera ROI Width = 400. / [Counts] Motor HIERARCH Camera ROI Height = 400. / [Counts] Motor HIERARCH Camera ROI X Bin = 2. / [Counts] Motor HIERARCH Camera ROI Y Bin = 2. / [Counts] Motor HIERARCH SampleRot0 = 0. / [Degrees] Motor HIERARCH SampleRot1 = 0. / [Degrees] Motor HIERARCH SampleRot2 = 0. / [Degrees] Motor HIERARCH SampleRot3 = 0. / [Degrees] Motor HIERARCH SampleRot4 = 0. / [Degrees] Motor END XTENSION= 'BINTABLE' / binary table extension BITPIX = 8 / 8-bit bytes NAXIS = 2 / 2-dimensional binary table NAXIS1 = 4 / width of table in bytes NAXIS2 = 23 / number of rows in table PCOUNT = 0 / size of special data area GCOUNT = 1 / one data group (required keyword) TFIELDS = 1 / number of fields in each row EXTNAME = 'Izeros ' / name of this binary table extension TTYPE1 = '0 ' / label for field TFORM1 = 'E ' / format of field END ��f��f��f��f��f��f��f��f��f��f��f��f��f��f� u\�����H�����sO�$����� XTENSION= 'IMAGE ' / IMAGE extension BITPIX = 16 / number of bits per data pixel NAXIS = 2 / number of data axes NAXIS1 = 200 / length of data axis 1 NAXIS2 = 200 / length of data axis 2 PCOUNT = 0 / required keyword; must = 0 GCOUNT = 1 / required keyword; must = 1 BZERO = 32768 / offset data range to that of unsigned short BSCALE = 1 / default scaling factor EXTNAME = 'Images ' / Name of this extension. END �W�S�P�D�Q�a�U�W�<�1���_�Q�P�Z�e�Y�\�B�h�L�]�5�B�N�b�G�A�X�X�s�F�I�P�;�M�\�V�Y�]�e�N�N�J�U�N�Z�X�j�E�T�[�Q�S�K�n�Z�Q�Q��X�\�&�]�L�[�g�S�Y���C�Z�L�S�i�T�Z�:�b�L�8�Z�c�Y�;�`�Z�P�`�b�Y�S�L�]�A�T�g���U�n�Y�X���b�[�D�[�f�P�F�S�r�i�Y�g�Z�F�L�O�Y�X�p�S�g�T�X�V�q�[�K�H�I�9�L�I�Z�M�M�O�[�}�F�]�T�\�S�7�e�Y�_�P�N�1�O�V�D�]�`��e�c�@�V�X�[�<�Y�W�\�Y�Y�N�E�W�R�L�R�F�U�W�Q�T�V��i�X�T�]�G�Z�V�X�_��l�W�_�V�^�b�T�o�2�M�.�P�^�N�Z�P�*�]�R�l�X�V�R�U�;�B�8�]�w�.�Q�Y�g�O�V�X�Y�`�T�X�Y���o�W�I�4�>�6�P�<�v�D�[���`�M�c�O�]�C�N�U�S�S�k�]�R�>�K�?�=�O�M�^�L�i�N�`�w�_�b�Q�d�D�J�X�Y�^�-�T�M�=�R�Z�i�t�C�L�Q�F�M�6�Y�$�P�~�C�'�9�K�T�_�d�u�R�Y�r�N�R�q�`�U�L�P�Y�Z�]�F�3�\�T�J�P�R�^�l�V�[�F�`�:�Y�R�U�O�U�^�G�V�\�W�y���V�[�C�V�Q�m�U�_�O�T�T�[�Q�W�c�Q�b�:�R�R�o�X�6�U��`�`�]�[�Q�o�q�K�R�X�F�L�g�T�X�1�L�Z�O�Z�d�N�o�S�q�X�R�g�X�a�T�Q�=�T�U�l�L�Q�R�Z�;�@�P�O�O�D�X�,�/�P�P�n�Q�I�Q�]�\�d�h�L�S�R�Z��1�V�`�R�R�Z�E�[�Z�L�9�`�-�]�O�X�Y�Z�N���U�Y�c�V�R�`�F�r�X�\�[�X�H�R�]�O�[�i�T�Q�a�R�O�Y�b�^�D�L�U�z�\�S�3�J�Y�O�G�Y�o�J�J�B�f�X�N�[�q�^�M�[�g�>�b�U���^�X�M�O�]�[�R�?�Y�j�Z�n�W�u�H�O�\�M�J�b�X�%�d�"�U�W�U�S�Q�K�X�]�G�T�L�l�`�h�\�[�J�U�P�M�Q�O�S�X���P�X�Q�P�^�W�a�b�j�Y�r�M�W�I�O�X�J�F�U�K�U�M�g�g�&�R�P�W�X�\�]�U�P�O�O�c�4�K�Z�N�B�M�d�J�S�U�P�c�Y�A�t���U�O�V�_�J�]�B�g�;�S�P���M�Z�8�Q�2�]�\�[�C�@�\�Y�k�X�9�[�U�J�Q�H�8�`�Y�V�r�P�P�M�O�l�V�8�K�I�P�F�H�O�F�?�T�Y�H�E�s�R�\�;�J�W�I�:�\�Y�>�c�a�[�M�J�X�U�=�W���{�G�S�Z�S�V�&�b�R�7�[�Y�_�H�[�U�M�j�x�T�V�*�Y�^�S�Y�]�K�R�L�K�V�N�L�Y�]�s�F�[�V�2�X�Z�E�g�Y�d�`�L�V�W�_�G�_�T�U�W�0�c�Y�d�@�\�d�R�T�J�Z�o�A�q�]�K�P�`�Q�d�j�j�Z�W�5�U�L�\�n�6�`�E�S�N�[�]�S�J���I�U�Y�f�Z�G�W�J�P�G�Q�W�<�:�U�[�i�r�Q�j�U�O�^�W�D�Y�Y�e�U�a�]�1�V�d�V�N�N�c�d�J�h�>�E�\�S�N�X�\�I�V�V�?�P�v�L�D�F�Z�X�I�`�y�Q�]�_�S�A�W�j�L�Q�U�q�N�X�d�[�L�H�T�f�P�U�b�G�]�e�8�^�I�8�O�o�R�[�J�g�j�[�R�[��J�O�L�U�J�X�R�_�T�_�\�V�G�U�X�U�c�L�B��[�C�Y�B�l�b�U�;�r�T�T�_�^�Y�T�U�E�g�4�\�W�R�r�U�S�O�Z�e���T�V�P�\�]�\�@�]�E�X�G�f�[�Q�J�?�R�R�]�L�V�U�[�N�J�Q�R�Z�X�R�W�S�b�`�S�U���`�E�]�S�T�]�C�=�N�M�h�d�:�[�[�O�S�e�7�J�Z�v�i�\�q�,�U�V�G�T�c�G�Z�]�S�J���J�[�4�P�H�d�R�A�\�F�L�D�e�R�H�'�T�W�J�^�K�P�[�>�W�U�b�_�k�W�w�|�\�^�]�f�I�U�`�X�D�M�S�_�Y�K�S�g�U�P�M�\�X�_�Z�Q�O�+�^�Y�T�)�S�E�`�X�Y�P�M�]�U�[�Y�Q�c�[���F�X�D�f�^�X�G�^�G�\�e�N��n�X�V�\�>�\�V�`�Z�T�R��1�/�b�_�W�R�T�]�M�\�J�+�[�g�x�M�K�S�^�e�Z�b�L�O�O�@�P�v�q�I�L�b�L�V�c�?�I�R�q�M�O�T�T�T�E�T�F�^���e�U�d�[�T�^�@�J�J�P�E�R�D�I�S�?�Y�W�j�R�T�^�N�M�5�J�V�X�S�`�[�R�G�R�z�X�U�g�Y�L�2�v�B�d�E�=�R�`�J�c�_�,�V�N�x�L�W�V��W�H�Z�U�|�X�V�P�N�p�I�^�L�T�S�Z�]�g�D�\�R�R�g�Y�V�m�[�P�0�8�`�Z�N�]�B�p�b�h�Q�a�5�U�$�[�@�L�J�R�Z�E�V�G�X�Y���S�T�K�R�G�e�I�L�Z�Y�K�T�\�]�c�k�e�O�T�e�^�X�I�P���M�s�Y�Z�Z�C�\�V�D�;�W�Q�f�S�`�>�X�F�^�t�O�L�X�f�R�c�L�^�T�R�Q�]�T�L�X�]�d�=�U�[�X�T�N�`�Q�J�`�o�7�[�:�O�U�F�=�[�c�_�S�U�^�U�_�M�P�S�;�K�Y�[�Z�N�Y�F�R�d�]�O�O�J�O�X�L�e�]�J�A�]�L�]�Y�H�`�W�W�@�W�Z�J�W�W�K�U�^�V�Z�Y�[�L�Y�Y�R�^�K�N�j�M�Z�P�E�V�_�n�Z�S�m�L�T�b�\�I�I�Z�X�V�H�g�.�_�=�S�d�[�<�g�1�<�P�S�G�L�\�.�K�_�P�V�f�X�L�a�U�Z�U�S�f�Y�R�I�c�V�Z�v�F�@�c�F�N�b�Z�P�d�Q�@�\�V�u��T�L�S�G�h�@�M�N�U�O�c�L�N�d�N�J�Q�C�a�>�D�l�T�C�X�i�P�X�Y�g�N�E�a�r�T�S���D�[�U�J�^�i�U�=�E�M�Y�C�:�R�U�X�T�G�L�T�U�R�]�n�@�\�K�*�[�J�]�X�\�Q�\�R�/�O�D�U�V�;�Q�z�e�5�b�a�Y�X�x�\�^�T�N�U�P�Q�_�1�c��K�I�^�Z�`�S�K�V�J�=�l�]�V�P�E�<�f�d�\�K�O�`�O�X�g�Y�Q�(�_�m�Q�Z�L�M�U�;�Q�V��@�p�K�]�D�H�)�_�U�]�T�l�-�g�O�R�K�Z�g�W�Y�Y�[�J��Y�R�Y�s�D�R�m�O�1�J�9�;�]�h�\�6�C�Q�U�P�V�I�E�V�>�Y�P�N�U�q�]�[�P�b�]�i�O�N�J�]�O�T�l�T�h�T�Z�@�D� �^�W�[�[�Z�S�\�X�<�T�U���Q�^�V�`�O�G�T�?�Q�Q�M�`�b�=�h�k�L�V�M�]�S�Z�R�d�a�T�O�_�P�V�^�P�O�`�R�a�d�[�F�U�v�E�^�D�H�K�_�O�W�O�O�X�R�W�H�D�t�`�<�T�\� ��V�W�E�]�Y�L�*�T�i�[�t�P�k�f�c�Y�=�a�Z�V�X�\�D�Y�o���j�R�U�T�Q�<�O�Q�n�_�H�n�a�N�B�a�N�w�{�b�>�=�V�:�S�Q�U�W�T�Z�Q�P�T�j�W�[�L�d�^�P�U�K�M�S�U�J�A�M�;�W�K�O�I�]�T�S�[�V�S�S�p�-�Q�X�i�Y�\�B�Z�S�W�;�Q�U�J�Y�Y�z�M�P�M�K�<�Q�e�T�|�]�K�;�r�T�[�g�j�O�M�H�`�@�c�_�{�P�N�M�I�7�B�\�]�i�Y�K�K�}�W�e�_�P�W�R�X�_�o�V�\�U�D�E�Y�5�X�Q�[�[�U�O�\�`�^�V�X�`�F�\�T���[�j�Q�5�Y�p�9�S�i�T�S�h�j�`�\�^�_�W�F�Z�X�d�c�l���`�U�I�^�K�]�Z�L�O�Y�X�R�>�E�S�:�`�]�Y�Z�O��e�R�4�L�=�^�>�Y�i�t�>�F�T�F�G�]�N�8�Y�]�T�V�C�e�^�]�C�j�[�D�R�K�H�O�W�S�T�:�P�^�P�'�J�A�X�T�F���b�L�f�Z�Q�R���V�X�^�g�@�U�[�Z�]�Z�`���@�g�\�]�`�W�M�Y�5�^�`�W�W�X�^�s�\�X�g�R�R�V�d�d�e�K�V�c���O�P�f�h�P�M�H�Z�R�^�c�S�L�N�Z�J�f�X�a�Q�!�4�]�[�j�_�D�S�\�W�F�X�3�S�V�A�[�^�U�Q�U�\�[�!�'�a�c�Z�P���S�M�U�V�H�a�D�X�P�b�V�Z�}�^�Q�S�Y�R�X�h�b�\�Y�R�M�K�V�F�K�l�T�n�>�b�]�@�I�y�Y�O�O�D�I�X�r�d�N�Q�_�P�Z�R�Z�L�<�2�J�,�F�`�L�Q�R�|�0�_�X�T�[�G�R�Y�>�^�R�O�T�R�P�T�B�S�[� �h�T�L�S�U�`�^�W�Z�P�J���F�P�T�T�^�=�Z�R�e�Z�A�P��F�d�^�M�:�W�J�m�P�K�h�T�t�b�U�]�R�\�E�I�s�d�l�V�D�\�L�R�k�c�a�M�Y�_�X�Q�X�2�d�^�d�U�V�S�Q�X�H�[�T���f�[�\�n�K�W�Y�F�F�D�N�v�3�K�k�V�Q�Y�;�H�^�B�W�^�;�J�S�N�p�K�f�M�]�T�n�]�~�{�c�M�l�F�C�M�J�a�P�Z�G�f�G�M�F�e�U�|�Q�=�V�|�N�V�H�U�Y�D�9�e�W�Z�S�U�6��[�a�E�Q�O�q�Z�]�N�Z�_�L�^�^�W�]�I�S�V�E�V�[�T�Q�?�P�*�R�e�i�M�N�X�V�E�a�^�S�\�s�c�[�R�T�X�`�_�J�6�K�]�R�O�Z�N�]�T�r�V�`�U�c�Y�g�?�d�]�O�P�T�Y�F�D�M�z�L�G�H�V�m�X�`�A�[�V�R�Z�U�{�H�[�+�S�^�7�U�[�Z�U�r�4�q�f�]�`�X�X�\�a���e�O�P���T�g�W�V�M�_�Q�T�g�^�[�S�M�S�Z�V�Z�S�U�R�H�Z�W�^�h�`�c�W�W�_�O�D�W�S�X�M�>�b�T���6�S�Y�f�\�T�U�R��I�Z�Q�W�]�\�R�t�J�o�b�Z�C�`�Z�|�E�Y�Q�c�/�Y�o�[���S�O�G�e�R�R�P�<�Y�[�h�]�l�Q�n�R�c�P�R�P�^�S�@�A�r�^�q�Y�N�f�t�6�P�G�l�W�@�X�O�]�W�K�V�f�d�Y�b�d�?�`�P��K�@�V�N�Q�K�\�M�i�X�O���U�A�Z�c�%�7�a�S�K�D�T�Q�R�W�E�\�[�/�L��X�]�6�`�1�R�J�R�j�D�O�[�^�4�o�O�Z�]�M�U�\�T�N�U�S�Q�T�]�N���6�V�c�V�J�H�V�\�[�Z�k�R�4�g�Z�X�M�_�\�q�F�]�[�c�X�"�h�T�T�`�c�M�]�s�H�J�x�^�N�D�V�t�]�P�h�^�R�g���S�V�V�O�R�[�f�W�M�P�V�[�`�O�C�N�J�T�Y�]�H�T�Z�G�e�F�O�N�`�e�b�=�j�V�O�J�V�N�q�M�p�K�W�J�B�M�j�V�R�H�]�Q�`�w�C�^�V�B�V�I�V�S�M�H�P�R�R�H�T�]�U�T�n�M�\�m�=�Y�[�G�6�?�X�S�W�E�U�f�{�[�Q���U�U�\�S�^�K�L�J�a�?�D�K�C�g�^�G�N�X�n�D�h�w�T�P�K�]�t�H�<�Q�7�X�N�M�p�Y�F�d�h�Q�F�P�O�S�e�s�]�a�4�*�F�H�J�_�R�X�;�[��W�V�C�\�[�`�e�O�K�h�K�R�z�]�P�W�;�D�U�s�U�U�Y�U�a�q�e�O�J�X�6�c�A�H�B�V�P�E�E�W�K�Q�N�r�n�I�?�Z�P�A�Y�b�S�c�N�P�C�c�^�d�Y�7�]�8�T�F�N�W�S�d�H�7�0�m�U�J�K�S�Z�S�f�I�Y�Z�W�W�<�U�S�C�O�[�G�O�X�Y�P�\�q�O�Q�X�Y�>�_�7�Y�Q�A�S�F�f�Z�5�N�X�L�`�S�O�Y�K�I�O�M�x�Z�p�V�Z�5�X�X�M�L�F�]�=�R�[�6�H�N�\�Y�B�A�V�g�W�A�[�V�g�Q�V�N�S�G�t�O�Z�1�K�w�Z�\�^�b�U�]�Q�N�Z�P�9�R�\�X�V�@�>�W�Q�Q�Z�U�7�S�b�P�Q�s�P�e�\�O�[�R�:�Q�Y�Q�Y�V�K�a�G�V�n�Q�Y�N�\�P�T�h�[�\�G�]�^�4�S�a�C�S�W�M�Q�Y�\�U�Y�G�?�S�>�P�W�X�I�H�2�K�T�[�N�_�\�V�U�d�Z�V�P�_�O�Z�V�Y��k�P�A�n�;�Q�/�l�Q�D�^�[�x�W�?�R�<�J�g�_�C�U�V�O�o�W�[�[�K�[�W�Y�i�Y�>�U�Z�<�S�D�Z�^�R�9�g�M�H�J�I�>�R�V�Z�W�h�E�V�b�o�S�Q�S�e�L�J�Z�U�H�G�H�\�[�c�b�F�N�S�a�<�T�:�V�N�P�F�V�J�?���c�T�V�]�\�d�n�a�Z�V�I�G�D�N�E�_�V�L�M�]�_�7�[�'��h�W�U�m�G�V�_�i�^�?�Z�V�`�U�L�t�m�J�J�T�\�k�Q�L�D�g�@�Z�U�F�T�M�Q�e�O�B�r�h�M�W�i�L�m�I�F�L�S�[�s��7�C�U�X�T�U�\�C�Q�@�9���S�_�]�_�S�\�X�]�9�N�E�U�N�J�\�p�R�l�3�K�Y�O�E�_���^�]�R�B�W�k�Z�G�M�I�P�y�G�b�\�T�W�Q�Z�S�@�`�S�|�[�P�n�K�M�X�N���_�h�E�Q�R�V�F�R�T�]�M�D�O�d�:�[�t�E�Z�'�M�c�`�Y�[�J�c�^�h�u�Z�G�`�F�R�[�B�\�M�X�I�e�<�U�5�o�T�=�N�T�<�T�a�Z�M�J�Z�9�d�Y�]�d�h�r�W�D�G�v�@�Z�R�T�a�4�W�O�[�O�M�2�^�_�$�U�M�X�R�X�V�s�^�Q�N��T�O�(�J�T�_�R�O�I�T�C�f�>�N�]�V�O�T�a�U�J�X�h�^���N�Q�V�D�>�N�\�K�U�M�=�K�f�V�Q�P�V�K�J�`�K�T�a�D�X�X�M�Z�h�G�R�`�i�q�Q�O�:�U�G�O�S�g�[�6�S�P�]�V���U�O�C�V�Q�\�Q�^�4�^�d��W�S�a�R�W�B�L�c�r�S�Y�9��P�4�U�Q�c�S�F�M�S�T�h�^�K�R�V�L�V�Y�S�U�c�Y�f�L�[�U�\���R�B�I�g�]�J�T�=�T�9�J�B�m�_�N�_�N�H�]�P�W�J�Y�d�P�T�M�T�W���Y�L�M�U�a�4�t�N�P�X�c�J��b�\�h�_�R�N�S�O�b�^�6�U�T�\�d�H�X�(�p�O�N�p�O�]�K�Q�b�T�B���^�I�&��R�h�_�U�N�a�d�u�f�E�f�c�U�U�f�O�]�W�#�l�Y�[�z�;�P�\�\�[�O�X�V�a�R�q�:�W�b�H�O�7�R�T�i�W�U��L�T�U�`���T�-�T�T�W�S���@�M�L�\�/�_�K�P�l�e�H�J�K�R�X�H�Q�Y�d�[�:�h�[�'�d�N�l�U�V�H�]�A�X�Y�X�]�G�f�Z�Q�K�e�o�D�l�F�N�:�H�-�]�e�V�L�F�\�a�P�V�`�X��R�O�[�L�\�X�O�?�[�Q�^�O�S�:�q�L�`�J�P�J�N�C�W�U�V�c�#�T�i�f�`�H�m�V�d�E�U�y�]�T�a�Y�T�J�[�u�i�G�X�J�s�O�V�t�K�I�s�=�g�`�N�W�:�|�A�W�V�3�r�O�k�^�L�]�d�W�F�`�B�W�H�P�]�o�W�T�P�Q�o�j�[�4�W�Q�T�Y�V�&�`�?�Y�g�_�G�g�T�M�H�p�g�m�N�]�j�f�|�z�X�S�[�c�\���L�V�<�X�Q�U�m�[�Y�o�m�P�C�W�w�H�Q�U�R�Z�`�Q�b�d�W�F�\�O�U�[�X�V�Q�Z�O�O�\�R�Z�E�N�H�A�V�,�R�V�V�R�V�U�d���1�c�P�S�Q�^�O�\�E�p�o�F�I�Z�a�L�P�I�p�n�V�=�K�D�9�y�E�I�]�T�d�b�=�O�E�[�_�c�[�C�^�G�R�+�`�Z�Z�K�C�W�T�G�I�9�Z�R�g�H�D�J�M�j�Q�d�[�^�Y�Y�J�)�N�\�Z�d�C�#�f�R�=�S�M�S�O�V�c�S�?�P�Z�G�Z�p�N�H�b�S�f�B�I�i�Y�b�X�a�M�S�Q�a�P�M�N�Z�W�K�X�s�Y�C�P�J�`�O�Q�X�I�P�U�W�E�X�X�b�M�U�I�P�K�Z�9�Y�d�\�R�a�V�K�c�[�P�U�Q�N�b�E�R�Q�c�G�^�O�P�V�1�Y�J�S�7�h�[�L�U�\�Z�@���Q�S�M�]�^�B�T�W�S�]�P�V�W�T�T�O�a�R�W�[�V�U�\�F��R�V�V�G�L�W�O�f�\�\�Z�`�y�^�P�=�O�W�A�S�W�c�P����S�_�A�P�U�g�Q�Q�X�T�Z���b�d�:�Z�A�7�J�Q�V�Q�Z�G�Q�l��c�_�X�u�L�S�A�Z�N�W�X�f�b�N�]�Q�.�C�R�Y�S�a�\�R�L�N�l�q�@�M�V�L�W�\�8�K��U�U�L�T�Y�i�S�F�b�H�b�V���a�T��y�e�W�N�b�^�V�[�P�]�M�L�X�[�M�K�m�k�H�U�a�!�k�V�W�O�O�P�[�Z�U�[�K�b�b�V�P�R�U�c�U�K�]�J�W�(�V�P�O�Z�M�D�@�h�V�T�U�X�[�]�;�X�E�g�R�V�Y�J�f�L�V�J�J�}�\�\�H�Q�Q�D�U�e���G�T�G�K�N�T�U�L�8�X�K�C�p�P�X�M�W�\�[�V�Z�b�U�T�C�V�T�]�D�&�Y�S�U�R�Z�\�O�Z�j�H�]�S�e�H�T�M�M�M�N�r�M���L�Y�]�_�]�J�V�R�G�t�P���O�R�k�R�Y�]�o�G�Q�J�K�D�?�T�X�i�U�H�S�>�R�P�K�c�Q�S�P�M�[�a�g�X�S�J�M�I�[�Q�I�A�e�\�U�J�V�O�^�H�r�_�N�J�_�<�m�U�R�N�\�Z�b�T�s�Y�S�V�W�O�L�c�U�M�W�[�l�a�N�X�V�[�U�I�7�P�o�O�S���]�b�I�^�Z�k�;�R�w�N�V�C�@�I�R�U�[�[�E�F�M�X�M�_�l�R�S�[�W�^�M�5�V�]�\�^�Z�U�T�N�B�X�X�4�R�U�]�+�J�L�U�I�V�\�N�^�f�D�Q�R��j�L�P�^�R�R�Y�T�L�>�G�x�x�Y�R�`�P�u�W�J�e�V�U�K�Q�k�a�s�Y�U��T�J�Q�@�9�l�V�Z�E�U�X�S�g�X�M�B�%�P�E�^�~�S�6�[�S�Q�q�Q�L�K�W�O��W�N�S�X�P�V�;�S�k�l�Q�X�P�S�[�N�Q�e�Q�P�\�V�d�K���e�>�D�R�]�_�O�P�A�Q�J�g�k�W�S�X�T�H�Q�k�k�S�J�D��>�U�S�N�H�=�U�L�O�e�P�T�k�d�O�R�I�\�A���P�P�V�l�"�Z�8�T�W�S�M�T�I�d�O�a���_�j�j�V�@�Y�R�Q�G�^�m�7�D�Q�c�?�Q�N�L�_�[�I�Z�}�D�K�W�M�X�U�Q�X�d�u�U�Z�4�d�9�W�P�W�U�J�M�[�O�N�N�e�r�6�J�^�Q�R�Q�W�W�_�e���Z�P�8�O�@�X�e�M�R�T�M�$�^�W�r�^�e�q�J�l�Y�S�_�h�V�T�M�N�L�X�M��U�^�I�N�e�]�K�X�V��R�[�\�W�X�_�Q�D�_�R�>�9�W�e�Q�i�o�]�O�V�L�b�_�k�n�`�X�`�J�Y�P�E�M�!�L�X�b�T�c�:�]�j�b�?�S�\��K�H�_�L�D�V�\�V�R�l�d�c�L�w�V�O�O�B�\�E�X�_�W�]���R�S�P�Z�F�O�Y�Z�\�X�i�|�d�\�U�S�Y�O�J�Q�S�W�?�o�O�C�Q�K�J�#�]�P�j�D�V�<�_�^�Z�J�L�x�_�T�L�O�R�K�_�@�6�C�>�T�Q�H�H�j�_�a�"���Y�`�b�M�P�b�k�K�R�g�^���X�V�b�g�Q�P�Y�C�X�U�j�`�O�Y�`�I�]�_�R�T�P�R�e�E�F�R�k�Q�I�S�c�L�U�X�F�H�@�R�\�o�]�W�t�B�^�z�[�^�f�Y�T�F�M�s�N�Y�^�`�6�P�k�L��I�[�_�P�R�]�W�F�T�\�O�\�b�L�K�]�\�[�W�[�d�M�_�N�4�M�B�]�c�S�p�\�T�]�8�l�C�H�Q�Z�I���H�W�P�S�V�^�p�U�E�M�N�U�;�E�O�]�P�I�U�'�c�C�6�c�S�R�Y�A�S�^�J�V�_�?�W�V�S���G�c�T�K�;�W�]�e�`�P�Y�V�Y�e�A�I�V�Q�U�.�K�L�U�f�m�j�`�_�F�U�Y�?�w�^�W�^�K�M�@�m�M�U�O�G�A�X�b�T�Q�W�V�^�L�U�W�Q�Z�N�N�I�[�>�X�}�U�T�8�Z�H�;�T�L�B�W�m�X�1�K�\�U�c�t�V�S�H�R�D�I�P�y�J�o�;�M�I�W�d�d�Z�K�V�X�N�u�^�P�N�7�G�U�W�\�c�M�F�H�V�N�Q�c���P�R�\�Z�I�P�W�Y�[�S�f�G�Q�T�M�D�L�[�Q�l�O�H�B�b�S�P�M�G�E�>�\�[�Z�T�;�N�L�<�O�Y�T�D�Z�V�U�N�3�Y�X�7�c�F�M�T�^�\�_�W�^�Q�R�X���S�T�J�Y�B�J�:�M�B�[�/�Ă`�u�Y�L�J�\�d�Q�k�X�I�.�^�Y�K�\�W�P�G�Z�V�O�T�T�L�J�Q�e�\�e�U�M�P�8�h�T�X�-�Q�k�D�H�D�g�F�F�J�W���6�H�P�P�[�h�`�V�L�Q�]�F�;�R�[�N�^�P�J�M�^�H�Z�5�3�9�[�a�\�L�P�Q�0�V�D�5�V�d�M���s�T�X�o�Q�j�o�T�Y�K�O�-�Z�f�G�B�P�b�L�e�W�[�W��Y�@�U�N�Y�L�R�U�R�G�_�c�V�I�-�Q�a�[�Y�L�N�O�Q�J�}�W�_�^�W�T�\�W�P�T�W�<�(�\�W�T�]�\�M�C�3�j�c�Y�L�`�T�N�^�e�V�Z�T�e�R�W�;�h�8���u�M�P�Q�E�b�C�S�X�W���\�K�G�F�a�e�W�J�Y�R�Z�O�W�I�a�T�U�P�d�X�K�a�N�F�t�a�T�Y�N�=�A�G�V�Z�b�K�l�I�H�R�H�9�Z�`�W�I�D�V���d�h�B���Q�L�I�R�`�(�W�0�?�?�Y�P�e�e�Q�Q�M�g�d�t�x�K�]�K�k�V�R�Y�U�R�O�X�f�?�M�X�O�V�U�`�x�L�W�F�N���K�q�@�Z�[�Q�[�Q�`�R�n�A�{�V�F�F�7�b�b�U�b�I�`�=�c�Q�N�S�R�w�]�d�t�V�U�B�V�`�C�M�e�R�M�h�T�k�G�V�N�V�%�P�W�b�{�J�S�S�[�]�U�Q�p���d�W�U�`�W�\�C�S�k�`�U�M�M�,�O�S�K�J�d�Z�H�W�K�<�S�Y�4�P�E�Q�p�R�\�^�a�T�\�D�k�Y�K�M�U�V�k�X�d�h�M�<�a�H�J�h�Z�8�Z�+�W�M�K�W�K�[�P�O�U�L�V�Z�9�J�W�0�`�O�Y�J�b�i�o�]�J�U�U�)�[�b�T�Y�Y�`�_�V�p�f�O�0�M�Z�Q�M�t�+�_�1�V�W�u�R�p�M�T�e�j�:�Z�O�K�o�j�a�M�y�V�W�K�;�Q�\�j�Q�]�`�\�c�b�V�I�P�U�|�V�T�N�U�V�3�S�\���W�Z�^�F�\�V�\�N�`�9�]���]�S�?�<�X�O�b�J�Y�Z�M���^�]�S�S�J�Z�]�9�Z�a�T�d�`�N�R�V�s�P�G�e�N�S�W�B� �K�L�U�U�h�^�i�R�*�L�P�J�~�W�P�R�\�E�]�V�@�N�T�Q�[�S�X�S�W�V�G�a�S�\�P�Z�X�0�9�Q�X�@�X�l�M�T�A�J�W��E�C�p�X�N�m�C�Z�M�Q�h��M�Y�O�L�]�?�v�P�A�b�[�F�W�k�W�^�i�-�j�V�V�w�^�N�d�C�k�T�K�R�?�a�Q�P�K�U�s�R�7�`�r�P�L�y�U�c��N�\�;�Y�V�N�f�U�L�]�T�K�:�n�=�V�\�T�m�g�X�Z�H�Y�V�X�5�Q�S�X�a�}�T�Q�\�T�S�v�e�q�W�[�V�T�S�G�O�Y�Z�Z�a�c�X�K�[�j�P�s�P�O�O�H�\�]�H�7�D�a�F�O�N�C�Z�P�Q�T�R�<�V�^�N�R�}�W�S�R�b�P�D�Q�V�L�T�[�a�K�I�j�W�[�Y�]�W�;�a�C�T�/�V�^���:�g�T�]�R�m�z�b�R�R�Y�_�Q�[�B�O�Q�S�k�Y�M�_�K�K�O�J�e�R�Z�P�j�T�F�F�R�a�]�a�_�W�`��k�F�K�P�U�Y�-�U�e�C�Q�[�U�P�T�P�Z�t�L�T�^�d�W�\���X�l�R�~�O�d�[�Z�q�M�B�W�a�1�P�U�]�M�K�4�I�?�[�h� �W�X�\�c�`�N�]�U�_�k�c�^�T�Y�i�M�K�g�U�=�V�U�S�`�ȂJ�o�I�U�M�Q���L�V�G�E�S�d�X���k�Y�P�_�c�\�W�F�\�X�`�W�^�f��Q�W�X�l�J�[�F�b�'�m�O�9�U�Y�[�f�Q�d�H�P�^�N�\�k�S�\�Z�,�W�]�K�L�W�K�a�Q�U�O�k�K�Y�_�`�V�@�c�`�n�Y�c�I�_�\�c�W�K�R�E��B�I�X�`�[�H�M�r�U�`�k�T���O�]�U�T�T�s�P�>�O�M�O��S�K�o�P�X�Z�K�q�X�_�Y�2�O�U�W�U�Y�N�j�T�D�V�T�k�C�C�X�P�P�]�S�^�M�c�P�]�9�i�N�O�?�Y�0�R�V�F�r�[���V�Z�V�Z�O�S�G�6�a�?�[�T�p�n�[�J�O�X�P�\�]�\�P�H�>�S�O�J�d�X�@�Z�V�K�g�[�S�Q�]�D�|�S�g�U�V�R�E�B�T���]�{�N�;�[�G�\�V�@�B�Z�O�R�)�I�s�W�S�R�;�B�W�}�a�V�"�R�X�?�f�O�D�\�I�e�U�r�P�r�O�a�c�L�Q�[�X�7�V�T�J�X�D�^�O�o�P�e�U�T�P�1�p�Y��O�\�V�[�C�F�T�Q�W�Z�b�N�m�Q�T�K�U�[�N�g�R�<�^�T�H�b�U�J�E�o�X�V�@�R�X�i�2�X�A�Y�t�O�r�Y�Q�N�a�L�6�S�V�L�l�J�O�d�O�]�f�D�^�]�L�\�S�S�A�Y�W�N�X�L�T�p�_�e�L�P�X�l�h�V�Y�3�L�A�W�k�^�Q�[�S�Z�i�Q�j�R�Q�W�.�N�W�W�U�O�X�M�r�W�P�G�U�V�V�_�Z�[�U�h�O�R�`�\�M�T�[�_�A�;�V�e�S�F�^�o�X�C�W�n�b�V�\�R�M�k�S�Q�N�S�O�>�X�M�c�P�S�K�X�Z�G�W�/�w�X�4�Q�\�Y�I�R�@�W�X�l�Y�E�Q�y�R�Z�c�Y�V�c�M�A�X���K�Y�a�Z�O�\�]�J�H�X�P�h�B�U�e�Z�`�Q�S�O�Q�U�g�W��Z�`�>�Q�]�u�G�`�1�[�U�T�C�R�U�Y���[�q�O�`�K�G�Q�V�T�Y�B�|�T�6�X�T�W�Q�Y�c�@�I�N�O�F�N�S�M�W�U�X���L�T�^�N�L�[�[�E�L�c�V���R�;�c�R�K�W�_�Q�d�O�H�\���N�m�8�W�Q�=�Y�[�G�X�B�t�8�U�G�@�[�]�K�m�<�K�Q�\�C�^�`�Q�S�U�[�K�C�l�f�W�q�j�X�T�K�a�e�S�K�T�`�b�D�E�W��T�N�a�D�F�B�a�^�F�f�V�_�V�S�a�L�G�p�D�1�]�P�R�+�M�L�Q�B�{�R�U�i�Q�K�K�F���\�P�[�Z�Y�M�G�S�Z�d�U�=�]�J�]�W�R�j�_�R�a�Q�W�D���R�R�N�X�`�N�H�K�Z�W�T�p�X�a�E�[�L�T�Z�A�R�e�`�I�Z�X�U�h�U�W�S�]�\�Q�G�S�<�P�P�H���L�Q�T�U�M�i�a�{�a�V�R�[�Q�W�<�T�W�K�Z�S�I�\�S�l�\�h�8�T�W�\�f�P�R�_�A�f�Y�T�T�Y�A�O�V�N�U�O�d�T�G�K�.�^�j�R�q�n�K�e�S�Z�H�Z�p�X�H�9�[�t�j�P�S�@�J�J�Y�W�]�C�*�:�H�_�^�P�V�I�N�^�\�U�X�S�V�J�C�e�x�R�K�d�k�i�I�j�X�J�G�b� �`�S�V�Y�P�P�F�W�_�U�c�d���S�;�p�a�L�c�\�W�R�D�v�C�f�V�T�d�T�c��]�C�T�T�[�P�2�:�V�_�A�U�P�;�_�Y�I�,�K�K�9�I�a�i�U�M�Q�Z�M�]�W�D�J�~�Z�P�W�K�Z�M�e�h�I�4�X�L�J�P�t�_�T�g�n�N�j�@�Y�s�<�[�L�e�O�]�W�d�`�U�T�M�@�L�j�I�6�G�W�J�V�"�W�A�X�k�O�X�X�T�N�u�U�S�N�Y�O�Y��O�R�5�b�V�G�R�W�k�T�W�k�G�O�R�_�]�S�P�g�5�[�<�n�k�M�\�?�Y�b�Q�6�f�Z�H�Y�Z�I�Z�w�F�c�O�\�q�W�O�`�P�^�U�C�N�O�_�j�i�D�B�j�F�W�T�b�a�P�A�k�F�R�Z�c�@�Y�T�Z�I�O�U�\�Q�\�G�R�T�U�M�]�B�Z�Z�X�^�A�1�^���O�b�W�?�)�Z�W�c�f�K�S� �]�L�Q�N�j�f�C�S�X�p�]�U�d�O�8�R�t�Q�f��d�X�]�[�Z�Q�H�Z�S�F�U�Y�I�J�a�I�S�J�T�u�\�K�]�]�n�M�_�]�Y���K�P�W�b�S�^�r�I�X�>�Y�8�Z�R�A�W�A�T�R�Z�T�J�Z���K�]�X�D�^�G�Z�g�_�]�M�X�B�]�h�D���H�V�d�J�N���d�E�S�Q�^�T�P�*�K�X�S�P�k�]�;�M�`�W�^�_�V�I�D�F�t�I�t�U�D�P�Q�S�P�6�O�Y�C�P�J�H�`�F�T�f�V�X�X�C�C�T�f���J�J�R�F�Q�s�X�Q�V�)�f�Z�W�n�R�_�[�M�_�M�B�W�=�D�Y�D�_�^�X�Z��X�>�U�Q�P�X�P�m�Q�S�V�W�!�M�N�W�N�V�D�6�l�]�L�U�A�Q�Q�b�`�n�Y�Z�^�c�\�R�[�R�E�j�-�M�W�A�M�,�d�>�T�R�^�V�2�Y�h�`�?�l�J�k�Q�\�U�W�T�7�c�R�J�d�^�+�d�$�P�V�P�\�K�I�r�[�N�J���D�V�S�W�Y�F�!�J�M�=�K�^�O�V�Y�I�d�E�Y�L�R�?�w�H�h�Z�b�M�O�Y�h�P�_�K�W�X�T�7�n�m�V�X�X�>�Q�Z���e�:�f�?�U�P�`�[�W�c�S���^�[�L�Y�6�_�E�I�@�R�c�]�t�U�"�L�;�.�c�N�M�T�`�h�M�A�T�n�U�K�}�M�V�h�s�L�U�T�H�W�^�K�W�P�T�]�R�=�X�A�d���X�b�\�J�d�S�]�<�L�U�X�I�O�o�b�O�W�P�S�v�U�Z�m���`�J�G�L�`�U�Q�Z�n�A�_�Q�p�c�V�D�U�[�C�c�a�P�Y�Z�e�M�C�b�P�V�`�a�i�]�W�_�X�T�P�Y�L�]�Y�d�N�^�X�P�U�<�O�E�_�d�^�l�m�b�N�_�[�h�^�d�R�]�J�Z�b�|�M�`�]�_�V�I�]�Q�[�f�R�1�M�V�J�L�L�X�^�Z�P�q�N�e�J�[�E�J���G��M�S�P�O�Z�Q�p�^�L��\�\�U�U�P�M�S�[�O�b�`�S�E�N�d�V�P�[�W�?�^�o�U�E�T�D�Z�X�_�Z�b�a�Z�P�,�:�G�U�S���u�L�_�_�P�L�O�(�Q�`�O�(�e�_�N�I�V�U�a�*�O�D�g� �<�I�R�^�M�]�S�V�U�\�X�W���W�\�Z���P�R�g�Z�D�p�b�O�^�j�b�W�;�c�^�F�A�k�K�S��_�K�T�[�E�k�5�`�`�Y�S�9�U�K�2�V�R�9�J�X�c�W�N�>�(�`�N�R�^�O�d�W�W�K�H�P�r�S�R�M�q�W�]�l�X�c�N�P�s���b�T�Q�b�U�<�G�S�P�\�B�V�d�L�^�X�\�Z�M�[�q�j�U�m�e�?�W�X�^�V�\�`�a�W�T�=�b�G�U�N�`�L�J�e�Y�L�S�D�f�K�h�_�V�5�P�L�p�t�I�Q�6�O�Z�i�e�T�X�b�<�l�D�`�p�P�Q�C�R�f�K�:�J�d�f�m�\�S�K�1�8�u�\�9�V�w�D�Y�8�P�J�=�e�_���F�d�K�S�X�S�X�Q�T�G�q�\�X�[�[�4�V�h�A�T�j�a�`�S�P�X�L�J�_�N�L�W�a�W���c�v�Q�0�k�[�N�W�X�J�M���[��N�U�F�[�F�U�`�K�T�Q���A�9�a�K�N�Y�E�R�Y�[�V���3�R�_�i�Q�N�S�L�K�\�m�s�^�_�@�T�V�a�N�H�K�_�Y�o�~�C�X�^�R�Y�W�P�F�J�>�^�(�Z�X�c�\�E�S�a�Z�T�T�O���Z�a�R�V�X�F�Y�o�E�[�I�D���g�\�Z�;�W�t�U�C�h�_�Q�T�`�[�<�K�L�]�Y�J���T�X�Z�C�t�N�J�l�W�U�P�8�g�K�P�>�E�g�P�Z�s�T�^�S�W�W�M�R�Q�U�j�S�X�P�Y�W�]�O���Z�Z�Z�p�A�W�_�C�X�A�S���R�V�e�.�e�I�O���I�^�R�?�N�H�d�U�?�_�M�^�X�P�n�W�]�T�R�>�D�R���R�Y�Q�O�M�V�Z�E�M�P�f�b�]�R�/�f�W�K�Q�]�a�a�0�Y�^�F�[�[�U�g�T�M�I�u�/�b�T�G�P��T�a�y�F�R�F�j�v�l�Z�G�<�7�V�X�U�K�a�=�s�f�G�T�P�R�V�[�]�7�K�P�{�H�V�P�e�_�a�H�T�P�Z�S�0�j�Y�W�U�_�Q�=�@�V�Q�Z�`�|�J�d�]�^�I�P�T�[�W�`�X�O�>�u�F�i�L�M�K�Y�r�D�I�d���=�\�G�a�W�O�S�Q�A�c�a���G�X�A�_�R�;�Z�d� �1�]�L�V�b��0�L�P�[�R�W�[�l�K�X�f�%�[�Q�R�e�]�Y�V�L�G�m�X�Q�S�H�T�K�O�R�~�b�]�L�\�D�M�V�W�a�[�V�[�X�4�e�W�F�V���\�C�p�M�[�R�S�T�P�W�N�)�L�v�R�H�W�Z���O�Y�`�a�U�b�]�\�R�n�d�U�L�f�d�M�t�M�X�X�O�^�]�M�U�Z�H�D�I� �P�Y�R�Q�N�e�\�Y�X�Q�A�u�L�F�O�^�\�b�O�N�G�U�t�]�Q�Q�\�b�c�W�j�Y�`�N�U�K�W�S�M�W�N�>�W�G�K�^�Q�O�7�`�^�M���e�\�T�V�S�3�O�P���H�M�V�U�[�W�J�I�:�H�_�*�5�^�^�T�K�V�@�w�I�7�U�S�X�^�j�T�H�F�Y�O�7�M�c�M�J�N�N���U�`�O�B�!�M�I�Q�P�f�W�e�T�V�[�S�n�W�S�[�Y�\�Z�c�c�K�O�U�P�g�K�W�=�O�^�Z�^�Q�Y�W�Y�U�E�J�X�Z�[�V�>�D�8�`�T�S�R�F�V�;�T�W�D�V�B�\�Y�N�X�Y�C�Q�\�V�^�1�1�a�P�S�Y�8�W�N�X�X�T�S�_�^�D�O�M�M�V�8�S�n�Q�Q�g�C�N���1�Q�P�P�N�O�F�g�_�U�W�M�'�b�V�`�R�L�3�R�2�X�M�M�R�`�U�j�O�P�Q�+��Y�X�g�W�f�Y�T�Q�U�O�^�^��R�X�V�R�O�9�W�h�[�Y�n�o�i�Y�j�T�3�o�d�\�Y�Q�K�R�^�u�T�Y�U�V�S�S�D�F�X�Y�W�Y�Q�b�U�a�Y�S�i�S�X�T�G�H�c�+�d�K�\�^�m�O�[�[�K�m�W���K�]�H�g���l�O�B�Z�f�j�N�g�R�g�@�i�E�[�Z�_�U�>�@���L�d�Z�H�^�c�S�L�N�e�Y�J�u�I�\�]�I�q�T�[�^�K�j�c�N�_�b�h�f�W�S�a�N��^�F�v�Q�P�x�G�V�W�h�S�i�S�L�p���p�O�d�a�D�V�i�Y�Y�U�T� �Y�R�Y�X�[�X�P�I�;�e�:�k�B�t�Y�G�P�l�Q�L�v�U�F�C�n�U�n�j�Y�b�Q�K�V�u�^�W�R�V�Q�.�<�I�b�W�N�[�J�G�k�Q�b�I�X�S�H�X�\�\�T�b�Y�j�\�i�0�q�B�Z�S�K�D�X�[���e�T�P�`�f�Q�W�e�m�Q�@�\�S�Z��s�\�'�;�A�U�P�V�U�m�P�$�L�L�b�Y�S�G�c�Y�6�G�\�y�b�N�Y�Y�9�S�M�O�T�d�4�R�P�>�Z�]�p�I�S�M�F�X�N�S�,�C�V�m�[�T�o�H�V�T�h�c�Y� +�_�M�H�U�Z�_�8�B�\�S�Z��T�T�E�T�]�\�[�-�R�W�O�H���Y�N�z�^�X�P�_�N�P�r�_�"�e�X�N�_�b�[�T�J�m�c�U�q�W�Z�M�Q�\�]�g�_�5�T�_�[�J�O�J�]�N�I�N�V�S�m�[�L�Y�b�X�G�S�T�_�G�S�=�\�D�y�b�S�{�X�S�<�F�L�Q�H�`�V�E�`�Q�O�M�c�^�T�L�Y�f�J��W�b�Q�W�J�c�J�x�R�M�H�S�d�_�R�Y�Q�N�K�Y�W�I�d�4�W�V�$�X�x�b�@�[�_�d�R�F�x�Q�Y�?�]�C���t�l�I�9�S�a�>�b�L�[�T�K�G�B�C�Y�P�?�b�O���i�Z�J�Q�O�P�_�c�D�1�R�R�P�b�V�V�G�8�C�U�O�N�i�I�t�^�s�b�L�J�P�_�_�O�?�P�U�c���W�W�H�V�d�^�U�>�O�`���N�S�I�U�>�_�X�T�_�5�R�S�[�H�S�V�=�N�b�M�9�L�Q�Z�T�K�N�U�@�a�N�b�U�[�R�X�X�Q���D�\�M�U�\�I�g�Y�S��[�a�H�N�V�I�\�X�H�N�a�T�E�T�c�O�U�u�K�E�Q�G�E�\��R�V�6�X�Z�g�R�O�c�>�m�\�|�H�M�I�^�R�^�U�T�H�L�[�s�<�Q�[�T�K�Z�T�O�O�O�0�I�R�I�Z�J�f�T�d�R�V�L�[�8�[�Q���T�O�V�S�d�i�b�P�:�J�I�W�?�K�`�S�E�Q�\�\�d�W�N�G�Y�G�W�g�*�k�[�]�U�h�Q�M� �I�\�R�=�o�^�R�L�R�O�Q�e�W�S�G�b�e�r�M�S�[�}�_�U�O�q�M�d�1�M�V�K�v�O�d�K�Z�`�S�D�W�X�^�C�Y�X�R�[�_��[�K�U�a�9�^�I�E�]�Z�W�Y�:�E�N�`�W�U�g�O�Z�H�\�q�P�g�8�U�U�O�T�X�c�L�a�g�=�O�O�g�W�\�Y�E�L�O�]�G�d�;�+�A�R�^�O�R�X�T�\�U�U�1�@�q�S�T�?�O�]�\�t�>�[���V�V�5�L�6�A�X�O�N�Z�,� �T�_�n�_�3�W�R�E�\�2�R�L�J�S�,�R�n�Q�X�T�R�A�u�Y�R�Z��L�W�O�V�\�N�a�`�J�K�\�\�A�V�;�e�R�S�R�F�W�U�O�V���s�W�k�<�Q�T�M�V�T�@�_�r�g�K�8�`�^�I�K�\�i�>�w�R�d�K�1�P�O�z�Z�`�W�S�V�T�P�Y�H�J�?�e�Y�+�`�N�R�H�M�|�P�G�V�X�U�t�`�L�^�G�U�a�N�X�S�F�q�y�U�[�{�[�O�_�U�U�Y�=�Z�j�V�P�\�`�N�`�Q�S���X�N�L�R�`�M�d�K�=�:�@�c�Q�R�Y�\�P�Q�[�P�T�s�W�Y�A�W�p�J�`�`�^�K�K�W���h�S�X�Z�W�Z�\�?�a�R�Y�-�X�[�2�O�Z�d�[�h�U�R�I�S�]�B�^�Z�r�L�e�Y�]�e�S�G�U�V�K�W�g�N�[�g�7�e�R�I�M�X�_�R�`�Y�O�G�S�w�^�N���?�B���W�5�[�Q�6�V�G�C�X�P�G��[�W�P�R�C�_�\�[�`�b�V�S�w�P�n�P�I�h�T�h�`�J�M�H�N�Q�f�H�F�B�[�G�N�W�Z�Z�?���e�T�W�E�S�<�Y�T�c�]�F�4�r�L�q�Z�X�L�P�K�\�R�C�B�V�T�R�Q�`�^�P�8�Y�W�]�M�Q�V�U�B�M�M�R�V�y�U�T�W�5�X�k�j�K�r�S�G�T�K�W�N�~�^�Y�T�J�b�W�`�y�Z�[�Q�Q�B�Y�O�T�i�P�[�`�L�Q�V�4�T�O�R�V�a�W�W�M�h�Q�Y�O�B�<�Y�`�Z�L�f�I�i�U�y�U�K�T�l�D�U�Y�U�U�M�G�N�]�Q�c�F�N���P�_�_�F�O�a�R�W�C�J�X��W�Z�Q�M�{�T�G�O�e�g�Y� �R�n�P�R�\�Z�=�Z�\�P�M�g�U�C�M�X�o�Q�^�R�B�A�`�Y��W�?�L�O�_�K�V�I�`�m�Y�K���J�|�g�W�S�R�W�S�W�=�i�<�h�Y�X�9�S�W�T�Y�_�K�[�@�5�I�A�[�[�r�\�Q�Q�^�8�T�S�R�T�V�r�[�j�O�c�v�W�Y�9�e�\�a�O�L�\�K�N�a�[�D�P�W�r�:�d�^�[�]�O�O�R�O�I�N�E�b�[�;�V�K�V�X�M�D�T�Q�C�Y�Z�E�@�\�X�Z�W�d�U�[�P�@�U�V�K�h�a�Q�b�e�T�X��W�e�K�R�T�T�M�[�Z�P�G�S�t�V�K�Q�V�Y�L�=�Q�?�R�T�W�j��\�`�Q�j�V�Y�Q�W�T�n�[�b�X�b�\�[�T�U�b�M�N�u�R�T�d�^�W�R�N�F�G�X�V�d�Y�j�9�e�G�c�V�g�b�Z�J�`�V�W�S�,�h�]�,�a�W�V�K�X�[�S�]�+�Q�k�^�S�~�S�j�L�k�n�H�d�i�P�Y�N�X�R�b�F�E�\�W�V�m�G�<�Z�S�W�_�Q�W�G���Y�R�e�U�T�Y�:�Y�W�O�A�T�Z�G�K�\�V�Y�Q�c�Y�\�O�@�G�]�T�T�U�_�e�h�S�_�t�C�P�G���V�U�]�Y�[�T�e�9�@�l�T�A�X�X�O�[�=�9���_�^�`�Q�u�c�\�J�V�^�=�S�Y�\�c�T�X�L�7�H�P�U�T�c�W�k�P�W�Q�^�C�L�S�L�I�I�V�B�S�P�T�I�^�P�O�w�C�X�^�o�O�R�U�e�Z�.�~�W�O�R�@�]�S�Q�P�^�`�j�i�C�M�Q�U�X�S�<�Z�R�F�Q�Z�L�3�L�V�Q�;�V�8�P�Y�E�=�P���^�^�P�B�O�r�O�P�Q�4�T�_�M�f�C�d�P�N�P�G�W�U�`�V�'�Z�I�d�H�X�_�\�W�3�P�f�n�_�T�S�E�W�Q�p�M�`�P�`�L�U�\�O�U�P�[�L�P�p�C�P�Y� �X�V�W�D�b�a�E�Z�Z�e�R�T�Y�L�-�^�K�`�M�;�R�T�R�V�O�\�I�^�U�O�g�e�M�R�+�C�V�V�G�Z�o�m�>�@�Y�e�a�<�Y�T�I�O�r�Y�^�:�X�j�T��g�>�]�n�J�V�@�i�w�g�R�H�[���K�s�)�Y�Q�b�R�K�R�Z�S�T�P�X�y�]�W�a�S�T�I�Y�F�A�O�P�7�0�N�V�^�P�X�F�D�H�O�f���H�Z�T�M�Q�M�M�U�L�X�R�b��r�[�#�`�Z�P�U�S�[�Z�]�F�f�V�Y�n�^�Y�D�l�\�N�Q�S�t�Q�L�;�^�U�c�`�f�X�Q�M�\�c�]�V�e�i�U�X�h�X�W�V�B�.�X�V�O�n�h�@�`�I�R�A�Y�V�Y�Z�O�S�g�<�W�k�\�U�`�Y�5�O�.�_�L�Q�U�H�F�Z�Y�J�S�I�c�Z�I�n�X�N�\�g�N�N�d�^�T�2�U�S�T�X�l�L�N�T�t�^�W�N�<�M�V�T�U�D�o�H�a�P�C�U�V�a�K�Y�X�<�N�W�h�=�T�I�e�7�Q�D�N�x�D�M�L�P�^�x�Q�P�]�X�R�/�P�]�l�S�[�Q�I�e�U�_�U�X�L�q�T�V�M�J�O�g�a�O�X�-�e�G�X�[�e�J�^�S�_�Z�Z�a�_�b�W�X�K�j�T���Q�p�R�V�[�6�T�X�U�b�m�b�^�E�R�W�:�b�e�j�^�T�W�R���;�X�Q�Y�M�e�K�Y�W�S�S�C�E�h�M�c�C�]�Q�9�e�U�d�L�W�E�]�G�P�U�@�U�j�S�J�_�G�M�s�G�N�\�[�X�T�T�O�`�R�y�Q�Z�O�Q�W�_�Q�@�<�]�A�w�[�\�'�y�M�R�[�H�\�a�G���f�W�g�V�X�?�D�w�=�<�C�>�_�K�U�^�M�[�V�[�W�e�X�J��h�S�N�J�@�O�]�\�d�3�T�R���U�N�T�K�S�R�N�e�`�K�L�S�f�]�V�b�O�^�.�S�Q�1�T�W�I�[�T�^�r�U�Y�i�a�?�Y�X�_�P���t�Z�Y�R�b�^�6�N�T�9�R� �L�d�V�Z�N�+�Y�f�\�H�R�K�v�N���K�U�f�P�]�\�X�Z�B�%�G�W�\�X�j�R�n�4�L�N�?�X�z�O�M�H�Z�F�\�X�R�Z�K�U�A�d�S�R�W�Z�n�F���_�e�W�<�V�]�c�R�U�C�_�z�K�V�e�_�:�U�X�T�T�`�V�M�W�M�g�b���V�I�P�o�U�^�g�D�[�L�X�Q�L�+�[�I�:�H�T���L�X�m�c�t�a�c�[�`�R�9�`�-�P�U�J�1�K�Z�S�O�R�X�Z�8�N�h�[�W�S�]�K�?�W�`�L�S�b�o�e�c�J�B�8�D�9�S�K�Q�]�L���S�N�3�c�W�Z�L�Q�Z�K�S�N�M�<�]�C�u�X�[�X�V�I�W�Z�D�`�P�P�,�H�S�N�I�N�i�W�l�d�S�f�N�e�c�Y�R�Q�E�@�j�Q�H�N�V��O�B�S�b�0�Z�M�7�C�|�X�S�[�V�M�Z�T�Q�J�^�N�J�U�D�3�V�b�~�W�O�f�S�V�g�X�[�=�T�S�U�W�S�\�N�M�k�S�R�O�n�L�^�L�]�^�_�F�Z�T�~�C�T�U�S�=�X�T�R�O�E�X�_�>�O���G�2�c�d�Q�4�1�N�T�?�O�i�O�Y�N�C�R�a�K�W�b�^�A���Z�U�:�U�Y�M�F�C�U�R�c�V�U�N�Z�\�C�]�Z�T�U�K�R�M���h�H�c�Q�S�T�S�V�i�]�o�L�d�[�]�3�T�A�S�Q�Q�Z�l�]���F�Q�_�Q�[�X�X�_�]�Q�E�J�h�U�B�9�T�U�9�W�O�_�f�X�Q�Z�a�S�J�Q�I�N�O�M�D�S�M�P��a�S�n�P�_�]�K�J�`�Z�G�2�_�N�T�]�a�]�0�C�Y�U�O�U�"�b�I�f�d�^�X�M�Q�O�9�>�f��T�h�E�]�P�^�H�K�S�C�\�`�l�Q�Z�^�V�W�N�e�V�P�A�Y�a�_�P�J�m�d�f�U�W�n�I�J��b�^�U�c�1�X�e�<�Y�^�I��M�S�Y�D�R�7�e�Q�Y�P�d���R�R�o�J�9�Y�]�B�M�O�U�\�B�X�`�W�I�P�Z�Q�T�^�e�T���P�V�A�h�F�f�N�X�9�L�R�O�S�I�H�`�E�L�a�U�Q�=�S�Z�O�P�e�N�S�<�P�Y�[�\�G�H�6�P�3�C�Y�[�A�A�f�<�U�S�E�a�N�%�U�N�[�U�O�J�K�K�d�T�\�=�s�N�X�T�-�S�Q�`�0�r�T���V�V�O�Q�P�`�H�X�Y�H�Q�[�J�5�c�`�[�h�>�U�S�E�@�V�5�I�[�A�N�O�U�p�p�O�H�G�Z���W�i�q�@�Q�Z�N�O�W�B�U�C�>�J�g�K�k�_�X�U�T�j�P�W�]�J�O�^�\�M�P�9�J�T�^�R�|�^�o�b�T�<�T�[�M�\�?�K�O�E�X�S�&�V�K�^�Z�J�l�S�B�@�]�Y�H�T�k�]�R�`�W�W�U�L�O�Z�U�^�y�C�U�F�^�Q�X���b�U�b�Q�b�9�T�k�`�S�]�R�u�a�T�H�G�L�d�n�G�M�/�[�j�p�S�K�U�K�M�U�S�>�M�R�X�v�[�a�}�L�M�[�V�A�l�5�u�T�[�q�L�d�t�Z�Y�a�K�S�M�J�V�^�J�Z�A�O�Y�U�]�R�b�k�I�=�f�L�F�U�L�R�I�L�D�q�Z�\�&�T�P�x�S�U�P�K�V�I�N�N�R�R�u�S�O�l�T�_�J�b�[�R�Y�Q�O�Y�f�U�S�U�Z�]�U�Q�W�c�a�T�O�Y�^�b�A�Z�A�X�M�E�A�D�Q�s�6�p�V�V�U�W�U�>�X�T�Q�L�l�`�W�<�[�O�n�U�V���P�c�Q�R�R�S�N�O�P�I�?�s�V�H�R�O�S�b�^�I�Y�L�V�}�J�R�Q�U�9�b�L�Z�S�[�U�3�l�Y�]�T�\�J�Y�N�I�U�e�Y�}�K�X�D�S�`�J�U�=�Z�w�L�G�~�[�K�U�a�R�I�R�^�M�U�]���M�H�T�]�s�s�F�W�Q�K�S�l�M�n�_�P�N�N�Y�B�M�N�[�S�]�N�&�\�^�U�a�N�7�V�U�R�H�Q�K�h�E�R�^�]�R�I�W�D�D�X�m�Z�U�q�S�=�_�Y�F�Q�S�V�D�r�g�i�[�j�U�W�T�}�l�]�Y�L�|�q�h�a�Y�^�V�J�X�\�g�Y�z�T�_�k�K�T�a�f�b�c�I�W�Y���X�X�Q�9�e�e�C�J�Q�U�g�(�K�X�c�c�K�J�\�]�0�H�R�Q�P�S�U�[�3�N�I�L�b�j�[�H�E�C�9�U�g�R�N�\�K�?�Q�f�6�[�V�K�\�N�S�a�s�L�N�^�=�\�S�Z�Y�?�P�J�S�\�M�=�G�_�@�M�L�H�[�O�Y�J�[�J�U�t�M�P�C�Y�W�h�K�X�X�P�P�Q�^�`�W�W�J�D�Z�V�m�;�C�o�Q�V�Z�\�6�W�J�b�-�b�\�e�V�U���Q�M�e�c�*�?�K�]�X�S�i�2�G�R�l�J�T�G�j�r�\�S�?�[���T�U�W�\�_�^�U�X�T�W�A�S�Z�L�Z�R�]�W�N�R�R�T�S�=�E�Z�U�J�U�X�O�b�W�K�D�\�u�,�[�j�W�R�N�Y�`�'�Z�V�O�J�"�R�d�B�`�Z�A�7�g�]�E�L�\�]�Y�W�Y�h�J�M���^�Y�Q�J�c�=�T�W�f�x�`�M�E�R�[�Y�P�T�n�P�]�W�N�U�G�J�U�Y�N�Z�a�S�Z�D�`�F�^�L�V�L�d�m�B�W�u�X�V�N�]�d�O�O�>�H�I�@�h�Z�c�P�a�h�t�o�e�R�O�;�Q�]�Z���T�R�K�H�:�;�s�I�P�X�I�S�H�H�Q�Z�N�S�i�L�l�R�b�Y�Q�R�0�b�F�Z�O�O�A�Q�W�u�`�U�t�W�L�_�b�F���R�\�I�K�Q�I�@�[�V�G�P�Q�>�^�;�\�:�L�t�L�V�Q�Y�N�6�V�M�X�B�[�M�N�+�R�Y�^�W�f�=�X�d�8�]�E�e�b�W�[�O���z�b�[�Y�x�_�X�b�I�T�A�\�_�z�\�8�E�C�S�W�g�@�G�I��D�^�R�N�X�1�X�[�O�n�[��=�t�R�p�a�J�T�R�Q�]�^���R�X�t�c�W�W�C�W���N�U�Q�h�b�b�Q�]�Y�J�Z�O�\�H�M�]�p�S�?�9�Y�b�L�G�Y�N�\�c�Q�S�%�S�]�I�T�?�^�B�M�Q��M�<�J�7�]�i�_�K�a�V�H���L�l�U�G�J�V�V�J�`�G�I�H�W�N�i�f�R�@�Z�M�\�U�u�R�R�]�Z�\�W�S�W�L�r�P�Q�L�d�J�_�b�^�Z�V�M�l�c�P�`�N�\�`�{�V�V�I�`�R�E�S�i�F�Q�_�W�f�X�K�h�G�J�M�d�f�_�H�Z�,�E�Z�e�]�S�`�L�W�]�]�O�_���a�I�P�Z�[�M�Q�i�N�O�X�2�e�O�a�F�;�T�R�a�G�m�h���S�M�S�Z�o�^�e�P�c�c�c�q�M�T�V�=�R�`�[�f�Y�W�Y�M�c�\�f�G�P�G�W�l�p�N�S�?�B�U�`�Y�Q�1�U�U�L�b�R�[�?���S�c�E�E�Z�L�Y�J�J�L�O�r�V�r�`�O�I�L�R�L�Y�W�^�1�V�\�n�^�W�^�9�Y�H�T�S�p�J�O�b�L�X�Y�S�I�R�X�B�D�P�U�Q�3�J�X�O�M�O�X�R�Z�U�/�L�N�O�U�f�d�^�D�Y�q�]�i�M�8�\�i�X�P�W�K�o�]�e�>�c�`�D�[�=�H�V�j�S�_�I�^�l�W��[�^�\�4�R�Z�L�8�K�M�<�P�%�X�1�F�U�l�q�N�Q�K�L�p�W�;�M�\�X�Q�\�h�[�`�8�T�i�H�X�g�_�V�]�\�X�_�L�e�N�G�h�Q�S�k�P�V�T�Z�M�a�Z�l�U�Q�P�U�W�Z�d�8�P�[�X�,�Z�K�X�e�K�B�U�F�X�Y�b���a�\�V�j�a�R�E�~�>�a�T�N�]�N�f�t�Z�W�L�Y�i�n�Z�_�/�i�d�>�_�]�b�^�Y�Y�O�s�q�<�G�I�n�s�R�L�Z�b�Z�K�k�?�Y�b�E�P�_�A�Z�V�I�L�X�r�L�X�Q�;�R�T�O�T�V�Q�U�\�I�^�u�e�b�@�X�^�:�V�d�=�T�X��a�d�Z�\�Q�H�Y�O�O�i�N�t�R�>�_�Z�D�\�U�K�Y�G�Y�X���R�S�`�Z�U�R�Z�A�Y�F�U�c�g�e�g�X�J�m�N�O�U�V�Z�n��Z�S�W�]�e�U�H�V�r�[�m�H��Y�I�I�S�U�c�Q�\�`�P�R�!�_�\�I�W�m�L�]�Z�\�T�W�L�`�R�_�]�P�K�Q�p�G�Y�H�y�C�T�Z�L�O�Y�Y�Q�e�T�b�S�[�Z�Y�J�M�X�]�f�R�G�@�^�s�Y�^�V�Z�*�P�N�]�f�R�J�T�q�H�&�\�S�Y�Z�_�b�H�T�J�M�U�T�4�o�U�S�/�Z�M�l�c�`�6�R�3�d�H�S�V�V�R�S�H�b�Y�m��n�W�K�R�S�`�s�U�X�X�=���/�U�N�`�`�`�T�F�V�m��W�S�Z�T�a�[�U�H�W�;�O�o�a�k�e�E�M�i�Y�X�]�@�N�Y�m�S�L�D�J�R�Z�e�H�C�h�P�Q�Z�z�T�G�_�P�W�U�f�j�N�\�K�b�T�D�X�R�V�V�T�S�D�J�G�U���N�U�T�T�;�h�[�Z�Y�T�G�W�A�P�P�U�z�Y�R�c�d�M�\�P�U�J�K�^�[�z�]�E�_�c�W�L�o�V�Q�\�@�a�F�_�W�h�k�H���l�N�b�X�\�O�T�L�V�G�U�S�:�d�;�H�`�R�v�P���R�O�H���K�H�Z�L�J�R�B�c�P�[�T�Q�X�Y�K�Z�W�j�a�T�K�j�Q�I�H�T�\�A�T�[�X�a�]�U�m�F�N�O�g�e�U�=�_�x�U�P�]�Z�X�X�R�;�\�]�?�W�:�N�;�]�N�6�;���y�D�E�Y�[�_�i�N�Z�I�S�R�5�f�T�V�h�I�R�c�q�x�[�D�:�U�C�M�J�N�]�`�@�H�F�Y�@�9�T�j�g�O�t�N�F�M�Y�Y�X���[�f�^���R�_�b�]�P�Y�O�6�j�F�K���V�^�6�[�S�X�e�P�D�R�Z�O�T�K�T�Z�V�Q�M�?�t�L�\�R�T�S�g�V�>�D�K�X�m�O�A�[�W�b�T�L�?�P�U�R�-�Z�\�K�O�_���S�X�J�]�N�f���>�w�P�^�T�L�U�m�I�>�T�9�N�F�n�[�S�L�S�f�Q�N�j�D���W�S�Q�Y�T�J�]�R�P�E�5���Y�M�D�^�j�[�S�h�L�\�[�U�[�i�7�C�f�7�>�J�7�Z�S�N�\�^�;�`�R�B�H�H�^�L�T�E�t�I�?�`�Q�O�i�Z�G�V�V�[�K�H�U���J�M�y�Z�R�@�T�N�4�I�R�_�`�^�U�V�L�M�U�K�J�W�X�_���3�P�S�>�b�R�P�W�r�W�M�L�F�g�K�Y�U�@�T�a�Y�K�k�j���P�:�!�_�R�g�b�L�I�Q�e�{�Y�a�G�U�Z�f�n�P�R�V�g�)�z�N�[�J�T�S�R�^���F�I�[�C�b�k�b�^�F�N�V�Q�e�L�S�^�K�\�W�N�;�V�S�P�c�m�X�?�x�P�Z�N�B�U�a�L�f�Z�L�\�W�c�V�N�^�b�N�L�Z�Q�h�O�&�M�b�;�Y�Y�P�S�Z�T�]�S�O�`�R�f�S�O�X�#�V�R�O�k�W�O�R�l�T�X�R�b�]�W�R�T�`�p�`�T�Z�T�Z�W�[�M�E�H�S�\�\�T�I�K�Z�\�R�5�V�Y�a�?�W�P�y�B�:�Z�S�Y�?�[�G�V�K�X�\���U�f�f�d�T�\�Y�I�J�J�V�E�Y�M�Z�_�>�S�K�_�_�M�S�G�6�>�\�d�Q�S�P�X�F�d�A�Z�!�V�U�H�h�X�Q�T�i�e�V�R�[�T�O�f�U�_�S�A�Z�T�g�T�=�K�U�E�O�]�W�R�Y�a�O�I�9���P�c�E�E�q�[�W�n�f�P�M�Y�Q�P�M�a�P�:�e�^�V���L�T�P�R�d�W�D�W�G�W�D�Q�v�T�|�L�e�k�I�<�N�]�R�F�S�T�`�e�W�W�X�S�q�c�x�V�Y�`�_�2�J�P�p�U�X�@�S�e�e�C�g�q�Z�k�T�i�f�N�s�T�E���T�J�\�[�F�^�O�`�Q�R�Z�_�J�A�L�}�z�a�T�T�U�T�[�a�Q�V�J�N�d�_�b�T�h�T�`�T�u�M�^�K�V�!�2�A�M�G�P�\�N�Z�V�[�X�T�i�G�U�Y�k�?�L�Y�O�;�7�S���K�U�K�\�V�Z�S�R�b�\�^�@�b�V�M�]�_�]�I�`�O�F�Q�V�A�A�_�B�a�]�c�P�e�>�Z�`���U�H�^�c�Y�_�O�Q�9�j�R���g�_�_�[�_�j�[�R�f�A�R�^�[�H�t�o�G�X�s�R�X�t�?�Q�$�_�b�l�U�\�J�>�Z�J��P�L�R�_�C�l�U�O�Y�i�Y�O�C�]�O�M�N�W�B�P�P�e�S�V�@�^�>�I�T�k�F�N�Y�F�M�'�^�S�T�N�B�v�U�Q�`�j�M�W�Z�a�W�_�F��S�M�@�Z�N�W�X�a�;�S�M�m�b�Q�X�S�G�e�Z�[�_�U�P�O�v�P�\�N�2�\�S�P�j�A�q�U�Q�_�X�Z�b�W�<�_�X�U�d�g�Q�7�S�V�T�S�U�N�h�W�c�R�M�P�e�Y�W�Q�l�R�g�M�3�\�N�B�8�h�S�c�C�_�O�J�T�\�7�R�Y�>�L�e�n�^�n�T�X�s�>�O�e�R�T�W�P�S�S�b�V�l���M�^�P�J�O�H�8�H�W�I�u�V�]�_�A��l�D�\�\�L�T�W�^�S�O�S�U�L�2�P�a�;�J�Q�[�C�^�d���P�P���W�Y�^�o�5�7�T�V�d�c�Q�R�g�D�V�N�i�O�`�f�W�[�E��T�5�N�o�T�:�J�2�J�^�G�V�V�R���?�U�Q�`�]�n�]�X�K�l�V�R�I�R�N�b�n�_�n�Q�L�a�I�[�f�X�U�Y�^�D�a�V�U�Y�p�q�Z�O�X�a�!�P�a�\�H�O�}�P�O�[�n�g�[�i�^�r�Y�]�C�h�^�e�S�N�U�J�A�L�a�P�Q��^�[�K�X�i�W�h�F�X�p�V�X�U�c�R�Z�g�M�O�R�O�h�b�L�4�V�_�>�e�e�[�\�S�V�e�g���U�C�a�q�X�]�T�g�B�a�L�#�Z�`�R�D�e�Y�a�O�h�]�Q�X�J���T�T�X�v�^�[�U�J�C�V���Q�0�]�S�U�\�M�^�i�M�^�?�8�Y�6�U�J�Q�S�b�J�Q�N�\�c�X�k�K�V�`�R�e�_�]�K�G�E�N�^�K�U�N�O�I�F�X�s�N�\�/�N�V�_�L�r�e�_�f�T�M�T�{�k���T�U�s�Z�Y�Q�R�H�<�?�P�^�l�T�Z�X�T�S�R�<�R�X�A�N�-�O�j�=�^�W�N�D�T�F�T�e�E�P�X�Y�d�Y�b�g�����j�w�O��U�T�]�[���g�Y�S�M�n�L�Y�r�B�N�Y�_�D�_�M�f�S�j�9�!�Q�c�_�G�/�X�P�R�Y�Q�^���L�N�[�[�^�M�T�b�T�i�i�9�R�_�_�_�]�G�M�[�[�T�P�Z�|�6�]�D�T�h��Q�Q�H�D�V�P�?�^�a�C�_�@�G�`�I�I�q�_�e�9�b�Y�Y�Y�c�_�W�`�N�^�^�`�O�]�&�S�U�W�Y�R�]�K�D�`�T�X�`�O�G�S�6�P�X�G�R�I�X��L�U�Q�j�N�O�e�K�X�D�S�B�H�G�F�G�@�\�v�/�Q�I�K�X�O�d�W�P�G�\�X�`�^�Q�L�r�����N�j�W�U�V�Q�i�S�\�_�S�h�K�l�2�N�@�_�P�=�V�\�i�S�X�]�M�X�g�m�]�d���I���9�]�x�[�j�b�c�[�_�I�F�X�Q��B�l�f�n�.�X�a�V�W�c�D�=�E�O�l�U�\�b�g�Y�Q�H���D�[�_�Z�U�\�Y�S�L�d�a�v�m�Z�[�\�`�J�Z�W�P�^�A�N�Z�Q�Q�H�P�Q�^�t�_�U�L�L�\���^�5�G�Z�Z�c�X�>�S�D�T�L�[�U�P�W�T�W�]�W�H�Q�^�K�y�f�V�T�N�S�b�K�T�Y�T�r�5�h�P�P�P�f�H�O�i�[�O�:�c�K�T�O�i�"�O�b�S�X�Y�I�R�U�5�^�Z�]�[�^�Z�Y�/�[�T�X�\�a�i�Z�]�:�S�M�R�P�`�Z�_�I�"�9�\�t�U�M�F�[�`�V�Y�I�`�\�W�N�M�V�T�j�]�e�\�J�S�L�X�V�3�_�d�k���g���Y�u�R�]�[�L�x�U�Z�Z�X�[�V�\�N�7�U�T�R�T�^�U�N�C�=�K�\�N�N�Q�G�V�Y�O�K�F�L�N�U�]�m�W�d�S�f�g�L�N�f�Z�O�O���V�f�O�Y�A�@�[�a�g�b�h��A�F�_�Y�~�K�S�Z�S�W�W�H�J�Q�N���S�^�Z�S�E�G�F�T��X�\�_�O�K�R�Y�T�b�R�L�d�8�`�W�A�R�P�^�J�K�`�Z�`��G�Z�Q�S�[�_�]�`�B�P�9�D�Y�Z�#�S�S�Y�V�L�O�5�X�]�0�P�U�X�O�X�j�^�W�R�U�M�T�T�j�^�g�Y�U�X�c�X�Y�G�C�S�y�^�r�L�U�]���b�L�I�q�Z�a�9�]�N�B�Z�M�f�Y�Q�R�_�G�R�/�`�W���^�e��t�����T�p�0�S�T�x�f�U�P�!�[�Z�l�]�Z�J�a�l�R�E�D�U�S�\�i�W�e�c�S�S�V�e�X�L�G�Z�A�P�O��P�\�s�Z�R�P�]�U�M�Y�Z�S�r�Z�]�L�V�\�R�d�a�u�o�P�@�I�R�W�a�T�[�[�E�\�T�]�p�g�N�O�W�f�S�V�e�Q�Z�?�N�X�i�[�Z�Q�f�W�]�F�@�I�1�u�S�S�d�M�Q�u�S�^�N�I�Q���[�7�Z�`�Z�f�P�L�?�P�Z�D�]�`�V�Z�f�\�Q�J�z�O�Z�a�C�j�Z�R�T�f�`�5�U�W�N�X�T�W�8�d�Z�U�>�r�>�n�R�M�S�^�G�/�Q�U�B�O�^�R�7�r�S�Z�[�W�H�[�D�J�N�[�c�g�Y�S�c�T�&�<�i�]�a�n�����]�t�^�_�Q�^�W�Y�C�R�g�e�H�<�P�_�L�&�V�j�P�H�Q�_�J�G�t�7�g�_�J�U�:�^�Y�R�\�a�a�=�J�k�_�O�O�h�V�8�X�P�;�^�O�[���\�f�H�l�X�`�^�R�<�X�W���W�m�K�]�c�_�[�T�R�7�]���T�d�Z�C�_�_�P�R�\�`�v�F�2�N�K�d�l�L�\�s�J�N�_�*�L�A�O�W�_�S�R�Z�T�X�V�T�_�W�T�T�[�L�u�R�k�,�]�]�V�Y�=�R�h�R�U�F�S�e�Y�M�Q�T�b�B�z�Q�X�W�V�\�S�J�I�E�r�J� �P�P�\�+�v�R�G�l�c�B�<�\�Z�W�M�\�Y�`�\�I�H�F�U�X�h�\�R�\�^�P�v�s�R�L�@�O�^�E�P�_�Z�i����[���k�a�k�U�Z�I�e�X�O�U�b�:�[�R�S�]�@�R�X�G�r�Z�T�^�G�\�:�Z���Q�_���W�Q�e�I�^�W�_�J��_�F�R�[�`�\�<�V�Z�b�K����S�}�L�W�N�;�M�(�g�f�i�F�Y�I�R�O�h�W�6�k�\�H�H�f�A�N�r�`�M�W�S�R�`�:�E�F�?�c�W�>�e�c�M�_�Q�\�[�O���N�G�^�p�Y�Y�X�K�\�W�P�I�[�H�G�U�F�U�k�s�T�P�M�J�U�X��S�l�U�\�Q�O�]�J�D�T�A�B�Q�N�G�V�K�V�N�p�a�L�^�M�V�[�R�/�r�V�N�T�W�L�N�{�l�B�I�c�^�W�R�=�r�[�v�X�S�R�`�j�b�S�7�M�l�T�f�T�X�&�}�W�X�f���������y�v�h�^�\�E�[�`�b�P�S�S�W�L�_�c���t�Z�`�N�M�T�9�P�O�\�E�J�c�U�Z�Q�V�R�7�q�Z�Z�G�L�b�3�Q�L�[�[�a�&�L�Z�^�T�[�G�T�R�W�I�]�[�\�=�G�F���R�-�Q�X�e�M�_�[�e�J�_�_�W�j�E�a�B�\�_�L�V�R�j�h�2�X�p�O�X�:�c�Q�T�[�R�b��L�L�T�i�O�\�R�a�d�E�[�?�f�[�T�K�Z�Z�d�P�Z�I�v�\�]�_�/�f�g�N�I�>�T�R�e�z�A�[�I�k�P�W�P�~�<�D�K�K�i�Q�M�Y�W�@�O�h�Y�M�L�_�G�]�P�a�U�O�`�R�I�Q�b�P�U�A�S�5�c�V�G�V�=�U�\�Z�Z�]�P�<�V�R�Z�V�m���������p�g�V�V�r�Y�M�R�V�F�V�R�H�<�B�Z�]�Y�Q�V�H�]�O�L�T�K�Q�o�4�S�T�R�Q�J�V�\�=�J�h�S�L�Y�]�`�D�K�Y�W�V�R�C�R�K���<�e�P�[�R�c�K�K�Q�^�)�e�V�=�`�S�n�3�b�K�V�E�O�T�O�]�P���W�T�V�]�G�f�?�=���D�M�[�W�r�N�_�Z�N�<�S�g�R�Y�L�\�H�S�a�m�M�F�k�U�*�3�o�a�N�F�R�s�o�\�@�Q�Q�\�^�Q�u�Y�[�N�T�O�T�\�]�T�n��C�Z�a�S�P�[�]�T�J�R�X�E�U�i���_�M�W�[�/�L�Y�T�H�]�[�R�P�[�W�V�V���_�X�=�s�K�U�W�y�b�X�T�U�q�c�R�p�`�q�y���������������f�x�u�X�_�[�b�V�=�T�Z�`�P�^�U�t�_�a�Y�S�4�a�P�f�C�U�;�m�N�Y�Y�L�h�V�R�R�C�Q�C��Z�E�S�u�N�R�l�f�9�d�V�e�^�M�R�T�1�P�w�U�;�G�[�]�v�\�d�T�Z�D�b�O�U�d�D�^��4�[�L�S�V�p�M�S�V�T�X�r�o�g�P�a�Y�a�[�b�N�Y�N�Y�%�R�]�M�S�U�]�]�Z�O�Q�n���P�S�N�R�Y�O�P�\�*�Q�P�V�P�_�b�o�j�e�c�b�R�b�L�J�>�S�8�U�X�K�C�Y�V�O�^�L�U�a�E�[�4�x�Y�5�R�R�S�Y�V�U�U�v���Z�Y�^�b�Q�W�K�Z�R�F�Q�9�P�u�V�[�r�^�U�L�s�Y�u�q�f�d�i���������i�d�n�_�O�h�Q�_�0�L�O�f�W�F�R�d�G���d�=�V�\�b�@�T�_�g�R�E�Z�h�R�S�T�L�[�}�;�c�\�\�`�<�[�T�O�_�^�\�X�]�N�[�X�8�L�W�b�L�W�c�V�Q�F�U�U�<�j�X�V�V�\�e�B�O�l�O�P���E�R�D�N�Q�S�R�O�a�K�\�z�J�Y�d�S�p�]�F�N�<�K�W�N�D�q�Z�V�A�o�c�S�N�T�j�V�U�{�R�U�]�U�I�U�H�m�_�a�>�W�T�W�K�K�0�P�G�W�O�S�%�h�Q�]�N�R�Z�^�U�_�_�U�O�T�T�J���v�M�U�[�P�h��e�V�e�U�\�M�[�\�R�X�U�M�G�H�\�_�c� �]�Y�X�S�O�q�d�@�U�b�X�T�@�]�S�~�����킸���W�|�s�|�]�i�`�`�R�G�T�X�V�L�J�r�n�g�Y�m�>�C�[�R�Q�Z�]�k���R�Q�i�R�W�O�P�U�X�C�b���O�`�J�/�L�\�[�W�Z�I�3���G�\�S�K�M�f�D�^�W�X�E�R�Y�]�]�N�S�M�Y�V�r�Q�H�l�W�S�d�h�a�W���O�N�X�R�^�D�N�d�S�Z�K�N�f�n�b�X�g�E����T�Q�j�2�E�]�U�]�V�?���c�^�G�>�=�V�P�_�>�E�K�J�[�Q���S�U�e�W�?�X�W�i�U�`�;��V�Y�6�R�Z�k�b�E�M�d�K��g�K�L�h�J�M�C�Z�b�h�U�X���@�L�n�G�]���P�c�J�E�d���$�_�K�_�E�V�N�C�b�_�u�Y�q�v�p�����������j�e�l�b��^�W�S�R�d�Y�R�o�P�N�X�Y�n�^�Z�6�S�]�M�N�_�D�X�7��G�Y�W�V�W�Z�M�y�R�U�8�_�a�a�F�2�J�j�i�_�m�K�a�`�E�F�i�W�\�[�I�Y�X�]�X�]�f�`�Y�K�O�0�`�Z�Z�>�_�U�(�K�`�5�Y�N�R�c�C�S�O�U�T�I�J�^�G�W�Y�S�E�\�U�O�_�s�M�Z�U�]�[�R�O�]�P�S�w�W���R�N�T�j�d�Z�L�8�q�'�R�[�H�L�o�T�C�W�}�a�V�c�l�`�Z�V�g�L�K�W���U�X�[�L�L�b�T�`�@�b�W�L�M�X�N�e�1�I�f�K�q�T�X�g���S�K�Z�Q�U�X�O�P�_�q�O�a�X�a�X�c�^�k�Y�a�t�����F�)�߂������j�i�[�2�l�l�e�H�A�W�g�[�\�R�H�?�I�Z���e�P�x�U�_�S�_�Y�g�H�U�J�R�k�[�W�N�N�]�b�R�c�J�^�~�G�;�T�[�W�e�J�`��S�l�Z�w�R�^�\�@�N�T�X���D�g�S�_�m�U�C�a�E�Y�U�\�q�g�V�P�p�H�X�D�S�J�L�P�/�V�D�O�]�U�Y�T�D�Y�B�]�K�e�X�O�d�c�O�b�T�_�X�P�<�(�&�T�S�a�W�C�Z�M�5�3�W�\�2�@�r�R�T�=�p�A�\�U�U�S�C�M�V�^�U�^�m�S�V�X�I�U�V�I�r�C�R�Y�T�b�b�i�N�O�S�a�E�i�g�Q�A�^�e�Z�Q�}�O�N�l�)�r�[�J�Q�N�j�Z�X�P�[�M�\�m�`���䂹�ڂĂ��x�i�U�i�S�[�I�l�U�h�Y�s�N�X�h�}�W�_�K�G�_�R�i�X�T�U�Z�S�O�g�H�b�C�S�C�[�S�\�N�6�z�r�P�>�c�H�\�R�e�Z�W�[�Y���c�T�l�_�n�O�W�@�O�P�R�L�f�[�a�H�W�c�V�I�Q�X�T�U�D�[�]�R�U�X�M�R�Z�t�J�]�L�j�I�Z�p�Z�>�V�Z�W�M�[�b���J�Z�a�I�f�m�U�@�X�U�_�Q��Z�T�=�4�^�O�e�T�d�P�D�Z�c��\�M�[�1�e�S�_�R�Y�)�X�9�E�P�V�@�n�Y�U�T�B�`�d�T�[�P�Y�E�G�[�X�T�a�W�R�[��T�Q�C�b�G�1�[�f�D�P�c�Q�a�M�K�e�G�2���c�\�^�Z�k��׃�d���3����������d�f�^�N�e�f�S�H�h�U�S�V�L�h���N�B�]�S�]�O�o�c�F�^�j�L�P�Q�Z�d�f�a�Y�I�R�W�O�X�=�4�b�`�_�H�O�]�W�W�_�U�U�o�Q�R�i�h�O�N�K�N�i�e���S�A�Z�\�T�P�E�b�e�C�T�`�O�L�r�H�V�T�Z�V�`�Q�:�\�+�_�S�q�X�Z�B�M�I�Q�V�U�X�m�P�T�]�e�5�^�Z�R�R�\�X�~�K�Z�X�^�>�`�`�W�I�P�Q�=�P�j�A�e��:�^�l�]�P�T�a�\�^�`�X�F�]�P�_�S�S�1�W�V�W�-�V�U�\�N�\�\�R�S�E�T�U�N�f�W�s�O�S�U�Z�=�^�p�S�U���Z�[�d�r�R�q�N�c�\�m�����΃��5��������t�x�E�p�7�k�w�h�i�P�b�T�k�q�H�t�R���N�;�j�V�K�Y�I�?�k�`�[�a�\�M�Q�W�V�[�Q�O�U�W�[�V�n�U�[�a�Z�Z�X�_�T�T�Q�9�N�[�>�a�N�N�d�m�\�F���,�L�V�H�M�X�.�W�[�]�U�M�Y�R�P�B��X�>�K�B�P�X�S�b���T�N�K�W�\�P�h�l�c�i�T�8�L�g�N�V�I�W�E�Y�Z�B�@�L���m�M�]�[�R�E�d�M�V�K�X�d�b�A���i�\�^�H�V�V�G�P�e�O�]�k�I�A�L�E�u�W�>�Q�a�l�]�G�c�Z�h�a�_�U�1�S�U�F�R�Q�;�r�i�X�G�R�R�U�]�J�P�P�)�[�b�Z�d�����l�Z�Y�p�����ŃV�����ރ��΂ق������������l�n�]�j�U�f�f�_�?�O�r���Z�`�^�P�S�c�O�[�D�J�\��S�h�T�T�8�R�R�n�X�_�e�E�E�Y�T�w�X�c�O�Z�N�_�`�R�K�R�j�Q�c�@�U�L�e�^�H�g�3�W�C�K�s�]�D�(�\�U�Y�^�y�X�[�P�d�L�]�d�j�G�^�a�P�|�]�Z�a�J�k�W�C�p�Q�M�e���W�l�Z�c�t�X�P�]�m�l�V�H�Y�D�A�K�H�<�U�_�n�R�M�Y�d�U�S�S�W�V�S�R�^�O�]�E�[�Y�y�S�Q�[�O�T�S�O�Q���E�\�^�I�V�a�K�E�\�c�k�V�=�K�W���Y�L�W�X�R�R�`�v�Z�^�L�v�c�l�m�h�f�f���f�S�x�����;�Q�Մ �M�3��؂��x�w�B�c���f�b�a���x���p���\�9�^�X�N�Y�_�T�1�]�W�P�Y�_�\�f�d�T�W�Z�{�]�I�R�M�E�<�j�K�W�4�Q�V�M�Y�S�\�B�X�L�+�S�]�_�V�Q�C�l�G�]�K�S�f�R�N�a�[�b�T�I�X�H�Y�]�]�U�I�Z���\�T�R�M�b�U�V�f�w�h�9�^�\�[�P�L�\�S�a�C�G���S�Z�P�J�n�_�X�R�S�Z�R�o�e�g�_�r�O�]�^�I�H�H�f�H�Q�Q�?�P�P���[�e�G�W�W�O�R�N�W�P�d�Z�S�Z�P�X�C�I�V�Y�"�W�K�B�N�K�X�1�E�M�^�^�W���M�R�c�f�X�[�d�&�R�U�Q�?�]�T�������[���������섨���΄l���,�ЂȂu�k���e�e�i�y���e�u�R�e�M�`��X�G�J�U�b�`�P�R�_���I�\�]�C�K�R�Y�F�S�V�C�a�j�S�V���`�U�T�V�c�o�K�T�c�]�T���\�a�?�T�C�=�Y�g�X�m�Y�;�K�Q�d�Q�P�E�N�>�r�N�M�N�m�L�D�R�[�a�;�C�W�Y�R�E�Q���`�Q�[�Q�l�e�W�a�[�`�[�I�e�h�Z�W�*�M�R�L�X�S�Z�w���S�S�N�Y�S�e�g�3�2�V�S�`�e���O�U�`�c�Q�a�Q�R�W�n�]���`�J�[�D�U�`�k�X�c�V�O�>�R�S�V�Z�\�P�`�J�;�J�Y�V�-�Q�d�U�Y�T�D�S�Q�`�Z�`�Y���7�j�����m���������A�2�<�G��y��V�n�႔�k���t���g�z���}�v�z�{�����p�_�g���M�e�S�c�P�L�N�P�q�W�\�D�L�J�c�b�I�S�a�b�o�i�Q�a�V�b�V�Z�M�C�G�y�\�[�l�Y�;�n�l�O�P�d�[�U�W�a�I�R�G�\�W�W�[�c�X�U�U�P�_�U�W�[�Y�v�d�N�W�[�V�O�\�`�l�^�D�Z�P�^�K���Z�P�I�[�Q�<�]�e�Z�_�V�S�a�Y�^�q�Q�K�P�U�K�X�X�V�O�M�I�X�a�\�K�]�J�L�p�j�i�Y�K�U�X�M�q�R�O�;�d�W�^�_�P�L�v�T�m�\�S���`�Z�K�\�m�k�c�H�X�]�M�x�P�4�M�c�\�q�d�o�Q�d�_�r�ÂV���‚��������݃������"��̉T�ӄă��傳���~���e�����{�z�g�V�s�}����g�X�J�m�H�O�H�[�d�[�Y�@�8�`�5�P�E�u�i�W�d�W�8�L�d�K�U�U�i�3�Q�U���Q�V�a�T�.���_�m�[�J�\�j�V�T�e�\�@���[�P�X�_�G�S�]�F�F�b�R�d�9�O�U�^�V�C�Q�K�H�W�T�V�o�P�:�U�L�L�F�U�U�`�P�E�W�X�\�V�R�N�u�<�f�W�O�I�`�>�Z�]�s�n�X�`�P�K�Z�[�G�f�Q�U�J�X�g�;�U�_�T�S�]�b�Y�]��X�T�X�K�`�N�Y�\�O�1�S�C�b�V�C�T�]�c�D�S�b�L�G�Q�T�H�c�Z�P�f�r�R�Z���n�t�=�u�~�������Ƃ����+��N�W�ƒ�N���0�p���O����ÂЂ����������g�����f�o�q�j���W�S�A�p�I�F�[�]�=�W�S�3�a�;�`�A�[�_�^�V�s�S�Y��V�M�c�[�C�P�P�[�d�f�^�?�o�P�P�D�T�K�]�e�Z�O�H�a�L�S�R�b�]�C�T�N�Z�E�\�`��D�T�\��M�M�\�M�]�`�Z�O�?�e�V�T�W�W�R�R�]�X�m�N�m�I�\�V�P�R�C�W�W�U�_�O�N�p�|�X�S�F�]���U�P�Y�k�Q�<�Q�G�q�S�H�F�W�@�X�d�Y�T�S�w�U�t�I�T�Q�M�T�]�j�C�X�\�R�Q�O�i���d�]�Z�I�T�L�\���R�r�M�E�X�U�`�u��������� ���׃1�0���셽���T�Q�i�v���������V����X�\��,�,�Ӄ����ǂ��������\�d�]�r�S�:�P�P�p�>�d�K�U�@�E�T�[�P�\�u�Q�q�W�B�J�I�O�P�Q�Q�\�S�T�e�[�X�V�c�O�T�l�d�Z�R�\�N�`�R�a�f���Z�9�6�^�?�P�P�i�G�L�U�a�;�V�b�F�L�X�M�J�_�l�u�\���A�P�]�N�[�Y�h�`�I�R�g�J�p�I�b�W�S��[�M�X�[�h�[�1�e�M�N�V�a�W�,�D�_�x�4�M�c�Q�O�`�Y�J�I�a�T�X�]�`�d�M�O�N�[�f�V�X�\�M�E�=�W�Y�D�]�U�W�S�7�_�[�Y�>�\�N�L���D�V�2�]�O�k�i��������,�P�)�%�y�����w����Զ2��������M�\� ����������s���T��Ղǃ �Ԃ��|�����o�S�X�a�N�X�R�Y�U�7�a�Z�`���I�]�f�S�M�S�O�X�i�X�Y�6�e�W���f�S�H�V�l�T�H�_��?�B�?�E�]�^�]�r�P�N�3�1�Q�D�J�l�Q�Z�T�<�k�d�Y�M�f�a�\�p�T�k�H�[�U�m�h�r�\�P�V�@�Y�P�]�Y�\�X�b�S�]� �Z�c�\�V�\�F�Z�L�Q�d�J�+�U�e�[�N�=�T�S�K�q�Y�_�Z�k�R�^�K�d�T�q�J�a�S�D�N�b�Z�I�M�Q�M�U�X�Q�a�7�X�A�W�_�K�W�l�Q�U�`�8�R�^�Q�F�T�<�M�X�X�h�(�h������ �E�m���Є'�����@��и�����ǿ���6����j�g�������Ńۃb���ڂ��������i�]�t�_�D�W�k�h�U�T�a�]�P�V�o�M�9�V�`�T�i�d�Z�R�U�X�8�T�O�i�Q�X�N�T�G�Y�V�R�Q�L�`�T�F�_�W�[�W�g�N�X�[�Q�`�U�J�_�F�O�\�T�g�U�Y�R�g�^�G�^�A�A�[�W�Y�V�Y�e�K�T�A�W�Y�[�Z�V�M��d�U�N�P�[�H�8�V�v�X�J�`�P�i�L�]�h�M�T�V�_�\�0�I�[�b�]�c�c�I�U�X�9�]�I�R�S�I�Z�.�O�Q�X�K�Y�S�V�r�Y�L�E�U�M�R�#�G�o�O�]�g�8�T�O�H�W�U�X�K�b�]�\�C�s������&�����K�H�腷�����P�ăڀݛ�N�ʨ\�V�������ȄR�\�l��ƒL�d�"�Q�肹�����e�e�Q�[�c�i�T�-�^�`�[�S�V�S�T�|�\�H�C�_�u�d�`�P�[�U�U�Q�S�[�]�V�J�o�d�T�P�R�Y���E�W�D�S�T�D�P�J�^�Q�Z�j�O�T�Z�F�X�O�U���U�V�W�S�!�U�a�N�V�]�g�X�C�c�k�\�d�@�S�M�Y�Z�_�[�f�7�K�2�S�h�c�X�I�Q�k�h�\�d�Q��U�I�Q�:�)�]�A�Z�P�\�S�J�h�d�E�V���\�S�F�c�S�7�T�T�b�D�`���s�=�X�P�F�X�j�#�U�*�Q���B�K�R�W�G�{�G�E�M�Z�L�N�y�I�k�O�h�W�w�����-�(�(�����\��e�`�V������ȶ���:�U��� �*�օ�V���΃��9����Ђ�Ƃ��Âӂ��z�@�^�M�I�A�_�[�N�]�P�]�Q�g�]�j�B�T�E�_�m�X�2�U�G�K�J�t�j�I�S�k�e�b�_�`�X�]�[�O�Y�\�-�z�~�;�Y�X�X�d�[�~�q�O�K�[�I�[�I�`�U�]�T�R�X�b�[�7�V�6�E�j�[�W�T�F�U�k�i�e�U�[�O�L�S�E�5�Z�_���V�Q�a�T�I�Y�Y�P�O�`�M�U�4�i�'�T�L�Z�@�a�O�Z�<�O�d�c�1�_�[�U�S�7�9�\�b�Z�U�R�(�Y�)�I�U�\�X�b�v�]���]�W�:�V�X�I�W�i�Z�U�b�`�T�a�2�e�R�W�X�b���������������%�&�\���Y���3������� ���f�֌V�W�����ȃ�;�����������ɂ��u�~���������^�o�N�y�G�b�l�Q�F�`�K�d�\�_�Q�e�U�p�b�a�]�M�[�N�I�a�U�W�Y�\�c�S�B�H�Y�a�P�9�Q�F�k�Q�C�^�G�i�E�U�x�^��`�N�v�T�R�M�M�[�A�g�`�=�e�k�S�H�Y�D�N�J�P�U�#�R�6�Z�a�S�P�a�n�C�\�O�6�f�Q�g�Y�5�h�^�;�Q�_�l�q�Z�B���H�X�]�T�N�9���_�f�J�k�[�S�b�K�K�L�K�D�Z�X�\�b�J�J�Y�U�Q�`�Z�R�U�P�P�S�S�e�V���R�M�]�K�T�M�E�O�U�Z�V�O�;�f�^�Z�Y��d�����������̓�0�g�`�]����ܚƢu�٣��������|���ƒX���a���܂����؂����������g�h�d�f�d�T�t�R�V�O�Z�W�/�U�B�U�?�0�K�k�U�K�[�n�U�j�L�P�*�M�W�T�S�R�Q�x�i�]�X�\��R�Y�X�l�E�S�N�_�b�U�f�G�L�d�M�G�u�\�S�P�H�b�G�O�N�V�Q�]�O�\�V�a�[�M�Y�X�L�<�M�Z�`�O�|�]�b�N�g�]�N�G�a�|�Q�T�H�g�L�w�p�N�L���c�v�J�^�Z�Q�{�J�f�X�=�a�C�U�c�[�\�O�Q�`�L�J�G�O�W�c�/�Q�v�Q�P�W�h�J�Z�t�\�J�e�S�N�Q�Y�]�W�Q�X�[�b�N�r���A�C�V�����т����0�������؄�`���>���J��ɠ�^���ԓ��w�ل��0�΃Ӄ��B�9�낈���� ���낄���b�R�{�e�J�B�R�P�Z�J�I�S�_�5�e���C�s�P�g�f�P�l�a�#�^�f�h�Q�T�l�S�]�T�E�D�Z�1�U�S�b�L�^�K�W�Z�Y�X�K�D�U�V�G�S�b�^�N�U�K�b�W�[�R�M�_�?�E�O�X�Q�L�_�L�Z�X�Y�F��E�Y�E�U�@�X�O�S�P�T�c���S�P�N�T�t�a�h�Q�[�`�Z�p�]�X�Q�<�W�\�^�[�=�S�\�\�X�A�Y�V�^�D�C�;�N�Q�F�G�H�_�F�]�M�W�W�~�E�O�V�[�Z�0�P���N�@�Z�O�\�b�=�]�<�n�_�_�n�\�c�r���ǂԂ؃0�=�\�8�o���փۄ��M�b�s���кq� ����m�J�8�(�S�O�� �тł₁���ɂ��������'�~�^�;�`�_�K�d�O�R�L�T�g�[�Q�I�V�<�h�Q�W�Y�\�X�T�D�Q�N�B�6�7�N�X�g�\�b�F�V�I�\�R���R�H�i���I�O�Z�H�a�W�l�j�T�Q�)�Y�K�t�n�P�|�_�P�K�;�^�U�c�d�_�[�K�S�j�Q�Z�u�V�E�E�P�A�T�f�\�]�p�[�V�z�Q�Z�a�[�V�[�S�\�]�I�W���A�h�N�N�X�=�<�e�V�V�s�X�8�N�N�W�\�\�]�d�}�V���D�T�K���o�N�X�q�U�X�P�Y�`�f�\�$�V�_�R�J�u�Q�]�P�G�X�a�\��;�k�h�����҂������Q�‚ȃN�A�� ��ݙ���Ʀ�����ч����+�������Ⴑ�ԂՂ}�ՂႥ���z�t���X�Z�e�L�T�\�i�G�R�S���Y�`�P�V�T�d�R�A�V�e�C�M�Y�_�G�T�N�r�x�V�R�V�O�g�^�:�e�C�I� �N�Z�O�W�D�f�T�^�V�V�Q�X�/�R�R�S�O�g�Q�K�?�R�V�E�d�f�T�D�X�Q�d�2�Q�w�Y�r�Q�d�Y�W�V�c�[�C�H�W�c�W�>�,�W�N�X�h�G�Z�V�N�U�b�A�S�[�Y���O�^�S�@�O�a�h�s�H�U�W�&�Q�C�2�S�L�R�T�X�r�W�e�c�T�6�C�F�I�Z�\�]�8�L�`�\�Y�^�L�L�\�Z�W�|�1�M�V�\�A�n�}�p���}�������Â��Ƃ����׃ �7�솀�Ԑߙʞ �����|��6�Ӄ_�.���т邿�������e�肉�������t�<�R�p�a�b���l�M�P�N�\�,�R�d�O�b�O�8�q�`�X�_�Y�V�f�`�e�V�\�Z�(�J�Y�U�R�X�e�F�a�M�S�j�b�b�T�]�O�F�`�T�X�Z�X�E�8�X�;�P�N�V�_�j�e���U�W�O�B�e�U�]�X�M�R�N�_�[�v�V���c�a�Q�U�g�T�Y�I�L�l�R�b�V�Y�:�S�[�W�h�g�Q�@�;�S�?�N�!�K�Z�^�g�h�J�Q�@�^�L�a�P�^�`�o�\�Y�b�_�e�r�m�8�^�a�W�j�_�E�R�^�S�W�K�N�W�i�U�5�a�Y�V�P�^�Z�[�S�U�j�K�G�Y�w�{���������z�����Ԃ����ƃ �����g������߆�������˂ڂs���x�������x������҂��u���H��/�X�[�Z�S�y�T�T�N�m�\�V�e�T�f�U�N�e�U�V�X�O�S�c�D�A�l�X��R�X�`�M�L�I�`�L�Z�e�K�8�=�U�O�-�L�b�V�O�v�]�W���b���S�C�O�^�L�X�P�a�X�Z�\�V�]�S�\�K�f�e�;�Q�S�B���S�1�W�W�U�Z�O�E�T�k�4�[�S�V�F�Z�^�V�U�E�Y�X�[�L�:�C�L�A�V�G�J�U�V�W�Z�T�>�e�U��8�b�Q�D�_�S�O�B�S�`�U���E�I�b�P�P�|�H�z�a�O�o�U�L�I�T�R�j�S�W�i�R�^�Y�O��]�T�f����������~�k���������|�탚�� �j�O���u��s�肕�}�������e�j�X�~����� ���Ƃo�S�^�U�U�R�H�N�T�A�e�K�W�E�[�F�U�M�f���[�V�[�L�F�h�g�]�?�]�Y�k�t�V�Y�Z�d�W�Z�N�Z�^�\�P���U�`�{�U�R�K�b�X�X�S�[���E�^�\�O�T�H�]�X�_�V�g�f�g�R�M�W�Y���p�U�T�R�b�c�,�O�]�Z�T�[�X�Z�L�V�b�F�R�`�<�B�E�O�a�H�L�}�!�d�W�Q�h��U�W�[�S�Z�K�Z�R�s�?�U���8�Y�W�I�Q�7�]�a�R�]�I�K�`�R�k�Y�^�M�[�H�X�i�>�N���W�X�g�Q�P�W�^�Y�S�6�U�]�^�Y�������}�u�����k�b�z�y�{�A���ރ$���y�愍����/�����~�l�u�l�e�x���u�y����#�x�z�ǂq�}�\�Z�-�c�_�R�p�V�I�L�^�X�Z�R�O�^�X�T�`�=�]�>�`�U�L�^�a�T�W�T�i�a�W�E�`�r�R�T�e�P�I�=� �4�W�W�B�s�Z�V�N�]�P�G�s�U�X�E�U�]�Z�b�U�U�A�\�F�1�W�S�b�s�_�d�R�W�R�X�]�Y�N�f�Z�_�G�M�a�L�U�j�h�R�5�V�7�m�c�B�w�_�L�p�\�Y�x�)�F�}�S�_�W�X�W�Y�]�`�Z�b�*�S�O�[�N�S�G�=�U�_�L�V�W��a�l�L�S�P�V�^�W�K�W�\�7�N�^�P�V�P�q�^�O�S�_�u�Z���Z���������{�����z�v���g�b�u���������w����(��w�_�t�o�U�G�K���e������P���I��􂼂Z�g�E�O�n�V�R�w�D�4�Q�`�;�a�W�P�^�p�`���]�[�s�Z�_�N�]�W�[�@�A���E�S�\�[�Z�s�P�[�_�C�Z�j�A�R�]�X�e�Q�M�Q�W�V�C�]�?�V�c�N�W�F�U�T�N�Y�R�I�]�V�U�A�<�U�[�`�[�T�Y�P�=���L�}�S�V�\�O�B�]�M�M�^�3�V�X�B�W�o�P�V�Y�F�G�I�L�0�:���\�H�Q�Y�b�P�c�N�T�a�S�G�Y�@�@�O�P�A�f�a�^�K�W�d�h�a�\�H�Z��M�T�h�V�E�c�N�[�h�[�W�W�U�j�b�O�p�G�m�\���ׂĂy�x�c�t�����S� ���U�p�|�����A�R�e��̂��i�r���Y�i�]�`�_�d�v�����)�脕�:�]���r�g�I�b�q�R�Z�+�m�m�>�W�Q�A�@�V�D�G�S�,�R�P�q�W�W�[�]�R�M�a�c�?�i�[�Z��Y�X�R�\�_�N�W�O�S�j�U�J�=�H�W�M�[�S�_�T���s�E�>�Q�W�Y�[�^�b�.�O�R�|�\�I�c�X�K�G�S�Q�^�N�f���]�W�a�Q�E�_�T�T�O�B�c�^�2�W�F�C�M�V�l�O�M�W�O�a�>�S�)�_�W�M�I�u�\�R�R�`�E�]�S�f�R�`�I�K�k�k�R�k�V� �B�b�I�V�W�E�S�b�G�_�S�K�`��V�O�Y�;�^�Z�2�]�P�C�K�J�w�_����s���e�h�u�g�W�d�:�D�k���ς������ +� �������u�s�_��[�^�O�p�r�k��� �D������g�[�>�I�Q�]�N�n�[�H�]�d�P���W�R�E�N�a�X�C�\�h�h�Q�Q�U�l�3�I�j�]�Q�W�U�_�]�D�P�I�G�c�f�I���T�S�a�B�Y�V�W�Y�B�T�M�#�Q�R�U�m�]�[�R�Z�M�U�J�^�t�Q�Z�O�Z�d�V�q�a�c�E�Q�S�p�W�e�C�:�F�T�L�_�m�R�1�2�Z�V�Z�a�z�V�"�o�O�G�]�[�\�E�p�<�[�V�S�O�_�d�V�G�h�b�8�Z�U�i�^�J�V�n�8�R�Y�S�@�r�Y�E�U�M�^�_�P�X�1�:�`�?�g�X�B�W�T�_�N�[�S�]�_���d�s�V���k�Y�x�o�d�k�_�@�c�g�d�g�a�r���������X�Q�m�h�h�P�I�S�W�!�]�]�c�_�a�z���h�c�g�W�R�`�d�C�_�c��X�R�^�Y�g�h�h�R�_�m�[��S�a�\�]�T�h�R�R�X�L�>�C�a�<�N�M�s�>�W�_�I�b�S�A�X�T�T�H�_�@�Q�U�X�A�\�[���O�T�N�Q�E�C�A�^�F�_�K�F�X�T�@�S�V�N�X�U�Q�@�V�g��V�N�]�U�I�J�Q�[�B�B�[��K�@�Q�W�5�^�y�a�@�X�]�]�Y�i�>�b�b�G�S�[�N�P�s�S�X�5�\�S�h�`�I�`�c�s�?�L�_�W�Z�_�L�S�V�Z�F�P�>�T�b�L�k��\�a�I�U�Z�f�_�T�a�l�]�[�Y�V�H�Q�S�L�P�Y�d�`�f�\�2�R�Q�V�k�k�R�p�W�p�m�T�8�R�@�G�t�O�Q�N�Q�T�C�d�_�m�Q�f�\�W�\�p�J�=�K�V�o�W�T�Z�V�U�S�\�I�f�e�X�^�`�N�_�f�S�f�V�L�Z�O�^�Z�;�J�)�X�N�Z�X�S�`�>���S�T�C�D�R�Z�T�E�a���\�h�d�V�E�F�1�Q�[�T�U�Z�J�h�_�T�W���c�m�W�j�Y���4�v�`�H�K�O�c�[�b�U�k�Z�l�V�P�Q�f�Q�Q�_�q�X�>�^�W�h�W�P�O�\�P�f�C�\�J�g�^�[�_�S�O�t�o�c�\�=�z�N�]�K�S�N�_�S�P�D�_�P�S�k�N�m�K�C�k�g�F�e�E���S�J�U�T�Z�a�_�P�I�R�M�[�0�i�a�`�\�X�P�[�Y�T�M�T�|�R�Y�{�O���[�E�_�t�^�`�W�(�a�_�J�W�B�O�Y�d�M�Z�R�F�h�h�S�l�N�[�U�Z�`�D�P�S�2�[�^�L�O�\�U�V�i�\�H�U���@�y�V�T�S�2�_�6�Y�_�F�x�Y�K�W�g�P�W�`�O�D�X�O�[�_�H�M�L�r�W�I�<�W�`�S�]�)�b�V�S�[�/�a�T���S�?�G�q�E�Q�T�Z�`�Z�[�_�S�R�W�`�_�^�3�W�p�W�b�n�C�>�]�z���X�_�[�[�Y�S�V�P�G�S�V�T�T�W�C�[�T�R�R�[�_�Z�\�Z�K�P�j�]�e�c�`�T�`�X�`�\�N�c�m�R�U�U�V�_�n�?�Z�a�[�e�R�i�z�=�[�T�S�d�Q�m�[�R�F�#�g�L�-�f�e�U�b�X�>�Y�T�m���E�S�V�N�J�Z�B�b�X�}�H��c�S�k�S�?�W�]�V�W�L�a�Q�/�d�\�_�E�A�Y�s�Q�g�(�L�)�S�[�`�I�c�[�`�X�g�`��r�f�Y�<�`�H�a�d�M�T�D�Q�?�U�b�P�U�T�c�?�R�k�e�R�`�]�C�N�\�K�R�j�F�R�K�[�S�}�^�G�a�R�c�m�Q�t�h�P�L�\�J�I�J�Q�X�Q�H�R�\�P�i�X�[�T�a�I�`�L�^�^�R�R�U�b�a�L�L�X�h�Y�[�L���Q�_�w�S�O�T�y�a�>�k�Q�U�D�V�Z�L�^�b�Y�J�L�T�_�W�^�T�O�g�O�i�S�^�x�Z�Q�R�Z�\�\�O�V�I�V���M�d�[�c�P�\�o�W�S�V�q�L�N�\�Y�_�J�Y�S�[�L�R�O�\�"�\�V�N�^�^�_�Y�[�I�@�@�`�>�C�?�A�>�n�Y�S�n�Y�H�]���\�W�J�S�E�P�q�F�Q�}�V�S�`�M�X�5�Y�\�m�W�j�V�k�\�^�\�\�o�&�V�V�a�P�f�R�T�P�Z�X�^�d�V�d�X�Q�\�a�L���Z�_�]�R�;�Z�Y�_�f�R���Z�j�X�_�q�U�P�H�T�h�R�]�e�D�]�\�O�X�W�Y�A�N�P�\�T�_�<�f�C�[�N�N�X�N�]�T�]�f���Y�L�h�d�Y�S�{�K�Q�d�h�_�U�Y�Z�N�X�h�f�X�M�Q�W�\�^�I�Q�O�_�I�P�m�E�H�C�^�\�W�Z�V�X�o�X�_�l�W�i�^�Y�:�^�J�[�O�^�O�a�'�d�c�V�q�R���M�Q�S�h�;�^�Y�V�b�[�O�a�J�I�X�U�W�Z�V�n�q�?�L�c��j�I�S�Z�k�K�\�U�i�L�h�W�l�@�R�?�W�N�o�^�a�g�W�a�#�a�T�B�U�d�]�N�Z�H�e�V�x�l�V�A�V�a�b�L�I�N�V�U�:�b�S�Y�J�^�[�U�U�N�a�s�j�U�V�I�[�W�a�U�b�X�R�W�P�~�\�?�S�V�[�g�]�\�`�<�N�[�1�Q�W�=�V�_�Z�^�`�r�Q�V�i�d�a�S�j�^�O�a�b�I�U�;�#�k�G�V�P�R�^�b�g�V�N�U�Q�L�M���o�h�X�[�h�Q�n�\�b�Z�F�-�w�R�_�Y�S�T�G�M�N�T�O���R�E�c�^�W�#�_�G�V�\�`�m�?�N�V�c�\�A�\�W�Y�Y�S�U�f�F�c�f�o�T�O�N�R�Z�Z�a�U��T�P�?�R�p�P�^�=�[�[�d�C�T�^�B�m�O�\�Q�C�a�f�T�]�#�Y�g�a�X�M�U�a�i�O�Z�R�[�h�\�Z�[�Y�S�a�c�e�T�b�^�l�R�e�U�_�l�L�\�[�Y�G�L�p�S�O�o�Q�B�U�]�X���[�O�P�[�X�f�J�J�P�a�Z�U�Q�j� �A�k�]�V�Q�;�W�c�\�c�j�X�d�B�X�Y�T�d�U�F�X�j�a�O�q�g�W�F�P�S�O�Q�O�U�W�V�D�Q�B�R�d�J�\�P�h�W�L�S�]�V�E�I�M�o�K�U�c�U�a�H�T�T�l�j�C�p�L�X�X�N�K���U�U�c�4�Y�P�P�r�S�G�^�P�Q�S�9�X��`�Q�J�`�N�K�M�Y�V�Q�R�O�^�g�T�t�S�Z�g�\�g�I�M�X�]�z�N�i�I�_�S�d�(�Y�?�+�X�j�>�T�M�^�F�a�[�f�d�m�J�C�Z�o�W�`�G�\�k�M�O�Z�N�S�c�[�N�V�X�N�S�I�L�N�R�a�f�Z�t�P�Z�Z�_�`�]�\�Y�P�`�_�]�Y�q�Y�M�U�S�E�B�S�n�N�[�|�[�U�l�Y�i�S�b�U�X�T�X�g�H�`�t�x�V�R�Y�m�Y�[�@�K�X�O�[�Z�V�t�G�]�\�Y���a�Y���C�3�Z�d�Z�M�a�9�8�V�Z�S�I�[�U�V�T�W�O�'�p�g�V��b�R�K�9�[�T�`�R�j�M�b�r�K�W�Q�W�E�]�\�O�L�1�S�C�b�X�I�_�l�V�G�S�d�n�M�w�P�`�l�Z�[�Q�]�v�a�X�;�R�Y�O�\�F�_�e�\�O�I�^�t�U�e���W�4�h�C�b�R�Y�a�A�h�L��W�[�c�h�d�I�X�g�Q�Z�U�T�E�H�Q�L�t�I�]�_�Q�I�J�Y�l�E�F�U�X�S�a�M�S�Q�<�H���f�^�W�Z�j�V�_�l�V�<�;�o�e�X�a�a�K�V�\�U�f�>�W�^�Z�L�X�Q�Y�N�p�]�c�S�V�J���_�Q�4�Z�R�N�R�m�H�\�c�a�V�Y�@�R�Y�L�_�R�W�P�s�?��N�K�_�c�6�V�_�@�V�V�L�>�H�^�B�\�O�s�U�h�I�S�@�Q�Z�a���U�A�k�p�L�Y�W�_�i�J�`�m�X�V�D�a�a�L�Q�X�W�A�b�c�U�S�V�X�>�W�X�`�e�N�r�Z���J�I�W�q�R�e�W�W�Y�Y�S�Z�g�T�L�[�%�[�K�s�o�R�P�p��X�F�b�z�C�j�F���i�o�`�@�K�P�j�L�V�L�C�f�O�S�`�Q���=�Q�R�k�b�?�c�R�C�O�Z�k�n�U�J�R�a�d�Q�g�U�R�^�e�R�[�Y�U�n�S�H�o�f�]�k�@�F�x�S�X�W�k�b�9�\�<�^�W��G�`�F�H�h�P�Z�|�<�_�M�Z�A�<�S�Y�\�K�W�M�S�T�[�E���Z�Z�Q�Q�h�W�D�X�[�^�I�M�_�Y�V�P�O�O�V�b�Y�V�K�G���S�W�T�M�R�P�K�]�g�J�E�X�[�`�n�;�h�G�T�T�n�Z�S�\�g�D�g�R�=�Z�Q�X�U�M�W�<�\�[� �]�W�X�E�O�N�T�l�[�Y�f�Y�B�`�a�U�P�J�H�M�L�e�S�]�.�Z�G�]�Q�?�Y�S�N�M�S�p�E�j�^�L�X�j�G�Y�T�T�p�M��#�^�G�\�V�\�]�V�V�Z�Z�^�j�f�X�V�V�T�2�E�J�o�R�F�I�m�b�C�e�I�s�P�'�[�Z�Y�U���L�e�G�_�Q���S�O�O�Y�g�#�]�T�M�X�N�Q�C�b�h�[�8�;�@�C�\�]�W�a�^�l�J�D�:�V���H�q�]�g�M�g�J�b�T�w�g�S�Z�C�U�W�U�a�d�d�Y�m�h�S�p�Z�W�I�W�6�^�R�L�K�a�^�P�V�d�M�h�V�a�V�=�N�Z�e�J�\�]�F�k�C�T�8�T�K�J�O�a�V�K���H�A�J�u�N�O�b�P�I�N�T��W�P�U�M�i�d�f�M�M�R�P���6�R�b�d�Z�_�]�G�Q�F�e�_�R�Y�v�A�W�a�`�S�U�N�l�[�T�_�b�G�d�^�d�M�O�r�d�L�W�?�1�W�Z�U�[�V�o�U�a�f�Z�5�n�W�I�`�E�S�r�[�O�W�Y�R�$�F�j�^�o�2�I�X�F�Q�W�[�{�Q�U�a�V�b�5�J�U�_�T�l�:�B�Y�]�X�R�V�X�]�T�?�N�O�Y�V�H�N�e�T�O�q�P�Y�p�W���P�]�h�Z�P�S�_�P�M�[�W�=���W�\�Z�\�M�M�c�Y�g�d�Q�L���S�=�F�^�Z�a�T�b�<�Y�\�Y�b�k�M�G�h�\�E�7�N�W�S�\�T�e�M�a�s�B�X�[�^�l�T�Y�P�c�G�]�a�e�?�^�P�.�;�^�\�5�T�\�;�X�[�M�Z�K�Y�U�U�e�P�Z�g�L�O�]�5�h�J�g�T�h�e�]�S�H�M�9�V�:�R�j�]�W�F�_�*�b�\�L�Z�R�Z�E�C�?�\�U�i�G�@�n�[�X�I�c�e�^�_�P�f�V�X�n�U���V�V�U�_�[�[�O�V�X�q�C�[�U�\�L�X�K�w�g�=�f�L�Q�u�x�b�c�J�C�T�]�p�A�S�V�^�n�K�n�X�c�b�L�5�U�s�W���]�o�Z�X�T�p�_�=�C�l�`�K�U�J�c�W�a�U�P�U��m�K�S�]�U�D�Y�U�F�L�a�R�W�S�d�%�J�P�Q�I�h�_�W�K�b�\�q�l�R�J�]�M�^�g�[�[�R�O�x��F�d�h�h�R�e�X�s�e�Z�P�V�W�I�U�W�S�E�Y�p�S�\�m��U�J�O�i�P�W�Q�Z�T�]�[�T�f�`�V�c�F�l�T�X�T�c�d�[�7�O�b�S�e�w�x�`�F�E�N�Q�S�Z�b�l�I�b�Z�i�a�U�[�m�s�W�W�M�w�C�V�y�P�c�V�]�^�b����4�C�I�[�`�T�f�G�c�b�8�]�S���d�X�Z�W�_�_�j�\�)�_�Q�T�_�<�h�`�Q�Y�[�S�L�\�i�]�V�N�X�e�]�S�`�Z�R�H�s�^�P�\�M�i�a�d�`�S�C�%�W�=�l�i�u�^�x�R�W�S�^�E�A�@�Y�a�o�o�C�R�V�O�e�o� �a�a�c�?�]�W�A���W�m�]�K�Z�X�E�Z�M�A�e�I�U�T�]�J�J�U���U�D�Q�;�r�W�Y�I�L�Y�\��a�P�X�H�X�M�V�9�\�V�V�g�C�_�U�,�n�[�]�b�P�W�m�9�O�l�W�[�w�Y�\�P�J�=�i�m�S�[�R�V�.�_�G�V�0�Z�^�V�R���Q�#�U�N�X�X�V�7�[�T�U�b�W�^�]�g�a�O�V�Z�g�E�O�P���+�[�m�9�f�?�G�u�e�e�b�D�L�d�_�T�\�m�`�_�L�O�T�[�T���W�o�T�^�o�Q�c�U�X�S�P�Q�?�J�d�_�Y�S�Y�[�D�_�m�]�b�X�k�O�d�G�W�L�V�f�Y�E�Z�L�X�d�c�X�P�W�e�;�V�k�U�V�X�H�^�g�V�f�o�d�@�8�Q�`�L�L�Z�W�Y�[�X�]�O�W�*�_�X�l�[�G�s�C�`�T�W�l�U�]�T�S�j�8�\�]�c�\�X�a�W�W�8�:�V�c�T�F�9�X�`�^�\�T�U�n�Z�X�U�B�O�e�P�\�X�g�b�z�2�a�\�g�S�i�H�V�B�L�d�S���I�T�h�W�=�\�W�_�[�R�;�Y�;�P�Q�M�S�d�]�2�]�]�`�K�2�I�^�W�b�[�U�:�t�K�o�V�^�\�S�U�_�V�^�N�U�P�[�T�O�N�_�U�Z�T�N�Q�?�W�_�\�m���s�S�?�e�o�>�a�H�W�s�I�f�f�R�^�N�a�Y�N�g�c�J�S�M�\�K�G�_�^�]�M�e�o�k�L�K���N�T�l�N�N�x�?�Z�Y�K�S�[�K�D�[�R�S�J�W�R�Z�b�C�W���W�V�`�V�N�Y�R�N�S�T�i���T�X�R�H�a�k�Q�w�i�Q�N�[�E�R�6�Z�]�Z�U�[�Q�f�J�O�b�L�*�X�h�c�j�c�R�^�I�\�T�[�t�B�Y�Q�R�V�R�^�a�W�Y�_�T�U�Z�_�q�?�Y�V�X�s�R�W�k�V�l�N�Y�Z�]�d�\�]�[�^�c�q�]�O�Q�U�R�\�_�V�0�J�y�[�U�P�[�^�X�T�P�C�Y�U�O�U�X�/�V�L�F�R�_�b�K�[�W�V�P���v�<�_�U�g�_�T�`�O�B�H���Y�]�^�P�H�_�@�\�E�a�w�E�]�V�I�q�J�]�Z�Z�H�_�Z�W�d�Y�D�^�N�T�w�f�&�b�P�^�F�`�^�q�f�R�W�6�Z�^�`�D�F�C�h�X�$�f�S�P�V�i�y�L�\�/�a�^�X�K�Z�O�_�f�Q�i�`�\�K�L�U�N�Q�T�G�W�W�W�^�?�+�h�\�`�Z�F�w�P�]�T�i�^�;�^�r�P�U�W�Q�W�G�T�b�\�Q�S�b�R�^�b�e�D�B�[�I�\�a�X�W�S�N�L�F�\�a�c�\�[�_�c�`�[���Q�J�P�h�M�T�f�|�j�f�V�C�R�`�p�Z�I�R�\�T�m�d�F�X�~�N�W�N�W�W�^�N�c�l�\�T�J�H�O�;�Z�X�j�a�[�_�g�9�R�y�Q�d�W�O�K�@�o�e�F�K�G�T�=�\�\�b�[�b�:�J�W�d�h�/�G�Y�W�P�B�R�c�K�`�W�S�<�X�P�b�Z�R�O�x�`�W�V�i�Y�M�R�a�F�l�S�V�`�V�h�H�U�z�Q�U�Q�]�]�K�]�_�t�f�j�Q�T�X�V�W�y�_�^�O�J�P�j�?�5�J�^�g�:�F�K�]�B�?�/�T�g�U�_�[�M�i���j�P�N�W�W�e�U�I�P�v�I�]�P�`�X�V�Q�8�c�b�j�^�a�Q�b�o�P�X�U�b�c�v�7�f�f�J�Y�W�j�c�k�`�a�=�Y�8�V�^�V�A�l�i�W�Z�N�B�T�X�f�`�\�Q�Q�{�]�f�O�O�H�Z�y�V�S�y�^�Z�i�q�H�S�^�_�g�9�b�D�d�Y�q�Y�]�Q�H�j�;���a�]�V�S�\�N�R�g�Y�^�m�i�c�T�e�Y�J�O�D�D�\�j�O�p�L�V�@�[�X�r�[�I�M�i�N�W�D�f�Y�_�X�K�Y�m�[�R�Q�X� �^�O�`�X�`�X�U�]�N�Q�H�w�m�N�Q�W�Z�z�d�W�v�8�X�^�x�m�c�V���f�^�4�V�Z�o�c�=�Z�X�M�A�Q�Z�m�Z�U���b�B�L�S�t�r�P�M�L�T�^�D�M�h�_�[�C�H�Y�[�[�]�k�U�m�[�X�O�P�e�d�a�U�Y�j�d�Q�Z�_�N�X���U�W�e�:�e�Q�J�Y�m�_�\�c�X�Y�F�O�U�q�b�Q�^�_�d�v���=�Z�P�K�p�R�G�T�`�T�Y�I�q�b�L�Y�h�k�b�M�`�h�W�R�j�U�L�P�T�Q�L�Y�E�I�Z�`�g�Z�X�P�_�O�t�T�a�_�T�k�E�^�T�\�M�_�i�c�[�V�b�b�F�]�[�U�U�_�Y�B�F�c�f�Z�X���]�Y�t�\�+�R�q�m�b�B�*�:�K�`�]�I�a�B�l�Z�V�b�q�K�.�x�b�\�O�=�H�\�b�]�a�a�[�_�b�>�f�U�O�\�]�_�I�U�d�8�e�3�b���J�[�]�Y�E�Z�`�]�Z�D�T�F�[�w�[�L�'�]�D�n�[�N�p�[�L�C�T�X�H�S�K�f�>�_�.�|�`�Z�U�`�g�]�\�c�Q�a�N���M�\�B�S�Y�W�L�k�`�V�Q�/�W���o�b�b�T�]�^�\�p�b�W�n�|�]�=�P�V�X�[�t�Z�H�o���b�L�U�R�^�b�j�Z�Q�a�c�a�b�X�e�O�T�U�g�^�o�Z�Z�g�Y�Z�O�U���P�K�_�K�[�Q�T�w�P�?�h�^�U�A�E�Z�Y�[�`�1�W�b�k�O�D�X�j�]�N�g�^�$�V�Y�Q�c�Z�m�=�T�X�[�@�V���]�h�W�q�f���g�L�[�M�[�w�a�{�N�[�j�]�Q�Z�?�?�U�T���Z�O�X�Q�^�W�^�d�V�N�U�`�[�]�]�@�S�T�b�D�R�K�f�q�q�Y���[�X�`�c�V�o�]���e�L�U���@�Y�c�T�X�Y�Z�Y�k�^�a�x�k�P�`�]�J�c�l�Z�P�S�X�Y�~�V�l�\�J�O�\�I�Y�@�N�B�K�?�7�R�Q�a�d�V�Y�R�P�l�[�/�d�Z�f�Z�^�O�h�a�R�V�W�O�P�[�a�C�X�R�`�Z�m�T�W�]� �`�e���Z�d�L�O�M�_�N�Z�i�U�Q�R�\�\�M�K�V�b�o�V�=�^�]�X�J�q�o�K�S�v�U�M�[�e�a�V�U�5�b�]�a�V�N�=�E�W�M�g�\�Q�I�[�F�X�T�d�Y�b�j�J�b�R�V�R�P�X�U�H�R�/�f�U�\�W�W�o�d�^�h�V�[�[�3�[�}�U�_�Z�]�\�N�d�\�\�R���`�[�X�U�e�M�[�Q�[�I�g���d�7�R�^�H�E�W�U�@�j�Z�\�g�i�u�U�W�d�c�V�[�O�`�Z�E�Q�h�^�W�S�_�^�a�R�S�J�Q�B�j�k�P�U�T�Z�`�P�V�=�Y�{�i�p�M�W�\�}�l�P�d�a�<�\�c���U�m�[�]�@�`�j�b�Z�]�_�]���r�W�Q�M�Z���l�e�u�X�Y�v�X�c�Z�R�N�J�f�W�N�O�b�M�j�g�Z�L�T�X�Y�m�Z�^�a�U�w�N�b�n�]�K�S�C�Y�r�a�j�Z�S�n�k�V�Q�P�M�^�\�f�k��E�c�R�D�\�X�U�O�Y�h�3�L�E�[�]�a�D�W�P�T�Z�M�m�Y�W�_�G�.�W�P�<�Z�N�N�W�P�H�5�X�[�S�C�S�O�E�\�T�]�O�(�o�g�O�R�T��T�E�R�W�F�T�Z�S�U�\�s�r�t�a�f�P�U�[�Y�d�x�V�Q�[�;���Y�d�[�\�\�V���a�d�Y�>�`�V�d�W�R�Z�u�^���X�i�|�R�-�\�W�L�N�h�_�\�_�f�e�O�X�V�i�T�h�Q�I�M�M�J�Y�U�X�Q�[�P�S�4�W�Z�=�X�K���S�Z�^�\�Y�q�\�c�X�]�C�W�^�Y�S�Y�I�[�S�^�^�J�?�f�Y�k�f�C�:�a�D�^�c�Z�R�n�N�H�a�`�]�S�e�>�T�6�^�m�c�X�d�_�\�T�_�f�C�J�=�M�c�]�V�P�\�f�\�X�S�o���Z�W�e�i�_�a�`�d�P�j�]�`�K�^�A�P�=�C�b�`�P�d�W�W�-�g�`�P�X�F�c�F�L�r�\�]���P�\���g�`�M�T�X�Y���U�t�W�X��N�Z�]�p�V�Z�Y�V�T�e�n�i�t�[�`�V�W�a�W�T�Z�U�3�Q�S�K�\�x�X�Y�A�P���V�]�q�.�l�Q�X���W�V�K�Z�Q�T�h�f�i�P�G�g�Q�c�I�a�P�Y�_�S���U�b�^�h�d�T�H�X�W�B�J�Q�^�@�[�d�j�Y�\�h�W�Z�f�>�;�U�^�S�L�V�P�^�R�H�k���d�H�Y�M�L�G�V�y�2�R�U�U�O�~�`�i�Y�Q�M�U�h�S�N�;�C�e�w�\�_�^�?�C�S�u�U�b�q�[�\�Z�c�F�U�s�\�X�O�]�V�s�k�[�L�O�a�t�R�U�O�Q�b�x�^�f�T�N�Z�Y�M�b�>�L�_�S�O�L�Z�S�\�N�]�_�V�`�7�f�f�e���E�k�`�A�Z�d�P�R�T�X�e�c�k�P�D�T�V�q�^�Y�c�Y�Y�c�|�r�[�O�[�\�S�X�k�,�S�i�G�H�W�e�^�E�E�Y�?�E�9�a�Y� �X�X��g�Y�R�V�W�_�]�H�V�i�[�U�m�T�j�[�P�U�i�k�T�j�b�a�Y�W�W�6�S�f�]�M�T��U�^�W�V�O�f���i�X�S�`�b�g�^�e�e�R�o�j�>�L�c�T�]�M�Z�H�Y�g�Y�^�P�T�_�,�f�P�W�S�Q�b�a�V�J�]�S�_�^�2�P�O�\�^�Z�V�Y�d�:�T�c���U�^�[�g�e�W�m� �{�R�b�c�)�Y�<�P�E�L�H�l�a�W�_�a�f�Z�]�h�V�K�`�F�S�B�f�J�[�V�c�f�J�X�L�P�Y�Y�O�Z�Q�U�N�^�B�_�a�`�R�`�R�`�Z�R�B�Y�U�X�a�Y�W�D�P�d�b�M�`�Z�,�Y�h�n�c�R�9�V�[�n�]�j�f�N�K�`�]�J�f�a�M�^�w�^�T�w�b�Y�7�T�X�[�X�Q�l�|�_�[�[�E�P�X�]�T�c�^�Q�R�c�?���^�H�I�W�h�P�[�j�V�P�f�Q�h�_�b�L�U�^�U�>�f�m�Z�Y�w�j�Z�M�`�\�H�]�U�c�G�R���O�U�E�^�Q�I�Z�d�i�_�Z���]�S�X�\�W�p�h�c�I�W�e�i���[�^�?�U�\�h�e�T�`�V�J�I�Z�X�U�U�_�X�;�z�Z�Y�R�\�W�{�\�a�o�R�O�V�[�Z�=�S�o�\�@�R�Q�Z�?�a�q�C�K���A�S�L�Q�[�~�P�h�Q�G�o�k�Z�x�_�)�f�N�\�_�]�^�V�N�\�F�Z�(�q�a�^�`�K�T�d�i�Z�N�`�y�z�T�c�T�_�^�Y�X�M�<�L�^�b�T�N�E�^�H�X�/�M�k�m�K�O�E�T�t�Z�X�_�Y�a�h�3�N�^�%�e�l�t�H�w�Z�l�p�_�j�l�e�P�_�S�o�w�`�B�]�f�U�W�C�a�^�c�D�W�Z�^�r�V�s�F�s�V�X�T�b�A�4�\�_�_�`�W�z�e�H�]�[�b�^�T��_�T�]�f�A�8�[�_�J�D�X�T�b�[�W�`�Z�9�L�W�H�H�Q�a�\�R�\�U�[�[�P�c�W�e�l�K�G�E�`�]�i�_���[�R�F�{�X�c�b�[�R�]�M�)�c�d�S�Y�\�V�U�`�K�Z�^�Z�`�n�R�s�V�S�W�K�e�Q�W�U�=�@�p�a�[�C�c�[�N�_�{�a�G�f�f�4�y�j�L�3�Y�d�c�R�[�U�[�^�r�a�X��/�~�Y�`�o�X�\�F�i�\�T�U�v�:�`�[�M�W�[�b�b�b�Y�T�]�P�d�/�g�W�T�W�O�U�_�S�N�K�|�Y�V�Y�W�U�U�I�Y�Q�Z�d�d�d�P�Y�\�h�l�6�A�V�;�V�[�S�e�W�^�Y�W�_�9�M�c�^�J�T�W�q�W�9�t�W�)�L�`�S�S�O�^�P�b�d�r�i�n�b�X�g�o�\�E�]�V�W�]�a��\�a�H�Y�X�_�V�B�m�c�A�f�r�B�R�_�K�^�[�X�e�`�S�X�B�Y�i�m�P�Q�+�g�e�G�\�e�K�c�M�E�K�\�h�\�R�V�U�N�Y���^�b�u�P�Y�j�\�T�c�P�U�X�:�d�;�[�i�t�a�T�H�V�X�X�T�U�s�S�q�[�T�_�o�F�V�\�M�i�3�g�_�Q�Z�l�U�\�A�T�W�Y�X�V�]�H�Y�^�W�\�b�_�W�G�[�^�W�Y�Z�O�=�X�;�\�_�g�]�T�a�J�P�_�N�T�V�P�S�N�W�U���b�]�b�Z�L�]�T�[�P�I�K�_�e�^�X�S�L�c�]�}�]�S�H�S��l�Y�_�T�`�W�\�O�h�_�O�1�Y�\�E�L��X�U�O�]�c�_�b�@�F�[�i�<�M�H�X�M�c�-�h�i�I�M�J�[�S�6�T�O�e�P�U�r�d�[�l�W�Z�\�O�/�d�K�L�b�J�A�W�c�J���J�X�e�J�f�i�D�c�v�Z�G�^�i�Q�H�j�]�M�'�p�d�E�Z�V�P�b�h�B�f�[�U�_�h�C�X�^�Y�Z�@�X�Y�X�R�6�W�:�V�Z�Y�R�W�}�\�P�P�Q�f�Z�)�G�`�[�N�T�U�f�Q�:�Z�M���D�V�X�P�V�S�X�R�c�V�`�Z���]�`�~�S�\�S�[�V�U�i�J�x�W�J�M�_�T�c�m�^�M�9�W�P�3�j�S�]�]�b�>�]�U�]�f�_�k�Z�O�;�L�Y�^�P�e�b�a�a�e�P�\�U�X�J�i�Y�c�2�[�W�K�q�Z�G�V�z�W�G�Q�_�]�N�A�m�T�[�X�6�D�T�Y�W�k�T�R�L�Z�e�T�G�h�T�_�\�Y�Q�Y�<�Z�d�R�\�a�[�j�_�U�_�h�_���R�[�o�i�o�c�R�X�S�T�H�_�_�j�S�Y�`�V�M�V�I�j�O�[�F�F�[�X�]�5�P�T�U�c�M�Y�Y�_�u�T�h�b�U�:�[�K�L�e�]�L�Z�X�\�P�V�r�P�S�R�T�P�p�u���o�Q�]�]�h�T�_�U�Z�[�Z�j�^�Z�T�[�B�N�M�X�W�p�B�W� �H�X�T�W�Z�L�L�V�X�J�V�b�r�d�\�T�j�]�I���R�T�f�b���\�W�D�[�S�G�q�f�S�W�X�l�r�A�V�^�T�]�N�Y�L�R�O�Q���c�R�P�`�j�W�X�C�l�S�\���W�Q�U�N�G�_�g�Z�0�J�k���S�_�[�J�P�Z�:�_�:�b�L�r�f�\�q�Z�A�i�U�O�O�G�Y�V�S�U�]�[�_�f�V�S�^�T���Y�d�O�V�G�C�}�V�e�b�O�^�D�S���{�T�W�W�K�j�^�D�l�Z�^�p�_�T�S�a�c�X�b�S�]�F�W�C�a�A�b�g�_�K�k�Q�P�@�M�K�F�a��e�9�Z�`�l�a�V�Z�O�O�U�u�f�t�W�}�2�{�h�j�^�@�n�Q�;�X�]�|�N�T�G�Q�[�]�\�^�v�J�K�b�V�S�P�\�U�R�Y�i�[�0�U�_�B�O�_�F�p�Y�Z�Y�[�6�T�a�Q�e�c�X�Y�L�E�X�V�o�,�[�U�G�X�W�a�d�^�o�E�8�;�z�]�W�S�J�U�`�U�b�a�b�n�_�Y�\�Z�j�[�;�V�l�M�D�d�\�W�[�X�a�`�`�Q��\�\�n�+�P�g�k�Z�X���\�h�X�I�K���7�X�:�c�X�\�P�Q�`�M�g�7�C�b�Y�l�]�F�[�~�q�T�U�Z�/�S�]�I�c�?�]�V�R�`�T�r�I�?�E�l�X�W�T�M�N�Y�a�C�O�_�Y�\�D�R�M�\�]�f�8�k�K�k�R�C�H�P�X�Q�l�;�S�Z�Z�f�[�[�I�Z�U�c�<�G�U�U�K�b�a�R�!�`�Y�h�^�N�U�M�^�;�M�V�_�c�3�\�T�r�L�[�Y�X�U�o�j�R�g�U�M�@�[�~�R�s�Q�W�V�Y�O���Z�d�]�l�Z�W�S�_�V�a�I�I�k�\�b�^�e�T�[�?�O�:�d�\�N�X�a�R�e�;�Q�g�L�X�{�s�A�X�]�E�W�_�O�_�_�`�[�?�_�Y�_�T�u�_�V�S�m�L�X�[�Y�v�]�_�e�V�S�d�K�]�M�U��X�^�g�a�[�?�U�z�W�N�\���\�X�F�O�G�P�K�e�a�[�k�i�j�U�5�I�N�W�Z�\�^�a�W�N�p�W�G�O�S�L�Z�W�N�Z�_�K�\��[�I�N�y�`�O�V�f�N���_�Z�g� �P�Y�k�V�g�U�e�`�S�Q�P�G�X�>�\�^�c�V�_�r�j�i�]�f�c�Y�S�P�a�T�[�Y�q�R�Y�d�@�W�R�P�C�V�S�_�[�^�u�O�V�Y�[�b�V�S�p�_�K�`�V�n�;� �;�Y�H�g�P�2�d�\�i�[�W�]�'�L�X�X�Z�b�\�L�c�_�M�I�"�c�X�X�S�P�`�w�^�T�b�I���>�a�|�t�X�_�T�Q�V�G�D�t�Z�>�V�b�E�H�]�T�i�`�R�Q�G�\�[�@�o�R�J�P�e�u�Y�d�H�c�U�e�P�e�d�^�L�C�Z�T�n�j�Z�H�H�j�I�i�R�^�N�^�J�]�N�Y�H�U�e�X�L�A�P�<�[�_�j�W��^�I�M�F�e�S�n�Q�H�I�e�_�g�V�I�`�X�u�c�`�r�J�N���g�d�S�h�S�J�]�s�q�[�P�a�g�b�[�H�q�R�T�S�j�P�M�i�7�H�_�\�Q�Y�]�W�6�T�U�`�T�f���X�[�S�[�O�b�T�V�g�Z�]�a�`�V�V�`�P�^�V�C�L�7�`�]�f�Y�|�U�K�K�U�1�G�W�p�(�R�8�u�V�g�i�:�^�g�e�V�v�?�L�X�B�D�k�T�Y�M�]�h�Q�M�o�b�l�L�b�X�h�]�c�g�^�r�[�N�M�^�Y�U�p�P�S�_�i��[�_�C�T�_�b�i�b�a�b�j���b�Z�Z�a�M�R�`�u�]�c�U�N��k�=�i�X�Q�\�S�[�w�^�a�f�B�L�a�e�\�Y�/�j�d�W�[�M�j�N�@�\�>�b�T�M�p�]�G�w�\�E�`�F�_�M�e�O�g�L�P�<�I�h�d�K�h�P�[�U�Z�w�S�O�_�M�`���F�D�r�g�a�l�X�T�`�M�s�}�4�a�Y�]�g�o�_�Z�H�X�c�Z�!�Q�P�?�`�[�[�O�[�l�`�K�a�v�>�n�i�N�T�e�J�X�R�H�Y�k�_�a�\�o�e�b�\�j�^�J�O�g�>�d�R�O�K�L�m�c�^�Z�B�]�q�\�_�\�g�`�T�W�d�R�I�e�Q�[�U�Y�X�X�C�K�n�W�V�����i�W�[�k�\�[�J�^�U�H�_���}�[�l�u�`���Y�Q�g�`�^�f�I�`�]�[�a�a�a�Y�l�a�^�_�O�S�b�T�U�M�I�Z�]�S�V�m�W���v�X�N�V�J�]�U�\�R�j�q�&�c�T�U�@�g�R�[�M�[�d�]�Y�F�X�B�N�U�^�]�i�A�b�]�c�f�V���U�_�X�S�I�n�W�W�c�a�]� �O�X�T�]�`�N�Y�b�Y�^�T�]�P�X�X�b�T�W�c�^�S�k�\�H�|�e�a�^�J�Y�T�[�W�[�l�*�]���Q�]�T�8�Z�r�K�P�^�f�]�2�*�c�F�p�k�_�[�J�]�a�Z�Q�1�K�c�O�j�`�c�M�c�@�`�Z�&�f�Q�g�U�M�Q�`�P�\�4�g�j�W�f�\�:�e�Y�[�S�B�Y�d�Y�Z�P�^�F�P�I�Y�]�W�Y�h���&�p�a�A�A�S�O�V�[�]�Z�E�]�Y�U�P�o�F�V�J�Z�c�j�G�3�e�X�a�^�\�{�X�.�`�I�P�a�1�M�e�d�[�L�f�@�c�k�U�H�L�M�O�V�X�T�:�d�_�X�i�W�j�X�^�n�`�X�H�S�A�c�^�U�[�j�p�X�R�b�n�n�U�D�C�W�f�N�V�Z�g�R�Z�V�Z�]�h�P�_�]�K�{�7�Y�U�V�a�Y�=�V�n�k�^�a�\�*�V�^�]�s�R�W�z�c�_�`�k�l�F�h�i�V�Z�^�b�a�J�^�g�K�?�X�U�h�O�P�^�Z�T�J�G�Z�s�h�S�L�c�q�F�d�Z�?�Z� �P�4�c�c�h�N�Q�Q���j�l�h�[�n�W�[�5�Q�f�_�R�i�d�Z�Y���`�C�[�8�O�W�S�d�O�_�W�q�W�S�d�A�Q�_�Z�f�_�]�J�c�G�^�N�U�h�l�J�g�T�X�^�J�g�M�S�Z�U�W�r�g�]�x�P�U�G�h���e�V�Y�c�]�t�]�\�@�g�L�j�i�P�\�[�`�_�U�Q�X�O�`�h�V�f�Q�S�X�b�l�q�\�V�P�f�k�q�_�N�S�M�c�@�X�X�W�\�^� �i�]�O�m�]�_�Z�Y�=�^�T�U�E�a�n�Z�o�F�l�^�Y�^�X�\�L�h�d�f�N�D�^�G�W�W�U�X�G�E�5�R�Z�_�k�w�b�`�Z�n�d�?�^�<�Y�I�M�R�]�S�j�V�W�D�>�b�t�\�o�;�_�K�Y�V�m�h�&�[�r�X�i�P�A�L�p�\�l�<�A�q�e�Q�]�b�T�S�J�\�k�l�7���e�L�Z�X�\�V�`�M�x�O�c�N�c�Z�l�U�P�a�c�Y�S�n�M�^�c�S�a�o�j�`�U�_�j�y�T�]�?�Y�e�m�B�[�^�Q�a�W�`�]�k�a�U�]�`�]���9�`�X�Z�Z�<�;�f�n�W�`�T�b�S�c�h�K�I�Y�d�`�D�S�\�S�b�{�=�g�p�E�[�,�b�^�S�Z�Q�T�Z�i�b�U�N�G�Y�b�k�c�9�c�j�C�X�W�j�b�T�V�X�^�6�R�E�\�F�\�X���]�y�f�L�Y�g�{�S�D�<�b�S�h�5�Y�Q�`�V�_�`�Q�P�W�^�c�p�`�a�H�W�a�a�K���[�C�\�o�P�M�s�W�N�[�X�c�V�c�V�O�]�N�U�Q�`�i�:�`�Z�[�\�T�T�U�2�K�r�f�X�S�W�T�R�\�R�F�[�Z�]�e�]�h�f�^�J�d�F�F�?�b�b�A�T�H�Q�Q�Y�U�l�l�Q�a�_�P�X�]�S�b�Y�@�^�q�X�m�h�\�b�[�V�S�P�m�T�d�U�<�8�V�b�]�I�I�W�`�P�S�_�@�a�H�N�U�k�8�X�T�T�s�j�[�K�Z�m�J�Y�Y�f�Y�@�^�]�=�[�e�\�T�_�N�_�e�_�_�T�k���X�e�<�<�b�^�G�h�M�X�P�H�Y���R�S�?�^�a�b�o�G�c�U�r�f���X�F�X�U�X�^�b�Z�d�V�j�p�H�]�i�Z�`�S�K�f�U�[�`�W���i�V�b�E�V�X�n�L�M�c�~�:�5�P�Y�l�`�]�h�N�\�t�r�R�w�b�n�d�d�h�j�B�S�V�]�k�d���U�k�J�U�U�_�_�>�[�c���b�o�\�`�^�b�S�v�b�b�g�d�d�o�z�Y�Z�G�_�f�^�d�Q�X�y�`�`�W�U�Y�a�P�U�^�^�a�h�^�V�O�a�d�]�^�\�X�U�Z�]���]�T�r�U�C�Q�s�m�W�e�Z���\�_�U�V�9�]�h�a�Z�e�Z�n�[�`��`�t�^�S�U�`�q�S�_�Z�?�E�U�`�a�]�X��S�c�M�]�`�+�R�|�[�q�W�U�q�\�m�q�I�M�]�m�X�_�U�i�A�K�T�J�U�G��r�S�M�g�T�a�Y�^�P�V�W�Z�j�R�Z�V�O�[�U�X�c�Z�Y�Q���T���T�c�I�Z�Z�P�b�[�a�c���Q�L�S�a�\�o�[�P�R�K�4�M�[�Q�_�|�z�@�n�I�I�F�Y���x�X�f�t�K�L�P�b�m�V�]�M�V�V�e�\�U�q�Z�N�]�M�Y�J�X�W�O�Q�P�=�a�Z�V�R�P�f�_�f�L�\�W�S�T�c�V�S�S�`�Z�v�Z�L�V�Y�Z�g�h�g�q�W�e���Q�h�J�k�[�^�^�O�a�q�^�O�h�[�J�4�g�T�b�u�=�Z�Y�G�`�S�5�\�Z�T�K�[�P�L�q�T�P�d�w�w�Y�S�q�k�i�o�R�Q�\�b�D�M�Y�%�`�O�]���]�S�k�w�_�S�X�S�U�U�R�E�j�Y�e�b�S�k�X�W�N�O�P�Y�p�L�f�[�l�O�A�h�k�i�G�f�c�P�\�m�d�k�W�d�r�`�N�W�J�K�]�b�[�S�O���^�S�d�]�b�X�S�^�J�E�\�i�X�]�\�W�S�Y�[�c�d�\�T�d�n�X�^���[���f�^�b�h�\�e�N�`�=�[�[���F�M�%�c�P�N�&�V�D�V�g���a�1�Q�b�,�O�^��`�V�y�`�h�h�6�W�Q�g�O�y�h�I�]�l�]�V�U�U�X�k�^�L�d�`�]�K�O�]�c�b�T�W�O�G�I�R�R�a�[�\�V�a�U�]�^�N�b�b�M�]�\�a�P�b�X�h�t�P�Z�W�S�R�_�S�W�[�\���S�[�T�P�I�z�d�N�\�c�N�U�\�Z�H�b�m�X�]�L�g�^�^�j�A�\�K�X�[�T�R�C�d�D�4�^�Z�<�_�W�g�a���_�V�B�[�B�[�P�X�U�A�X�S�?�Q�U�W�`�l�X�M�V�R�b�e�M�u�L�_�]�Q�H�e�S�5�z�t�e�s�Y�l�j�b�c�q�W�Z�]�Y�p�l�\�g�H�X�K�O�Y�a�e�Q�Z�w�b�M�`�b�Q�d�W�]�Z�U�c�8�;�M�Y�h�U�O�q�^�Y�D�d�c�\�:�e�B�\�W�X�V�f�O�d�\�J�Z�x�D�U�k�]�P�J�]�}�d�H�S�a�@�Z�m�\�=�?�U�y�Z�T�W�c�V�g�`�_�[�i�b�Q�\�c�b�Y�S�^�c�b�B�Z�j�{�a�^�X�Q�[���J�]�g�e�X�q�;�W�e�c�}�O�g�B�u�n�T�W�f�_�_�V�d�j�7�W�\�V�G�V�n�Z�_�X�`�r�^�e�q�g�V�V�b�b�t�G�V�T�f�m�k�j�Y�K�P�D�[�\�$�N�c�f�p�`�_�F�b�h�U�w�c�V�]�s�x�|�P�R�q�Y�q�b�a�S�I�Q�j�Z�R�g�M�P�^�a�[�s�i�l�T�[�X�^�L�d�T�9�c�e�n�M�N�`�h�J�]�d�e�Z�k�A�a�Z�k�P���f�\�a�]�s�W�d�a�a�\���]�L�\�W�d�]�W�Q�L�P�V�]���R�a�\�[�<�0�L�Z�L�c�]�k�u�P�d�k�]�Z�`�\�*�Y�K�\��X�T���V�G�W�d�s�^�b�M�Z�Y�|�K�\�U�O�z�h�^�X�e�R�W�g�f�X�_�W�?�[�2�X�;�Z�L�f�ÂG�D�J�\�V�X�c�e�Z�Y�P�L�R�`�^�b�Y�a�5�d�q�l�T�c�S�T�T�Y�I�m�;�U�\�d�b�g�n�^�\�Y�[�[�2�x�Z�[�W�U�E���V�T�m�K�B�a�[�c�Z�Q�Q�d�U�Y�m�W�`�Z�N�N�A�j�W�O�s�j�N�^�p�\�]�_�]�O�h�j�b�]�R�S�Z�c�W�O�m�U�f�d�y�]�b�g�h�P�j�d�s�G�r�i���e�i�_�[�q�H�b�X�e�r�b�B�a�m�I�]�_�F�c�i�d�g�c�>�-�O�W�Y�b�I�Z�g�R�T�\�Y�J�(�o�I�X�^�V�H�i�<�_�c�z��\�_�U�a�g�^�U�P�S�v�M�a�h�i���^�h�l�]�o�\�\�^�X���|� �Q�Z�_�e�[�a�j�_�t�X�\�.�b�a�q�h�M�a�\�d�c�\�2�_�3�a�n�[�[�4�n�R�V�P�b�S�|�[�]�\�h�i�h�Z�a�F�U�_�b�!�a�Y�p�`�]�X�\�e�L�Y�_�1�n�n�K�^�J�d�d�d�m�a�d�a���F�t�_�R�b�g�\�i�O�<�s�|�c�^�^�S�[�u�T�k�r�^�a�=�]�N�I�i�d�y�e�]�`�g�_�_�R�d�Y�Z�\�[�l�c�R�c�K�l�P�]�Y�[�m�]�]�`�S�W�n�b�v�R�Q�S�a�]�L�k�U�;�J�f�Z�[�a�s�s�n�d�R�u�]�O�Z�[��R�^�K�T�`�Y�X�K�e�X�@�[�;�_�U�n�O�\�g�J�u�W�b�K�}�\��_�U�X�U�U�Y�U�T�T�q�b�d�Y�j�i�L�G�O�g�Y�g�U�P�_�M�O�\�M�d�j�k�W�]�f�l�G���k�P�f�d�[�O���n�j�`�W�t�J�e�U�<�[�]�O�z�V�`�g�[�7�V�e�g�J�O�c�X�L�P�Z�B�X�U�_�j�W�W�T�O�W�L�_�[�Z�I�d�`�^�f�w�=�[�V�Q�n�l�[�4�J�c�X�o�Y�T�_�Z�d�g�^�F�X���a�X�M�T�Y�X�\�U�W�>�>�Y�O�h�R�H�V�l�O�[�Q�v�_�D�V�b���]�X�_�c�F�Z�m�`�V�[�k�^�O�f�]�`�`�^�]�:�]�K�l�`�a�Z�O�`�^�_�>�W�f�o�{�Z�[�a�Z�e�\�]�S�U�!�l�_�\�j�b�i�E�]�_�Z�P�i�S�N�V�d�]�m�b�r�T�@�U���\�V�R�Y�_���d�l�V�R�]�]�T�E���S�l�H�Q�a�o�o�Z�N�Q�b�\�x�T�T�)�_�a�V�[�X�a�{�b�n�c�O�R�{�a�K�j�I�Y�b�\���m�W�B�<�`�Y�e�M�Q�d�P�I�8�W�Z�Y�[���b�[�[�;�q�]�X�]�_�a�e�S�`�`�N�[�j�i�\�b�f�_�e�5�d�a�@�f�J�W�Y���T�F�R�k�g�P�d�T�^�X�E�a�g�Y�Y�Q�J�X�m�0�w�\�U�M�e�|�n�v�R�W�b�e�K�M�e�l�Z�H�_�R�_�g�Z�W�I�J�e�U�T�0�c�k�H�a�c�\�c�H�T�u�S�5�i�O�s�`�F�^�k�Z�]�^�E�~�i�T�G�_�U�^�f�`�S�N�V�^�Y�d�b�]�K�Z�f�f�X�U�_�Z�j�c�4�j�Z�_�n�`�T�o�i�`�q�i�]�b�Z�^�b�T�q�O�\�P�\�[�`�]�m�E�`�X�b�X�L�Z�K�_�]�X�/�X�P�u�K�e�\�]�:�c�U�^�S�Y�:�W�[�P�k�[�S�L�S�L�i�O�U�q�V�E�u�_�[�c�b�W�B�T�p�u�X�[�Y�^�r�X�W�k�a�<�;�d�P�b�d�\�L�^�@�X�B�3�L�[�J�_�]�U�]�J�Z�Z�V�U�|�x�R�^�b�W�_�_�_�\�^�Y�9�k�d�X�`�V���b�=�m�S�W�Z�Y�M�W�S�H�v�i�G�b�_�L�j���\�z�Q�h�S�\�U�s�a�L�f�z�`�e�^�X�]�O�T�U�a�U�W�`�i�\�T�Y�e�U�Z�e�K�E�e�[�]�r�P�U�b�`�^�W�Z�P�m�_�x�b�A�[�_�X�b�P�d�]�t�e�Z�\�Z�@�\�=�e�d�Z�a�[�c�_�Y�Z�M�R�a�J�b�W�V�;�?�e�A�Z�b���Y�Z�c���E�X�h�=�S�b�T�[�_�U�_�0�W�\�\�R�t�q�`�l�;�n�a�_�Y�f�p�a�[�`�c�O�9�\�S�W�7�b�O�`�b�S�S�c�_�N�Z�G�e�c�j�q�t�b�S�]�b�f�Y�c�\�q�S�q�y�L�b�P�R���a�R�\�e�D�Y�a�T�L�c�d��I�`�\�N�A�d�V�]�Y�\�O�S�>�a�V�H�U�^�]�C�g�P�f�Y�>�b�_�e�l�\�^�O�W�2�_�[�]�8�W�]�`�]�o�P�Q�V�]�m�8�a�]�k�o�]�e�W�{�i�^�=�d�M�e�E�k�G�f�_�Y�Q�^�S�e�^�P�K�t�:�c�c�[�t�R���/�T�A�W��U�h�L�[�`�Y�Y�j�J�W�b�h���_�H�U�Z�X�L�F�c�g�W�X�]�P�C�W�U�\�^�R�X�Y�M�[�b�C�`�l�j�s�O�Z�n�Z�W�_�B�b�I�T�d�j�r�^�I�T�^�Z�i�^�f�T�d�_�v�c�b�[�l�R�z�[�8�h�o�\�_���`�E�d�h�S�^�R�S�V�Y���Y�=�`�q�]�Y�]�Y�q�Y�L�Y�j�i�h�]�x�m�`�K�S�[�q�Y�`�[�T�b�a�Z�`�Q���g�P�`�Q�X�`�^�g�B�\�L�]�[�n�X�N�e�\�_�\�X�]�Z�V�}�Y�k�p�]�c�_�c�N�b�W�J�O�q�X���L�Y�]�Q�H�o�k�R�Y�J�^���`�C�X�O�Z�]�^�k�r�]�f���j�p�[�c�k�\�N�w�S�V�^�6�d�V�f�\�}�d�n�g�_�_�e�d�>�y�m�`�U�\�v�S�l�d�S�[�d�N�a�:�W�X�Y�\�a�d�j�[�Y�=�n�M�R�d�`�\�R�c�i�W�J�\�X�G�a�W�`�g�\�R�S�H�n�Z��c�L�G�r�S�z�g�Q�W�y�X�F�N�N�g�]�b�V�f�V�N�b�=�R�?�h�=�m�]�U�i�V�b�K�a�6�N�f�q�^�W�n�F�V�^�l�c�K���_�f�X�b�`�N�\�M�c�E�b�[�y�[�h�d�V�Q�a�K�Y�f�i�Z�[�}�X�U�h�V�b��g�O�l�[�L�n�S�T�^�`�a�]�k�]�D�`�w�2�t�0�l�a�X�_�e�f�O�p�_�g�q�`�X�c�`�Z�l�Y�V�N�X�a�_�H�l�`�]�v�_�[�Z�J�_�S�b�i���`�W�f�]�X�s�^�j�C�\�a���N�L�o�U�Z�u���u�g�o�d�I��U�]�g�5�Z�^�T�P�\�M�`�`�g�W�X�Z�P�e�j�a�\�r�Z�]�~�\�S�c�H�d�B�]�g�f�E�P�X�c�\�c�W�q�k�\�e�W�L�O�O�m�v�\�c�J�_�V�X�d�m�e�]���]�p�c�m�^�b�U�c�x���o��G�Z�]�V�x�y�`�\�F�^�b�-�^�]�\�W�U�V�a�f�^�Q�`�b�X�`�x�b�c�e�Y�h�U�`�q�p�\�g�D�X�I�r�Z�c�f�c�G�R�K��9�[�b�e�I�U�Y�g�V�Z�N�p�M�Z�E�q�S�[�K�O�U�f�i�g�b�S�s�S�I�b�d�f�P�{�V�f�[�e���g�W�X�a�V�i�d�w�h�[�J�L�[�T�g�]�A�W�x�J�Z�o�b�6�J�T�c�T�[�X�d�b�T�i�B�Q�T�T�i�Z�]�k�O�8�\���U�d�o�x�[�k�_�k�^�M�T�\�Z�]�k�`�r�W�l�]�Z�Q�_�\�]�^�D�]���]�Y�V�w�a�a�k�e�a�g�V�G�m�a�_�]�Z�V�|�^�@�g�e�4�Y�W�M�U�R�`�_�X�`�w�s�i�D�X�i�Z�T�y�n�q�a���Q�T�T�g�]�F�A�^�E�i�e�M�`�R�]�Y�i�@�Z�k�]�W�p�b�k�7�^�2�X�^�[�Y�e�=�s�Y�T�]�g���V�e�`�G�U�Z�X�[�j�]�a�{�N�[�r�T�a�Z�T�c�o�T�m�^�g�a�n�b�a�c�H�U�D�a�c�l�a�I�T�]�R�R�y�Y�[�f�F�[�[�c�o���f�Y�N�G�y�K�e�h�P�]�W�V�_�f�`�Z�n���c�v�V�d�]�k���]�y�j�J�b�_�n�\�U�T�_�g�Z�d�S�k�T�h�h�q�R�A�j�s�p�o�l�J�f�U�}�`�l�g�a�Q�[�d�[�Z�X�g�w�]�Z�U�i�d�`���>�\�n�i�b�d�a�f�L�D�_�w�X�b�N�]�[�C�b�U�K�f�^�t�M�F�^�]�e�b�U�l�:�Y�e���_�i�g�B�Y�X�H�a�[�6�c�n���U�Z�a�n�W�X�c�d�?�{�z�h�|�L�d�f�S�h�_�f�P�W�d�Y���V�f�c�Q�e���:�E�e�O�n�T�W�X�X�U�W�j�v�b�c�T�O���`�9�!�V�R�f�_�^�V�R�e�O�`�T�|�b�V�A���Z�d�G�l�]�]�W�'�i�_�e�Z�}�v�S�Y�h���S�_��f�b�i�A�W�L�o�u�r�V�g�c�[�K�_�V�V�`�`�Q�k�b�a�_�a�X�c�X�_�^�`�j�j�h�\�U�i�J�n�e�W�H�e�^�c�]�p�d�i��[�V�d�T�Y�a�q�`�p�Y�f�.�e�V�h�S�P�c�D�e�T�b�[���N�w�c�S�i�i�;�S�W�b�p�!�C�f�]�o�[�_�o�`�]�o�[�p�a�]�+�K�[�P�_�\�[�e�_�\�"�d�i�s�`�a�s�a�z�b�_�U�]�[�`�`�\�h�M�k�W�F�\�X�]��k�X�m�m�c�`�V�[�q�b�k�C�h�P�{�p�B�e�b�f�s�\�u�[�b�Y�b�^�g�B�_�U�Y�e�]�q�R�_�'�]�`�^�S�F�_�l�]�c�0�`�S�\�]�R�]�Q�W�[�g�N�d�X�X���M�J�`�]�X�e�p�a�f�P�M�U�r�d�V�Y�\�D�c�^�J�^�^�U�b�Z�^�H�c�]�]�V�d�S�P�e�[� +�q�b�e�^�_�Z�c�[�H�M�e�v�U�a�h�i�c�u�K�}�b�[�\���g�\�V�i�H�_�R���W�d�o�i�4�F�p�\�U�a�Y�m�p�Y�2�Z�N�6�a�Z�Y�J�M�j�]�]�N�Y�>�Y�B�O�X�_�S�_�[�Y�S�j�i�P�b�e�c�[�J�[�p�L�`�f�i��i�a�o�c�`�r�`�6�R�Z�O�H�m�U���F�X�e�[�W�W�c�\�X�l�W�d�W�R�X�[�N�h�Y�A�S�w�X�f�d�g�Y�Y�=�k�^�K�S�W�X�a��a�\�Y�a�X�W�]�U�Y�_�_�5�b�Q�V�]�`�_�Q�`�b�`�c�C�F�]�p�_�^�k�Z�@�X�b�s�_�,�c�g�M�b�F�X�b�f�h�d�b�X�M�Z�]�e�\�?�T�K�X�X�n�q���[�Y�f�d�^�a�[�w�^�k�P�V�M�[���l�_�T�d�b�X�X�]�a�H�A�^�f�i�g�P�T�e�B�e�]���b�`�e�a�r�W�Q�c�o�d�g� �j�e�X�b�l�m�z�c�_�v�b���`�_�d�h�\�h�t�]�2�^�f�^�t�r�Z�[�a�i�Y�h�k�V�]�Q�S�{�j�F�T�X�R�R�u�o�g�J�c�f�Q�`�j�z�W�R�Q�[���\�c�V�W�^�2�a�_�e�e�a�d�b�j�_�a�U�Y�D�W�U�=�N�e�;�b�S�P�^�]�X�l�{�R�R�a�U�]�Y�X�U�c�U�W�e�I�W�\�J�j�`�e�]��� �i�e�N�f�\�d�_�`�J�Z�a�`�f�X�`�h�G�a�e�f�_�]�Q�`�X�g�^�a�d�S�`�a�S�\�j�j�D�s�_�`�U�W�6�]�Y�X�b�W�`�(�b�d�\�c�m�V�L�h�e�S�f��X�S�P�V�R�h�V�d�z�Q�_�S�i�V�K�_�n�a�b�\�[�L�f�_�Y�?�f�`�U�c�d�`�m�d�W�^�^�Y�_�=�c�_�f�J�o�y�X�Y�o�o�K�_�e�e�]�r�\�e�`�^�|�+�i�\�d�X�l�f�m�}�e�d�T�\�D�`�a�E�^�b�h�\�Y�j�R�]�W�F�@�[�V�U�b�M�L�i�a�\�[�a����a�d�G�Z�]�S�j�\�\�[�w�L�u�Z�]�_�U�Z�M�r�f�f�X�]�c�g�d�h�[�\�[�R�`�X�e�q�d�V�V�W�b�a�i�f�e�_�Z�X�u�b�`�G�Y�V�a�r�^�[�e�w���T�h�X�m�e�a�l�`�\�Q�Y�a�T�g�\�h�R�n�c�X�W�V�M�n�Y�t�`�Z�i�b�d�X�X�g���]�s�Q�f�b�K�\�]�]�J�S�a�e�U�b�t�o�^�^�V�f�O�a�a�h�[�S��T�T�b�r�_�j�O�V�a�l��t�_�f�T�f�~�Q�C�a�]�n�K�>�H�e�\�e�\�Q�X�r�e�Z�k�?�]�_�m�c�V�`�F�R�U�a�Y�T�U�a�d�f�n�e�`�j�e�^�k�I�r�c�E�K�D�h�a�h�_�a�U�m�A�O�^�V�q�v�J�g�d�N�M�[�c�d�W�C�k�W�Y�L�X�h�a�b�^�I�h�y�`�H�]�C�U�X�k�e�Z�]�V�t�Y�U�n�[�d�j�M�[�k�m�d�e�\�b�y�U�]�I�`�_�v�m��_�R���Z�n�e�P�I�^�J�Y�c�d�_�S�`�@�`�c�r�a�|�Y�c�L�W�{�`�^�W�`�R�W�\�a�X�Z�g�Y���^�c�o�=�P�a�s�I�h�V�Z�_�\�Z�\�C�f�c�n�_�^�Z�H���^�]�g�b�(�m�F�b�]�o�w�e�I�V�M�_�d�I�e�k�^�[�L�Q�y�Z�S�_�g�V�n�s�`�Y�f�i���\�j�q�Z�d�Q�a�;�\�[�b�c�N�W�h�_�q�X�P�R�m�^�_�e�U�U�j��z�[�^�c�V�O�Y�T�h�X�[�t�T�S�p�R�k�9�Y�^�d�[�h���T�e�e�s�m�t�b�b�Z�Z�`�f�b�i�P�\�M�d�L�l�k�V�l�^�w�i�U�W�Q�`�\�V�T�l�s�Z�V�����c�a�]���[�K�9���Y�b���P�Z�X�\�[�f�c�e�M�Q�l�[���Z�R�c�h�j�`�\�b�}�e�r�|�Z�V�D�J�h�M�d�h�V�[�Z�W�Q�`�X�R�G�l�V�Q�~�e�g�_�G�\�b�_�X�v�g�^�`�G�c�V�[�W�Z�Q�T�n�b�b�\�Y�Z�7�B�j�\�]�Q�`�_�}�U�a�X�y�i���K�^�6�f�^�Z�Y�o�^�p�u�`�W�n�e�W�b�^�N�b�X�N�Z�u�S�V�R�[�q�f�x�\�U�Z�`�\�L�E���j�p�[�e�T�l�f�e�����`�N�X�f�[�r�I�f�W�_�`�d�j�h�S�d�^�g�d�{�m�_�U�O�a�Z�5�O�d�\���Y�a�h�[�@�`�g�I�?�o�d�e�v�h�u�d�c�U�h�K�"�`�b�`�t�Y�T�[�e�u�[�E�f�v���u�c�o�W�_�W�I�f�V�^�6�=�N�`�Z�]�L�j�f�d�^�`�X�F�z�I�`�g�Y�`�a�O���_�P�|�b�2�g�Z�d�V�`�W�\�j�I�U�_�\�N�s�T�e�k�_�R�\�^���b�X�t�]�O�b�`�V�U�_�t���V�l�g�;�R�j�d�J�V�]�_�f�m�[�^�W�_�P�b�Z�Z�X�v�Z�S�k�]�a�q�a���^���d�Z�a�v�.�p�J�g�R�T�S�w�b�`�\�i�S�a�`�W�j�j�A�`�`�J�_�i�i�Z�W�~�_�a�\�j�c�Z�\�Y�N�`�c���^�j�\�X�\�[�]�\�`�V�Z�Y�`�S�b�Z�b�^�a�c�V�Q�e�g�j�[�F�[�_�J�Q�b�U�b�e�M�d�c�a�c�H�h�h�P�_�_�f�W�d�d�Q�G�\�a�S�d�L�[�j���`�g�P���Y�D�j�^�v�5�M�T�h�Y���y�c�s�l�v�N�c�a�p�_�[���i�g�n�Y�]�c�Q�B�R�b�g�a�i�\�A�e�b�p�M�T�T�d�y�X�b�}�n�a�_�g�f�l�|�j�N�R�p�d�H�{�i�[�e�H�Q���a�_�`�w�Z�_�Y�h�b�Y�]�_�[�T�r� �j�W�[�u�c�h�j�`�c�e�Y���R�U�_�b�L�H�]�^�d�b�:�a��W�[�l�Z�V�e�i�X�n�g�e�Y�V�`�\�f�Z�m�G�i�]�`�.�T�x�X�M�c�Y�X�d�`�m�`�^�U�a�T�?�k�]�c�i�Y�i�Q�1�w�f�e�W�W�h�\�Z�\�e�U�s�]�X�`�o�+�I�a�G�T�^�I�l�Y�d�_�]�h�x�f�c�[�]�_�l�]�f�a�e�q�Z�h�w�m�g�p�O�_�Z�Y�g�u�b�{�c�N�l�d�V�W�_�Y�]�c�f�f�N�\�j�g�a�i�V�g�q�]�t�X�d�c�u�^�b�e�L�a�d�Z�C�u�i�u�\�a�X�O�N�Q�g�Z�Y�n�R�f�M�g�b�^�b�l�a�T�\�[���z�t�k�\�i�s�[�[�b�h�g�k�d�G�X�C�c�U�t�P�`�Q�Y�K�T�p�[�W�g�?�a�Z�h�c�`�]�a�v�l�S�l�`�`�_�e�]�Y�b�E�j�m�y�m�g�b�Z�\�_�Z�l�X�n�_�o�[�j�X�\�Z�W�y�V�p�\�K�&�?�^�f�p�u�Z�f�e�Y�Z�Z�U�n�E�^�n�h�e�e�^�P�p�l�d�\�7�\�_�g�T�m�^�V�D�X�g�^�N�n�B�f�t�`�\�a�^�a�j�m�r�O�Y�c�T�|�[�S�M�j�v�`�T�c�X�\�X�]�\�f�e�L�-�a�_�e�h�`�]�_�`�x�e�c�W�c�L�K�o�a�m�j�]�p�{�v�h�\�_�~�G�]�X�\�Z�e�>�^�U�^�S�{�U�k�d�`�f�[�j�=�Y�f�j�^�-�`�l�T�`�J�K�U�X�[�`�d�f�u�a�w�K�S�h�c�g�p�t���b�.�b�Z�a�X���o�\�m�S�n�a�T�S�R���t�H�d�e�u�c�^�\�;�Z�e�K�=�_�Y�S�S�W�`�n�\�]�^�o�h�W�T�a�c�P�_�S���X�e�T�F�l�\�]�I�Z�W�f�Z�_�f�r���i�d�`�g�`�r�a�k�^�J�^�f�Q�r�b�S�|�h�R�d�u�b�R�n�-�l�@�K�T�i�W�S�r�f�a�N�W� �[�U�o�g�R�n�U�b�Y�c�i�0�R�a�<�Y�f���n�g�]�]�X���g�K�\�]�f�T�r�M�\��\��R�`�j�W�O�e�a�i�]�[�[�i�S�W�k�j�W�g�k�c�V�q�g�T�Y�L�i�_�R�g�[�`�l�T�Y���k���f�n�p�S�R�_�_�F�`�N�S�i�l�i�c�`�_���_�g�_�\�k�Z�g�w�Z�`�A�f�l�X�S�b�R�f�i�{��`�s�W�m�V�P�]�]�v�b�^���n�^�j�q�q�y�s�]�I�`�^�b�����^�]�v�a�b�b�j�d�^�k�Y�T�k�j�U�q�g�U�{�e�^�W�q�U�N�r�b�[�Y�[�h�q�e�M�f���A�c�i�f�d�u�T�s�a�g�Z�Z�j�b�k�V�d�d�e�]�Y�_���e���o�_���W�d�h�Z�J�]�G�j�T�b�T�c���i�b�[�g�o�a�Y�_�o�`�X�]�_�Q�r�e�c�\�W�r�|�c�W�n�a�e�e�j�b�k�^�F���a�Z�l�b�P�l�`�M�E�c�Z���Z�m�P�P�m�g�U�I�]�T�[�\�w�t�m�\�N�n�^�5�|�n�S�e�d�[�j�W�z�e�J�W�U�a�Z�R�q��D�a�s�h�i�l�?�c�Z�f�\�x���m�y�V�a�^�J�_�p�N�\�V�\�_�i�B�g�E�Q�Z�d�d�O�]�j�Z�d�>�\�\�V�c�f�[�Y�q�d�Q�8�U�Y�_�c�Q�y�Z�>�V�`�T�K�1�h�W�N�Z��e�B���]�5�p�g�l�]�R�`�[�N�l�b�a�Y�W�W�-�i�d�^�G�g�_���g�_�c�u�\�_�`�l�M�R�a�\�F�j�_�S�f�a�p�Y�a�P�c�\�P���`�d�[��R�p�e�w�[�^�w�l�K�b�N�o�L�c�Z�c���V�Z�X�V�^�x�Z�i�Z�L�L�k�r�U�Y�U�W�t�v�\�c�Y�q�H�^�S�q�[�]�R�r�Z�7�Z�T�i�i���m�b�`�Z�i�z�<�i�u�R�o�X�d�`�e�o�n�r�y�p�_�}�R�i�L�W�c�i�d�`�c�Z�g���[�l�_�Z�j�d��`�y�9�g�\�f�m�h�P�i�o�\�x�F�d�f�J�R�G�c�]�d�Q�j�f�Z�_�m�O�i�h�u�g�Y�@�c�b���e�U�l�[���i�i�X�c�R�l�H�j�Q�T�{�>�m�W�[�j�U�F�]�m�c�u�^�V�j�b�D�T�[�`�m�_�n�i�Y�Z�d�c�q�p�c�g�^�E�?�W�h�u�]�X�T�J�J�i�^�k�Z�K�l�X�H�W�S�j�c�a�s�`�X�]�V�i�^�]�q�F�V�j�y�p�l�e�d�j�T�v�X�R�J�i�h�o�b�_�c�O�]�m�Y�s�f�n�Z�7�_�i�a�e�O�S�[�\�V�|�r�L�a�e�s�e�b�c�=�X�l�j�H�P�`�~�O�c�i�f�f�s�H�\�j�{�M�a�\�f�X�^�[�g�X�h�g�a�b�T�j�n�_�W�_�x���\�N�n�[�[�S�Q�c�t�j�i�]�B�^�Z�Y�_�Z�e�d�Q�{�^�[�_���b�^�C�_�`�w�]�h�d�a�e�d�[�_�g�R�a�d�|�M�b�d�c�Y�P�Y�m�i�^�j�f�_�i�q�h�`�_�c�]�D�_�f�e�e�^�?�g�r�u�a�c�V���h�B�^�j�a�c�k�T�_�p�\�_�a�R�T�[�o�S�c�i�Y�[�`���R���f�Y���[�\�O�]��R�_�9�Y�e�\�d�K�V�d�`�2�b�\�s�]�d�W�V�`�h�W�k�7�k�e���e�~�U�`�I�^�`�a�Z���l�r�G�S�N�r�_�P�_�_�k�d�{�[�O�U�f���U�H�g�g�J�e�@�P�\�]�c�d�e�?�V�q�c�]�h��O�0�\�j�k�[�V�e���x�d�V�`�M�b�\�g�P�c�j�X�`�d�d�h���a�c�j�P�Z�a�X�j�a�C�W�`�h�c�f�R�a�a�a�w�c�E�Q�o�=�D�j�g�c�l�t�i�d�d�l�W�d��e�p�X�G�k�P�Y�b�L�h�a�8�Z�R�S�f�\�]�W�5�^�W�V�d�5�G�f�H�L�X�m�W�{�L�i�d�V�e�R�g�Q�~�`���r�X�Y�g���_�i�f�E�q�`�Y�E�_�_�d�P�m�g�W�e�[�p�N�g�Q�T�k�g�u�a�f�a�[�Q�g�p�M�z�i�]���`�Q�h�a�P�[���v�`�f�b�_�T�f�i�Q�i�Z�\�`�c�_�z���\�V�e�Z�\�^�C�d�b�g�a�^�]�q�h�a�m���[�i�t�j�X�T�W�d�]�g�X�]�U�d�^�f�]�?�_�h�`�6�[�V�0�^�_�c�Y�c�a�~�Z�e�U�l�\�<�[�]�e�E�Y�s�`�j��S�g�M�a�R�c�g�^�e�m�c�]�~�d�j�F�\�e�b�^�g�`�f�W���M�S�b�q�a�a�^�l�e�?�e�m�p�F�^�[�<�b�^�n�f�W�b����_�f�p�_�d�b�_�c�V�_�k�j�_�l�`�[�R�Z�1�^�o�d�X�`�P�p�Y�s�f�a�C�d�`�g�T�k�b�\�Z�b�U�g�S�a�e�_�K�|� �d�o�S���C�i�`�q�T�p�`�[�q�r�[�y�\�l�c�R�d�g�b�Y�S�A�c�O�I���l�j�f�_�Z�g�s���Y�a�c�V�f�l�j�m�Z�m�]���X�_�W�]�[�j�_�e�e�d�d�g���`�d�d�h�g�V�V�^�a�L�_�l�x�c�Z�9�i�L�O�g�^�y�n�a�a�w�r�Q�P�Z�k�c�n�[�h�e�g�U�R�k�X�c�e�d�\�\�v�e�g�J��b�k�c���c�`�i�\�^�a�g�]�d�X�b�Z�a�x�s�l�m�e�h�S���c�b�n�X�^�R�J�_�|�n�S�F�R�q�n�]�Z�d�^�\�d�b�a�g�)�I�b�b�m�d�b�p�f�V�R�}�{��Q�e�y�X�k�v�d�l�j�e�@�E�Z�r�z�a�^�Q�`�j�a�Y���P�c�^�^�R�d�a�i�l�^�\�T���u�m�g�_�k�_�i�p�j�o�e�s�_�Z�`�`�]�l�`�i�C�]�d�i�]�s���`�W�[�a�f�e�]�{�f� �h�k�t�V�j�x�f�n�z�e�T�i�h�\���s�|�m�d�c�l�U�j�Z�c�b���c�u�c�q�^�[�f�n�[�g�d�[�U�|���]�U�`�\�Y�\�L�^�U��c�`�m�z�i�a�f�Q�^�f�O�k�b�F�X�s�J�C�]�Y�b�p�e�v�)�f�t�`�a�g�q�a�^�o�^�R�u�p�_�S�m�\�`�Z�[�h�e�t�����]�P�P�e�n�a�a�K�}�N�H�|�]�e�V�`�o�Z�s�r�Y�m�^�3�\�Z�`�[�S�[���i�K�W�n�J�E�g�U�^�u�e�a�o�[�l�c�L�i�v�p�S�^�e�g�Y�O�q�Y�W�c�@�T�`�g�f�f�o�g�X�f�k�c�g�U�g�g�h�d�a�Y�]�[�f�g��k�]�`�l�M�f�m�f�\�2�a�[�t�`�]�W�b�}�{�_�d�p�h�S�C�i�b�&�t�_�s�a�[�L�^�W�~�l�d���r�Z�k�J�k�V�Q�W�J�Z�U�n�g�k�^�g�]�P�M�i�~�_�a���X�[�e�`�B�f�b�>�l�a�r�Y�`�u�p�_�R�g�I�e�`�W�u�Z�`�j�V�t�J�F�o�q�e�j�h�O�X�T�v�h�>�B�h�T�_�h�r�^��D�^�h�]�n�H�g�\�Y�I�s�Z�X�~�e�N�e�u�h���_�q�d�]�k�f�Z�^�q�d�R�b�Y�b�Y�[�d�P�c�n�i�a�o�j�_���m�\�W�^�M�`�r�V�M�C�c�f�B�k�j���L�L�Z�[�e�p�Y�d�f�J�_�j���e�S�E�N�s�^�Y�_���`�n�?�P�f�\�Z�n�R�K�Z�i�\�]�g�H�^���b�b�n�t�_�?�Y�f�d�X�p�Q�a�`�k�Y�T�e�j�g�]�r�U�f�S�a�^�V�d�^�g�\�\�\�z�Z�����^�[�o�a�I�b�q�z�x�_�Q�]�t�Z�r�f��n�s�\�e�b�j���k���_�}�d�]�i�j�z�k�X�s�`�r���e�d�N�e�o�m�H�`�d�0�[�l�f�r�Y�U�d�^�i�\�`�e�-�P�i�c�M�_�Q�h�F�E�t�^�r�v�W�O�l�Y�i�c�T�a�h�\�}�r�K�l�a�e�p�c�b�s�p���r�`�m�c�f�K�Q�c�g�\�b�}�`�d�a�z�H�d�k�e�^���s�`�a�I�b�e�r�>�C�W�~�X�E�Y�i�{�H�l�k�h�m�i�)�\�r�c�a�d�,�C�m�r�`�Y�h�_�d�j�r�g�m�^�H�P�_�`�k�_�n�^�e�j�X�i���7�e���_�_�o�x�g�V�c�T�b�:�|�`�b�T�[�g�W�f�e�U�e�Z�S�t�d�q�X�~�I���R�H���O�y�H�_�n�m�n�Q�e�t�^�b�a�]�]�p�q�S�y�a�a�A�g�a�Z�b�o�g�\�c�g�a�V�]�o�`�m�|�<�-�\�^�V�_�n�V�l�b�o�d�`���R�`�f�m�Z�g�\�k�d�j�h�q�N���*�o�T�c�n�R�b���X�`�p�j�k�e�b�X�k�\�^���`�i�X�T�j�x�>�u�l�E�m�g�g�]���F�s�g�b�e�i�k�~�]�f�z�c�l�P�`�i�u�e�j�[�k�f�c�[��V�[�_�q�^�s�h�Y�l�^�]�d�~�U�O�h�g�i�c�j�Y�B�\�h�[�p�b�f�d�M�����f�[�I�p�V�]�^�Y�D�o�H��`�r�k�g�l�M�m�W�R�m�b�c�T�v�R�`�c�f�j�H�c�k�Y�i�_�f��a�n�|�j�h���H�a�\�h�k�s�j�T�c�X����d�r�b�k�i�u�C�j�n�P�Y�o�g���T�p�g�R�h���j�y�f�c�J�r���f�U�v�i�b�W�c�i�t�^���c�i�T�j�d�j�h�o�^�a�f�]�g�R�_�d�c�a�[�����j�l�j�d�b�_�[�X�u�i�C�p�f�t�b�o�f�e�]�}�h���_�\�`�s���m�^�_�z�b�`�_�K�u�U�b�W�*�e�P�q�X�i�e�\�r�M�_�`�C�F�t�b�v�b�<�q�f�Y�p�P�����s�`�n�h�b�b�[�c�j�U�[�-�d�y�d�i�l�q�_�^�a�_�j�Z�i�Y���g�Z�X�N�V�d�e�W�`�l�\���_���R�f�q�]�p�R�~�s�`���[�-�o�o�k�b�t�J�m�]�Z�W�k�`�^�`�e�~�_�H�c�i�^�k�[�>�c�M�J�_�_�U�e�u�e�u�X�s�w�l�]�k�j�k�t�W�j�X�j�V���b�^�Z�b�e�c�n�]�O�Z�q�+�g�R�e�r�S�^�e�P�j�=�h���u�m�q�U�H�e�X�l�_�Z�U��D�_�H�m���j�V�[�]�m�[�|�N�j�c�c�a�d�`�t�h�]�l�k�P�B�Z�p�R�Z�f�c�w���e�_���W�c�q�X�i�e�h�k�h�_�k�o�]�c�k�m�P�|�l�O�R�U�_�2�D�p�d�`�a�t���z�c�_�X�d�j���f� �p�l�a�y�r�Z�k�Z�j�O�r�2�b�b�?�i�h�l�[�d�Q�m�c�g�c�b�k�W�j�Z�{�n�x�e�U�p�U�c�)�s�f�j�a�f�[�L�T�c�T�e�g�v�n�u�h�l�Y�f�e�r�q�K�m���l�h�l�h�h�Z�`�r�p�,�b�c�Y�X�k�s�k�z�g�e�n�q�V�a�d�c�i�`�]�h�q�a�h�Z�I�|�A�~�g�m�`�x�Z�c�|�f�h�c�`�_�d�f�G�g�`�d�h�k�m�`�g�N�g�a���h�P�]�h�V�~�b�\�s�M�J���b�S�[�h�t�l�9�]���F�l�j�^�g�d�t�g�Z�b���~�7�e�|�i�\�j�k�l�c�w��O�\�U�e�a�~�]�g�h�b�_�b�h�J�_�[�k�f�c�\�n�q�Z�k�.�\�U�y�d�n���W�i�l�i�\�p�i�l���f�e�f�T�f�o�]�x�T�g�e�`�Q�r�o�i�Z�X�^�r�l��o�[�[�B���l�p�x�S�Y�h�o�g�f�b�j�@�i�^�W�Y�W�Z�b�g�G���p�b�H�o��k�^�t���\�v�t�b�`�^�e���Y�k�^�i�I�Z�m�t�o�h�R�c�c�j�b�d�n�f�Y�V�J�z�T�i�\�Y�V�l�H�n�j�d�y�f���J�g�h�d�A�n�t�V�>���m�`�y�b�p���S�g�U�e�|���d�f�z�K�}�_�a�x�b�g�^�l�a�l�r�\�a�X�k�g�8�X�d�B�i�N�g�e�l�_�i�j�c�f�z�i�R���P�V�g�`�o�f�M�e���{�w��c�K�v�c�h�p�a�b�m�u�j���k�c�z�d�^�o�p�]�h�]�_�z�l�D�R�t�]�m�y�j�t�d�g�w�f�V�e�q�j�g�e�^�o�l�q�u�R�l�|�d�u�j�e�j�m�q�o�v�U�f�i���\���b�o�q���X�g�b�o�p�m�c�s�Z�y�x�n�c�v�~�c�a�g�\�w�q�g�[���v�t�d�x�o�m�k�q�g�k�X�\�i�l�g�h���^�X���m�r�`�L�P�_�N�g�a�w�b�S�m���o�k�r�x�]�p�m�x�h�_�b�k�S�f�a�]�d�e�^�t�d�l�0�i�m�g�j�n��^�d�[�p�m���m�q�s�l���o�a�j�l�h�g�p�[�g�^�m�_�`�e�^�j���]���A�s�_�j�c�W�W�~�`�o�i�d�^�l�a�c�q�h�w�\�t�o��H�k�U�c�O�b�m�n�_�f�_�i�l�p�e�d�e�d�]�p�s�a�e���V�k�f�a�d�]�\�i�`�o�O�n�e�Y�d�a�[� �`���_�M�d�g�i�x�s�w�k�l�X�_�i�j�}�o�X�f�c�h�o�r�?�]�[���x�_�k�p�l�k�U�c�z�n�^���p���b�^�\�b�n�f�f�I�p�i�h�}�a�f�b�T�O�c�g�m�k�{�j�j�c�o�e�X�r�f�}�z�b�c�c�l�`��]���f�j�_�l�b�h�w��_�M�j�o�b�c�p�\�����Y�c�|�k�q�e�v�N�q�[�@�b�`�k�o�Q�Z�h�i�g�b�g�e�C�b�U�g�s�d�Y�g�U�Y�_�p�H���f�c�\�_�z�k�~�p�_�Y�N�V�a���f�`�p�d�\�g�b�h�g�J�����]�h�j�p�f�r�[���q�j�m�����[�X�s�|�q�K�g�t�g�h�h�|�g�k�n�l�p�q�p�j�f�m�r���Z�t�o�q�c�h�c�i�c�k�_�g�P�b�n�h���b�y�s���d�p�r�w�q�h�a�_�[�j�~�e�m�~�~�x���q�u�>�l�o�s�q�e�s�?�J�g�w���u�F�j�y�]�o�z�q�r�v�N�X�h�X�o�q�g�r�v�n�p�{���n�B�t�|�y���g�r�p�q�z�n�d�o�j�w�f�[�i�c�q�f�y�j�z�o�h�k�x�r�m�z�w�|�y�b�i�s�g�h�o�b�n�q�t���a�p���^�t�l�e�a�m�{�q�k�y�l���v�s�w���s�c�q�z�n�m���v�I�q�]�k�k�o�r���q���c��n�����y�����������������������v�i�����������{�������{�����������������������������������������������������������������������������z�����������������������~�������������������������������{�������������������������������������������������������������~�����|���x���������������������������������������o���}������������������������������������������������\�������������������������������������z���������} \ No newline at end of file From 3f66c40aa65544488b17451a54891618674b8515 Mon Sep 17 00:00:00 2001 From: Harlan Date: Thu, 16 Jan 2025 13:32:10 -0800 Subject: [PATCH 07/11] version bump --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 53dca6f..5456db9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ authors = [ ] # A list of the package authors edition = "2021" name = "astrors-fork" -version = "0.1.10" +version = "0.1.11" license = "BSD-3-Clause" # The license your package is under repository = "https://github.com/schwarzam/astrors" From 08d568de2d6c74ac50e2d6819596f4dc9d6b2627 Mon Sep 17 00:00:00 2001 From: Harlan Date: Thu, 16 Jan 2025 15:36:34 -0800 Subject: [PATCH 08/11] Fixes --- Cargo.toml | 2 +- src/io/hdus/image/image.rs | 21 ++++----------------- src/io/hdus/image/utils.rs | 8 -------- 3 files changed, 5 insertions(+), 26 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5456db9..2ce14d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ authors = [ ] # A list of the package authors edition = "2021" name = "astrors-fork" -version = "0.1.11" +version = "0.1.12" license = "BSD-3-Clause" # The license your package is under repository = "https://github.com/schwarzam/astrors" diff --git a/src/io/hdus/image/image.rs b/src/io/hdus/image/image.rs index 6c692b5..1d925b1 100644 --- a/src/io/hdus/image/image.rs +++ b/src/io/hdus/image/image.rs @@ -9,7 +9,7 @@ use std::io::{BufWriter, Write}; use crate::io::hdus::image::utils::{ get_shape, nbytes_from_bitpix, pre_bytes_to_f32_vec, pre_bytes_to_f64_vec, - pre_bytes_to_i32_vec, pre_bytes_to_u16_vec, pre_bytes_to_u8_vec, vec_to_ndarray, + pre_bytes_to_i16_vec, pre_bytes_to_i32_vec, pre_bytes_to_u8_vec, vec_to_ndarray, }; use ndarray::ArrayD; use rayon::prelude::*; @@ -17,7 +17,6 @@ use rayon::prelude::*; pub enum ImageData { U8(ArrayD), I16(ArrayD), - U16(ArrayD), I32(ArrayD), F32(ArrayD), F64(ArrayD), @@ -32,7 +31,6 @@ impl ImageData { pub fn get_bitpix(&self) -> i32 { match self { ImageData::U8(_) => 8, - ImageData::U16(_) => 16, ImageData::I16(_) => 16, ImageData::I32(_) => 32, ImageData::F32(_) => -32, @@ -44,7 +42,6 @@ impl ImageData { pub fn get_dtype(&self) -> String { match self { ImageData::U8(_) => String::from("uint8"), - ImageData::U16(_) => String::from("uint16"), ImageData::I16(_) => String::from("int16"), ImageData::I32(_) => String::from("int32"), ImageData::F32(_) => String::from("float32"), @@ -56,7 +53,6 @@ impl ImageData { pub fn get_shape(&self) -> Vec { match self { ImageData::U8(array) => array.shape().to_vec(), - ImageData::U16(array) => array.shape().to_vec(), ImageData::I16(array) => array.shape().to_vec(), ImageData::I32(array) => array.shape().to_vec(), ImageData::F32(array) => array.shape().to_vec(), @@ -78,9 +74,6 @@ impl fmt::Debug for ImageData { ImageData::U8(array) => { write!(f, "FitsData::U8({:?})", array) } - ImageData::U16(array) => { - write!(f, "FitsData::U16({:?})", array) - } ImageData::I16(array) => { write!(f, "FitsData::I16({:?})", array) } @@ -150,10 +143,10 @@ impl ImageParser { Ok(data) } 16 => { - let mut vect: Vec = vec![0; databuf.len() / 2]; - pre_bytes_to_u16_vec(&databuf, &mut vect); + let mut vect: Vec = vec![0; databuf.len() / 2]; + pre_bytes_to_i16_vec(&databuf, &mut vect); let ndarray = vec_to_ndarray(vect, shape); - let data = ImageData::U16(ndarray); + let data = ImageData::I16(ndarray); Ok(data) } 32 => { @@ -193,12 +186,6 @@ impl ImageParser { .flat_map(|&item| item.to_be_bytes().to_vec()) .collect::>() } - ImageData::U16(array) => { - let vect = array.clone().into_raw_vec(); - vect.par_iter() - .flat_map(|&item| item.to_be_bytes().to_vec()) - .collect::>() - } ImageData::I16(array) => { let vect = array.clone().into_raw_vec(); vect.par_iter() diff --git a/src/io/hdus/image/utils.rs b/src/io/hdus/image/utils.rs index bc1f4b0..e32956d 100644 --- a/src/io/hdus/image/utils.rs +++ b/src/io/hdus/image/utils.rs @@ -76,14 +76,6 @@ pub fn pre_bytes_to_u8_vec(bytes: &Vec, output: &mut Vec) { }); } -pub fn pre_bytes_to_u16_vec(bytes: &Vec, output: &mut Vec) { - assert!(output.len() * 2 <= bytes.len()); - output.par_iter_mut().enumerate().for_each(|(i, item)| { - let chunk = &bytes[i * 2..(i + 1) * 2]; - *item = u16::from_be_bytes([chunk[0], chunk[1]]); - }); -} - pub fn pre_bytes_to_i16_vec(bytes: &Vec, output: &mut Vec) { assert!(output.len() * 2 <= bytes.len()); output.par_iter_mut().enumerate().for_each(|(i, item)| { From b194487e994cd99e489690884d7aecc79b5b65e7 Mon Sep 17 00:00:00 2001 From: Harlan D Heilman <73567020+HarlanHeilman@users.noreply.github.com> Date: Fri, 17 Jan 2025 21:15:37 -0800 Subject: [PATCH 09/11] polars bump --- Cargo.toml | 4 +- src/io/hdus/bintable/bintable.rs | 33 +++++------ src/io/hdus/bintable/buffer.rs | 13 +++-- src/io/hdus/table/buffer.rs | 7 ++- src/io/hdus/table/table.rs | 26 ++++----- src/io/header/card.rs | 94 ++++++++++++++++++++------------ 6 files changed, 100 insertions(+), 77 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2ce14d9..07bd84c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ authors = [ ] # A list of the package authors edition = "2021" name = "astrors-fork" -version = "0.1.12" +version = "0.1.13" license = "BSD-3-Clause" # The license your package is under repository = "https://github.com/schwarzam/astrors" @@ -22,7 +22,7 @@ include = ["/src", "LICENSE", "README.md"] [dependencies] ndarray = "0.15.6" num_cpus = "1.0" -polars = {version = "0.41.0", features = ["dtype-u8", "dtype-i8", "dtype-i16"]} +polars = {version = "0.45.0", features = ["dtype-u8", "dtype-i8", "dtype-i16"]} rand = "0.8.5" rayon = "1.8.0" regex = "1.10.3" diff --git a/src/io/hdus/bintable/bintable.rs b/src/io/hdus/bintable/bintable.rs index 15e2eef..715a7c4 100644 --- a/src/io/hdus/bintable/bintable.rs +++ b/src/io/hdus/bintable/bintable.rs @@ -123,7 +123,7 @@ pub fn read_table_bytes_to_df( .num_threads(n_threads as usize) .build() .unwrap(); - let results: Vec> = pool.install(|| { + let results: Vec> = pool.install(|| { limits .into_par_iter() .map(|(start, end)| { @@ -146,25 +146,18 @@ pub fn read_table_bytes_to_df( }); }); - let df_cols = columns - .iter() - .enumerate() - .map(|(i, column)| { - if (get_first_letter(&column.tform) == "P") - | (get_first_letter(&column.tform) == "Q") - { - local_buf_cols[i].read_var_len_cols(); - } - - let buf_col = &local_buf_cols[i]; - let series = buf_col.to_series(&column.ttype); - local_buf_cols[i].clear(); - series - }) - .collect(); - - let local_df = unsafe { DataFrame::new_no_checks(df_cols) }; - Ok(local_df) + let local_df = DataFrame::new( + columns + .iter() + .map(|column| { + polars::prelude::Column::new( + column.ttype.clone().into(), + column.tform.clone(), + ) + }) + .collect(), + ); + Ok(local_df.unwrap()) }) .collect() }); diff --git a/src/io/hdus/bintable/buffer.rs b/src/io/hdus/bintable/buffer.rs index c323676..60aaef9 100644 --- a/src/io/hdus/bintable/buffer.rs +++ b/src/io/hdus/bintable/buffer.rs @@ -1,4 +1,7 @@ -use polars::{prelude::NamedFrom, series::Series}; +use polars::{ + prelude::{NamedFrom, PlSmallStr}, + series::Series, +}; use crate::io::hdus::bintable::*; @@ -148,8 +151,8 @@ impl ColumnArrayBuffer { } pub fn to_series(&self, col_name: &str) -> Series { - let col = col_name; - let blank = ""; + let col: PlSmallStr = col_name.into(); + let blank: PlSmallStr = "".into(); let series = match self { ColumnArrayBuffer::L(data) => Series::new( col, @@ -280,8 +283,8 @@ impl ColumnDataBuffer { } pub fn to_series(&self, col_name: &str) -> Series { - let col = col_name; - let blank = ""; + let col: PlSmallStr = col_name.into(); + let blank: PlSmallStr = "".into(); let series = match self { ColumnDataBuffer::L(data) => Series::new(col, data), ColumnDataBuffer::X(data) => Series::new(col, data), diff --git a/src/io/hdus/table/buffer.rs b/src/io/hdus/table/buffer.rs index 4b22df2..1125290 100644 --- a/src/io/hdus/table/buffer.rs +++ b/src/io/hdus/table/buffer.rs @@ -1,4 +1,7 @@ -use polars::{prelude::NamedFrom, series::Series}; +use polars::{ + prelude::{NamedFrom, PlSmallStr}, + series::Series, +}; use rayon::prelude::*; #[derive(Debug, PartialEq)] @@ -72,7 +75,7 @@ impl ColumnDataBuffer { } pub fn to_series(&self, col_name: &str) -> Series { - let col_name = col_name; + let col_name: PlSmallStr = col_name.into(); let series = match self { ColumnDataBuffer::I(data) => Series::new(col_name, data), ColumnDataBuffer::E(data) => Series::new(col_name, data), diff --git a/src/io/hdus/table/table.rs b/src/io/hdus/table/table.rs index 736abb5..c36f03a 100644 --- a/src/io/hdus/table/table.rs +++ b/src/io/hdus/table/table.rs @@ -161,20 +161,18 @@ pub fn read_table_bytes_to_df( }); }); - let df_cols: Vec = columns - .iter() - .enumerate() - .map(|(i, column)| { - let buf_col = &local_buf_cols[i]; - let series = buf_col.to_series(&column.ttype); - local_buf_cols[i].clear(); - series - }) - .collect(); - - let local_df = unsafe { DataFrame::new_no_checks(df_cols) }; - - Ok(local_df) + let local_df = DataFrame::new( + columns + .iter() + .map(|column| { + polars::prelude::Column::new( + column.ttype.clone().into(), + column.tform.clone(), + ) + }) + .collect(), + ); + Ok(local_df.unwrap()) }) .collect() }); diff --git a/src/io/header/card.rs b/src/io/header/card.rs index 96856b5..f747e42 100644 --- a/src/io/header/card.rs +++ b/src/io/header/card.rs @@ -8,10 +8,10 @@ pub struct Card { } #[derive(Debug, PartialEq, Clone)] -pub enum CardValue{ +pub enum CardValue { INT(i64), FLOAT(f64), - STRING(String), + STRING(String), LOGICAL(bool), EMPTY, } @@ -50,8 +50,6 @@ impl CardValue { CardValue::EMPTY => "".to_string(), } } - - } fn check_type(s: &str) -> CardValue { @@ -86,7 +84,7 @@ impl Card { pub fn new(keyword: String, value: String, comment: Option) -> Self { Card { keyword: keyword, - value: check_type(&value), // Assuming value is always a string + value: check_type(&value), // Assuming value is always a string comment: comment, } } @@ -118,15 +116,21 @@ impl Card { self.keyword.clone() } - fn write_formatted_string(&self, writer: &mut W, mut string: String, bytes_count: &mut i32) -> std::io::Result<()> { + fn write_formatted_string( + &self, + writer: &mut W, + mut string: String, + bytes_count: &mut i32, + ) -> std::io::Result<()> { string.truncate(80); string.push_str(&" ".repeat(80 - string.len())); *bytes_count += 80; writer.write_all(string.as_bytes()) } - + pub fn write_to(&self, writer: &mut W, bytes_count: &mut i32) -> std::io::Result<()> { - if self.keyword == "COMMENT" || self.keyword == "HISTORY" || self.value == CardValue::EMPTY { + if self.keyword == "COMMENT" || self.keyword == "HISTORY" || self.value == CardValue::EMPTY + { self.write_formatted_string(writer, format!("{:<80}", self.keyword), bytes_count) } else { let keyword_string = if self.keyword.len() > 8 { @@ -134,7 +138,7 @@ impl Card { } else { format!("{:8}= ", self.keyword) }; - + match self.value { CardValue::STRING(_) => self.write_string_card(writer, keyword_string, bytes_count), _ => self.write_other_card(writer, keyword_string, bytes_count), @@ -149,12 +153,17 @@ impl Card { pub fn comment_ref(&self) -> &str { self.comment.as_ref().unwrap() } - - fn write_string_card(&self, writer: &mut W, keyword_string: String, bytes_count: &mut i32) -> std::io::Result<()> { + + fn write_string_card( + &self, + writer: &mut W, + keyword_string: String, + bytes_count: &mut i32, + ) -> std::io::Result<()> { if self.keyword == "" { return Ok(()); } - + let mut formatted_value = self.value.to_string(); let remaining_value = if formatted_value.len() > 67 { let remainder = Some(formatted_value[67..].to_string()); @@ -164,27 +173,32 @@ impl Card { } else { None }; - + let mut card_string = format!("{}'{}'", keyword_string, formatted_value); if let Some(comment) = &self.comment { card_string = format!("{} / {}", card_string, comment); } self.write_formatted_string(writer, card_string, bytes_count)?; - + if let Some(mut remaining_value) = remaining_value { while !remaining_value.is_empty() { let len = remaining_value.len(); let take = len.min(67); let continue_card = format!("CONTINUE '{}&'", &remaining_value[..take]); self.write_formatted_string(writer, continue_card, bytes_count)?; - + remaining_value.drain(..take); } } Ok(()) } - - fn write_other_card(&self, writer: &mut W, keyword_string: String, bytes_count: &mut i32) -> std::io::Result<()> { + + fn write_other_card( + &self, + writer: &mut W, + keyword_string: String, + bytes_count: &mut i32, + ) -> std::io::Result<()> { // using unwrap_or with an empty string as default if self.keyword == "" { return Ok(()); @@ -196,11 +210,10 @@ impl Card { CardValue::LOGICAL(_) => { if self.value.as_bool().unwrap() { formatted_value = format!("{:>20}", "T".to_string()); - } - else { + } else { formatted_value = format!("{:>20}", "F".to_string()); } - }, + } _ => formatted_value = format!("{:>20}", self.value.to_string()), } @@ -220,20 +233,24 @@ impl Card { let value; let comment; - if card_str.starts_with("COMMENT") || card_str.starts_with("HISTORY") || !card_str.contains("="){ + if card_str.starts_with("COMMENT") + || card_str.starts_with("HISTORY") + || !card_str.contains("=") + { let card = Card { keyword: card_str, value: CardValue::EMPTY, - comment: None + comment: None, }; return card; } - if card_str.starts_with("HIERARCH"){ + if card_str.starts_with("HIERARCH") { keyword = card_str.splitn(2, '=').collect::>()[0].to_string(); keyword = keyword.replace("HIERARCH ", ""); - } - else{ - keyword = card_str.splitn(2, '=').collect::>()[0].trim().to_string(); + } else { + keyword = card_str.splitn(2, '=').collect::>()[0] + .trim() + .to_string(); } keyword = keyword.trim_end().to_string(); @@ -242,7 +259,7 @@ impl Card { if let Some(idx) = remaining.find(" /") { // If there is a '/' character, we split the remaining string into value and comment. value = remaining[..idx + 1].trim().replace("'", "").to_string(); - comment = Some(remaining[idx+2..].trim().to_string()); + comment = Some(remaining[idx + 2..].trim().to_string()); } else { // Otherwise, the whole remaining string is the value. value = remaining.trim().replace("'", "").to_string(); @@ -250,20 +267,29 @@ impl Card { }; // println!("{} {} {:?} {:?}", keyword, value, comment, card_type); - Card { keyword: keyword, value: check_type(&value), comment: comment } + Card { + keyword: keyword, + value: check_type(&value), + comment: comment, + } } - pub fn continue_card(card: &mut Card, card_str: String){ + pub fn continue_card(card: &mut Card, card_str: String) { let mut value; - if card_str.starts_with("CONTINUE "){ - value = card_str.splitn(2, "CONTINUE ").collect::>()[1].trim().replace("'", "").to_string(); + if card_str.starts_with("CONTINUE ") { + value = card_str.splitn(2, "CONTINUE ").collect::>()[1] + .trim() + .replace("'", "") + .to_string(); value = value.strip_suffix("&").unwrap_or(&value).to_string(); let mut last_value = card.get_value_clone(); - last_value = last_value.strip_suffix("&").unwrap_or(&last_value).to_string(); + last_value = last_value + .strip_suffix("&") + .unwrap_or(&last_value) + .to_string(); card.set_value(format!("{}{}", last_value, value)); } } - -} \ No newline at end of file +} From 3edd490e49913687ef31bea8ed4c142dacc13707 Mon Sep 17 00:00:00 2001 From: Harlan D Heilman <73567020+HarlanHeilman@users.noreply.github.com> Date: Tue, 21 Jan 2025 10:30:23 -0800 Subject: [PATCH 10/11] Create rust.yml --- .github/workflows/rust.yml | 85 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 .github/workflows/rust.yml diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml new file mode 100644 index 0000000..ef534af --- /dev/null +++ b/.github/workflows/rust.yml @@ -0,0 +1,85 @@ +name: Main + +on: + push: + +env: + CARGO_TERM_COLOR: always + +jobs: + build-test: + name: Build and test (${{ matrix.os }}) + + strategy: + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v3 + - uses: swatinem/rust-cache@v2 + - name: Build + run: > + cargo build + --locked + --verbose + + - name: Run tests (without coverage) + if: matrix.os != 'ubuntu-latest' + run: > + cargo test + --verbose + + - name: Run tests (with coverage) + if: matrix.os == 'ubuntu-latest' + run: > + cargo install cargo-tarpaulin + && cargo tarpaulin + --verbose + --out Xml + --engine llvm + --skip-clean + - name: Upload coverage reports to Codecov + if: matrix.os == 'ubuntu-latest' + uses: codecov/codecov-action@v3 + + release-please: + name: Execute release chores + + permissions: + contents: write + pull-requests: write + + runs-on: ubuntu-latest + needs: build-test + + outputs: + created: ${{ steps.release.outputs.release_created }} + + steps: + - uses: google-github-actions/release-please-action@v3 + id: release + with: + release-type: rust + + publish: + name: Publish to crates.io + + runs-on: ubuntu-latest + needs: release-please + if: needs.release-please.outputs.created + + environment: crates.io + + steps: + - uses: actions/checkout@v3 + - uses: swatinem/rust-cache@v2 + + - name: Publish + # https://doc.rust-lang.org/cargo/reference/config.html?highlight=CARGO_REGISTRY_TOKEN#credentials + run: > + cargo publish + --verbose + --locked + --token ${{ secrets.CARGO_REGISTRY_TOKEN }} From e7b921cb043b1b4c72fbf91c01cf71f5f4ab5658 Mon Sep 17 00:00:00 2001 From: Harlan D Heilman <73567020+HarlanHeilman@users.noreply.github.com> Date: Thu, 10 Apr 2025 22:41:43 -0700 Subject: [PATCH 11/11] fix: fixed possible div by zero when bintable is empty --- Cargo.toml | 4 ++-- src/io/hdus/bintable/bintable.rs | 33 ++++++++++++++++++++++++++++++++ src/io/hdus/bintable/buffer.rs | 1 + 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 07bd84c..7e27618 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,10 +6,10 @@ authors = [ ] # A list of the package authors edition = "2021" name = "astrors-fork" -version = "0.1.13" +version = "0.1.14" license = "BSD-3-Clause" # The license your package is under -repository = "https://github.com/schwarzam/astrors" +repository = "https://github.com/schwarzam/astrors" readme = "README.md" diff --git a/src/io/hdus/bintable/bintable.rs b/src/io/hdus/bintable/bintable.rs index 715a7c4..79da51c 100644 --- a/src/io/hdus/bintable/bintable.rs +++ b/src/io/hdus/bintable/bintable.rs @@ -85,6 +85,22 @@ pub fn read_table_bytes_to_df( file: &mut File, ) -> Result { let nrows = header["NAXIS2"].value.as_int().unwrap_or(0); + + // Early return for empty tables to avoid division by zero + if nrows == 0 { + let empty_df = DataFrame::new( + columns + .iter() + .map(|column| { + polars::prelude::Column::new(column.ttype.clone().into(), column.tform.clone()) + }) + .collect(), + ) + .unwrap(); + + return Ok(empty_df); + } + let mut n_chunks: u16 = 1; let mut n_threads: u16 = num_cpus::get() as u16; @@ -163,6 +179,23 @@ pub fn read_table_bytes_to_df( }); drop(buffer); + // Handle the case where results might be empty (for empty tables) + if results.is_empty() { + // Create an empty dataframe with the correct schema + let empty_df = DataFrame::new( + columns + .iter() + .map(|column| { + polars::prelude::Column::new(column.ttype.clone().into(), column.tform.clone()) + }) + .collect(), + ) + .unwrap(); + + pad_read_buffer_to_fits_block(file, buffer_size)?; + return Ok(empty_df); + } + let mut final_df = results[0].as_ref().unwrap().clone(); for i in 1..results.len() { final_df.vstack_mut(&results[i].as_ref().unwrap()).unwrap(); diff --git a/src/io/hdus/bintable/buffer.rs b/src/io/hdus/bintable/buffer.rs index 60aaef9..e0fecaf 100644 --- a/src/io/hdus/bintable/buffer.rs +++ b/src/io/hdus/bintable/buffer.rs @@ -39,6 +39,7 @@ enum BufferTypes { Vector(ColumnArrayBuffer), } +#[allow(unused)] pub struct Buffer { tform: String, size: i32,