relList;
int foo = getRel_ui(dbHome, rrDbName, regionID, r2List, relList);
if (foo < 0) {
QMessageBox::critical(0, "Error", "Relationship db exception.");
return;
}
for (unsigned i = 0; i < relList.size(); i++) {
string r2_name, r2_space;
foo = getRegionName(dbHome, rDbName, r2List[i], r2_name, r2_space);
if (foo == 1) {
string tmpStr = relList[i] + ": " + r2_name + " (" + r2_space + ")";
ui_browser.relationList->addItem(tmpStr.c_str());
}
else
QMessageBox::critical(0, "Error", "Fails to get region name from ID " +
QString::number(r2List[i]) + " in region name db.");
}
}
/* This function collects parent structure info and show on the interface */
void browser::toParent(QListWidgetItem *pItem)
{
QString pStr = pItem->text();
// Return 0 if parent name is same as the structure name ("BRAIN")
if (regionName == pStr.toStdString())
return;
ui_browser.nameEdit->setText(pStr);
searchRegion(pStr.toStdString(), name_space);
}
/* This is the slot when item in child name list is double clicked */
void browser::toChild(QListWidgetItem *selItem)
{
QString selName = selItem->text();
ui_browser.nameEdit->setText(selName);
searchRegion(selName.toStdString(), name_space);
}
/* This slot takes care of double click signal in relationship box. */
void browser::toRelated(QListWidgetItem *selItem)
{
QString relStr = selItem->text();
int colon_post = relStr.indexOf(": ");
int ns_post = relStr.lastIndexOf(" (");
if (colon_post == -1 || ns_post == -1) {
QMessageBox::critical(0, "Error", "Relationship not understood: " + relStr);
return;
}
QString newRegion = relStr.mid(colon_post + 2, ns_post - colon_post - 2);
QString newNS = relStr.mid(ns_post + 2, relStr.length() - ns_post - 3);
ui_browser.nameEdit->setText(newRegion);
searchRegion(newRegion.toStdString(), newNS.toStdString());
}
/* Show acknowledgement information. */
void browser::about()
{
string helptext=
"This initial release of the VoxBo Brain Structure Browser was written by Dongbo Hu (code) and "
"Daniel Kimberg (sage advice). It is distributed along with structure "
"information derived from the NeuroNames project (Bowden and Dubach, "
"2002) as well as the AAL atlas (Automatic Anatomical Labeling, "
"Tzourio-Mazoyer et al., 2002)."
"References:
"
"Tzourio-Mazoyer N, Landeau B, Papathanassiou D, Crivello F, Etard O, "
"Delcroix N, Mazoyer B, Joliot M (2002). \"Automated Anatomical "
"Labeling of activations in SPM using a Macroscopic Anatomical "
"Parcellation of the MNI MRI single-subject brain.\" NeuroImage 15 (1), "
"273-89.
"
"Bowden D and Dubach M (2003). NeuroNames 2002. Neuroinformatics, 1, "
"43-59.";
QMessageBox::about(this, tr("About Application"), tr(helptext.c_str()));
}
/* This overloaded function takes care of some key press events */
void browser::keyPressEvent(QKeyEvent * kEvent)
{
if (ui_browser.nameEdit->hasFocus() || ui_browser.searchList->hasFocus()) {
if (ui_browser.searchList->isVisible() && kEvent->key() == Qt::Key_Escape) {
ui_browser.searchList->setFocus();
ui_browser.searchList->hide();
ui_browser.nameEdit->setFocus();
}
}
if (ui_browser.nameEdit->hasFocus() && ui_browser.searchList->count()
&& ui_browser.searchList->isVisible()) {
if (kEvent->key() == Qt::Key_Down) {
ui_browser.searchList->setFocus();
ui_browser.searchList->setCurrentRow(0);
}
else if (kEvent->key() == Qt::Key_Up) {
ui_browser.searchList->setFocus();
ui_browser.searchList->setCurrentRow(ui_browser.searchList->count() - 1);
}
else
ui_browser.searchList->show();
}
else if (ui_browser.searchList->hasFocus() &&
ui_browser.searchList->currentRow() == ui_browser.searchList->count() - 1 &&
kEvent->key() == Qt::Key_Down)
ui_browser.searchList->setCurrentRow(0);
else if (ui_browser.searchList->hasFocus() &&
ui_browser.searchList->currentRow() == 0 && kEvent->key() == Qt::Key_Up)
ui_browser.searchList->setCurrentRow(ui_browser.searchList->count() - 1);
else if (ui_browser.searchList->hasFocus() && kEvent->key() == Qt::Key_Backspace) {
ui_browser.nameEdit->setFocus();
ui_browser.nameEdit->backspace();
}
else if (ui_browser.searchList->hasFocus() && kEvent->key() == Qt::Key_Delete) {
ui_browser.nameEdit->setFocus();
ui_browser.nameEdit->del();
}
else if (ui_browser.searchList->hasFocus() && kEvent->key() != Qt::Key_Up
&& kEvent->key() != Qt::Key_Down && kEvent->key() != Qt::Key_Return && kEvent->key() != Qt::Key_Enter
&& kEvent->key() != Qt::Key_PageUp && kEvent->key() != Qt::Key_PageDown) {
ui_browser.nameEdit->setFocus();
QString orgStr = ui_browser.nameEdit->text();
QString newStr = kEvent->text();
if (newStr.length()) {
ui_browser.nameEdit->setText(orgStr + newStr);
popupList();
}
}
else if (!ui_browser.nameEdit->hasFocus() && !ui_browser.searchList->hasFocus())
ui_browser.searchList->hide();
//kEvent->accept();
QMainWindow::keyPressEvent(kEvent);
}
voxbo-1.8.5~svn1246/brainBrowser/main.h 0000664 0000000 0000000 00000004143 11531772013 0017662 0 ustar 00root root 0000000 0000000
// main.h
// Copyright (c) 1998-2010 by The VoxBo Development Team
// This file is part of VoxBo
//
// VoxBo is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// VoxBo is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with VoxBo. If not, see .
//
// For general information on VoxBo, including the latest complete
// source code and binary distributions, manual, and associated files,
// see the VoxBo home page at: http://www.voxbo.org/
//
// original version written by Dongbo Hu
/* This interface allows user to browse/search brain region database. */
#include "br_util.h"
#include "ui_browseRegion.h"
#include
bool setFiles(string, string, string, string &);
class browser : public QMainWindow
{
Q_OBJECT
public:
browser(string, string, string, string, QWidget *parent = 0);
private:
void buildUI();
void buildList();
int parseRegionName(QString, bool, QString &, QString &);
bool chkNameSpace(QString);
void setNameSpace(string);
void searchRegion(string, string);
void searchSynonym(string, string);
void clearUI();
void showParentChild();
void showParent();
void showChild();
void showSynonym();
bool chkName(string);
void showRelation();
void keyPressEvent(QKeyEvent *);
string dbHome, rDbName, rrDbName, sDbName;
Ui_brainBrowser ui_browser;
vector nameList;
vector spaceList;
long regionID;
string regionName, name_space;
private slots:
void popupList();
void selectName(QListWidgetItem *);
void changeNS();
void toParent(QListWidgetItem *);
void toChild(QListWidgetItem *);
void toRelated(QListWidgetItem *);
void resetUI();
void about();
};
voxbo-1.8.5~svn1246/brainBrowser/myDB.cpp 0000664 0000000 0000000 00000007134 11531772013 0020127 0 ustar 00root root 0000000 0000000
// myDB.cpp
// Copyright (c) 2010 by The VoxBo Development Team
// This file is part of VoxBo
//
// VoxBo is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// VoxBo is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with VoxBo. If not, see .
//
// For general information on VoxBo, including the latest complete
// source code and binary distributions, manual, and associated files,
// see the VoxBo home page at: http://www.voxbo.org/
//
// original version written by Dongbo Hu
/* Simple database class, more like a wraaper of Berkeley DB's db_ */
using namespace std;
#include "myDB.h"
/* Class constructor. Requires a path to the location
* where the database is located, and a database name. */
myDB::myDB(std::string &path, std::string &dbName, u_int32_t openFlag,
bool idCompare, bool allowDup, DBTYPE inputType)
: db_(NULL, 0), // Instantiate Db object
dbFileName_(path + dbName) // Database file name
{
try {
// Redirect debugging information to std::cerr
db_.set_error_stream(&std::cerr);
// Set encrypt
db_.set_encrypt("fyeo2006", DB_ENCRYPT_AES);
// If this is a secondary database, support sorted duplicates
if (allowDup)
db_.set_flags(DB_DUPSORT);
else if (idCompare && inputType == DB_BTREE)
db_.set_bt_compare(compare_int);
// Open the database
db_.open(NULL, dbFileName_.c_str(), NULL, inputType, openFlag, 0);
}
// DbException is not a subclass of std::exception, so we need to catch them both.
catch(DbException &e) {
std::cerr << "Error opening database: " << dbFileName_ << "\n";
std::cerr << e.what() << std::endl;
}
catch(std::exception &e) {
std::cerr << "Error opening database: " << dbFileName_ << "\n";
std::cerr << e.what() << std::endl;
}
}
/* Private member used to close a database. Called from the class destructor. */
void myDB::close()
{
// Close the db
try {
db_.close(0);
//std::cout << "Database " << dbFileName_ << " is closed." << std::endl;
}
catch(DbException &e) {
std::cerr << "Error closing database: " << dbFileName_ << "\n";
std::cerr << e.what() << std::endl;
}
catch(std::exception &e) {
std::cerr << "Error closing database: " << dbFileName_ << "\n";
std::cerr << e.what() << std::endl;
}
}
/* This function returns the number of records in database,
* used to generate keys automatically. */
long myDB::countRec()
{
long length = 0;
// Get a cursor to the patient db
Dbc *cursorp;
try {
getDb().cursor(NULL, &cursorp, 0);
Dbt key, data;
while (cursorp->get(&key, &data, DB_NEXT) == 0)
length++;
}
catch(DbException &e) {
getDb().err(e.get_errno(), "Error in reading records");
cursorp->close();
throw e;
}
catch(exception &e) {
cursorp->close();
throw e;
}
cursorp->close();
return length;
}
/* This function compares keys arithmetically instead of lexically.
* It is called when the db key is a long integer and we want to
* rank the records according to the key value. */
int compare_int(DB *dbp, const DBT *dbt1, const DBT *dbt2)
{
long l = *(long *) dbt1->data;
long r = *(long *) dbt2->data;
return l - r;
}
voxbo-1.8.5~svn1246/brainBrowser/myDB.h 0000664 0000000 0000000 00000003414 11531772013 0017571 0 ustar 00root root 0000000 0000000
// myDB.h
// Copyright (c) 1998-2010 by The VoxBo Development Team
// This file is part of VoxBo
//
// VoxBo is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// VoxBo is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with VoxBo. If not, see .
//
// For general information on VoxBo, including the latest complete
// source code and binary distributions, manual, and associated files,
// see the VoxBo home page at: http://www.voxbo.org/
//
// original version written by Dongbo Hu
/* myDB.h: simple wrapper of the basic _db class */
#ifndef MYDB_H
#define MYDB_H
#include
#include
class myDB
{
public:
// Constructor requires a path to the database and a database name.
myDB(std::string &path, std::string &dbName, u_int32_t openFlag = DB_CREATE,
bool idCompare = true, bool allowDup = false, DBTYPE dbtype = DB_BTREE);
// Destructor just calls private close method.
~myDB() { close(); }
inline Db &getDb() { return db_; }
long countRec();
private:
Db db_;
std::string dbFileName_;
u_int32_t cFlags_;
// Make sure the default constructor is private
myDB() : db_(NULL, 0) { }
// put our database close activity here. Called from our destructor. Could be public
void close();
};
int compare_int(DB *dbp, const DBT *dbt1, const DBT *dbt2);
#endif
voxbo-1.8.5~svn1246/brainBrowser/region.h 0000664 0000000 0000000 00000013503 11531772013 0020221 0 ustar 00root root 0000000 0000000
// region.h
// Copyright (c) 2010 by The VoxBo Development Team
// This file is part of VoxBo
//
// VoxBo is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// VoxBo is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with VoxBo. If not, see .
//
// For general information on VoxBo, including the latest complete
// source code and binary distributions, manual, and associated files,
// see the VoxBo home page at: http://www.voxbo.org/
//
// original version written by Dongbo Hu
/*******************************************************************************
* regionRec class definition: hold each region's information
*******************************************************************************/
using namespace std;
#include
#include
#include
class regionRec
{
public:
regionRec() { clear(); }
regionRec(void *buffer) { setData(buffer); }
/* Use an input data pointer to set each variable. */
void setData(void *buffer) {
char *buf = (char *) buffer;
int longLen = sizeof(long);
ID = *((long *) buf);
bufLen = longLen;
name_space = buf + bufLen;
bufLen += name_space.size() + 1;
name = buf + bufLen;
bufLen += name.size() + 1;
abbrev = buf + bufLen;
bufLen += abbrev.size() + 1;
orgID = *((long *) (buf + bufLen));
bufLen += longLen;
source = buf + bufLen;
bufLen += source.size() + 1;
pFlag = buf + bufLen;
bufLen += pFlag.size() + 1;
link = buf + bufLen;
bufLen += link.size() + 1;
creator = buf + bufLen;
bufLen += creator.size() + 1;
addDate = *((long *) (buf + bufLen));
bufLen += longLen;
modifier = buf + bufLen;
bufLen += modifier.size() + 1;
modDate = *((long *) (buf + bufLen));
bufLen += longLen;
}
/* Initialize data members. */
void clear() {
ID = 0;
name_space = name = abbrev = "";
orgID = 0;
source = pFlag = link = "";
creator = modifier = "";
addDate = modDate = 0;
}
/* Return combined data members as a single contiguous memory location. */
char * getBuffer() {
memset(databuf, 0, 1000);
bufLen = 0;
int longLen = sizeof(long);
memcpy(databuf, &ID, longLen);
bufLen += longLen;
packString(databuf, name_space);
packString(databuf, name);
packString(databuf, abbrev);
memcpy(databuf + bufLen, &orgID, longLen);
bufLen += longLen;
packString(databuf, source);
packString(databuf, pFlag);
packString(databuf, link);
packString(databuf, creator);
memcpy(databuf + bufLen, &addDate, longLen);
bufLen += longLen;
packString(databuf, modifier);
memcpy(databuf + bufLen, &modDate, longLen);
bufLen += longLen;
return databuf;
}
/* Return the size of the buffer. */
inline int getBufferSize() { return bufLen; }
/* Print out all data members. */
void show() {
printf("Region ID: %ld\n", ID);
printf("Region namespace: %s\n", name_space.c_str());
printf("Region name: %s\n", name.c_str());
printf("Region abbreviation: %s\n", abbrev.c_str());
printf("Original ID in source: %ld\n", orgID);
printf("Region source: %s\n", source.c_str());
printf("private flag: %s\n", pFlag.c_str());
printf("Region link: %s\n", link.c_str());
printf("Added by: %s\n", creator.c_str());
if (addDate)
printf("Region added on: %s", ctime(&addDate));
else
printf("Region added on:\n");
printf("Modified by: %s\n", modifier.c_str());
if (modDate)
printf("Last modified on: %s", ctime(&modDate));
else
printf("Last modified on:\n");
}
inline void setID(long inputVal) { ID = inputVal; }
inline void setNameSpace(string inputStr) { name_space = inputStr; }
inline void setName(string inputStr) { name = inputStr; }
inline void setAbbrev(string inputStr) { abbrev = inputStr; }
inline void setOrgID(long inputVal) { orgID = inputVal; }
inline void setSource(string inputStr) { source = inputStr; }
inline void setPrivate(string inputStr) { pFlag = inputStr; }
inline void setLink(string inputStr) { link = inputStr; }
inline void setCreator(string inputStr) { creator = inputStr; }
inline void setAddDate(long inputVal) { addDate = inputVal; }
inline void setModifier(string inputStr) { modifier = inputStr; }
inline void setModDate(long inputVal) { modDate = inputVal; }
inline long getID() { return ID; }
inline string getNameSpace() { return name_space; }
inline string getName() { return name; }
inline string getAbbrev() { return abbrev; }
inline long getOrgID() { return orgID; }
inline string getSource() { return source; }
inline string getPrivate() { return pFlag; }
inline string getLink() { return link; }
inline string getCreator() { return creator; }
inline long getAddDate() { return addDate; }
inline string getModifier() { return modifier; }
inline long getModDate() { return modDate; }
private:
/* Utility function that appends a char * to the end of the buffer. */
void packString(char *buffer, string &theString) {
int string_size = theString.size() + 1;
memcpy(buffer + bufLen, theString.c_str(), string_size);
bufLen += string_size;
}
long ID;
string name_space, name, abbrev;
long orgID; // original ID from input file, such as ID field in NN2002's hierarchy table
string source, pFlag, link;
string creator, modifier;
long addDate, modDate;
int bufLen;
char databuf[1000];
};
voxbo-1.8.5~svn1246/brainBrowser/region_name.db 0000664 0000000 0000000 00000600000 11531772013 0021351 0 ustar 00root root 0000000 0000000 b1 @ ® ® ’’ gä£ð8’$ªbLØÕ±DXÕ…H;2ÿ‘ªíP`À‹!kØÌé%öòóVV¼bvä]TÅ(½30fÜÔè¾]-Ëp¦¤DQúIªÆÀ";z¨UŒÝóG;ð#h«ñÍÉ…èof
ài¸Ý˜¦ç¦ä¸è¿Ÿ”š×ÁšéøîyKö•ˆ¥+WY1|%CUˆry'I†`Le'Ü]ìx?_êU£»“J¨îÆfª)ÎLâ^‹sS•—òjÈ«yBû/×·-Ñ<²»HƒGÌÅéäÍ‚áÚÞø1'‚4•1=á
ù.N†65½#–cÀ]—Y]îJÐb'¡‡Æ%WŠY&¹«T)åÈÒÖ0±úíoï
J†jYK£Ì¤LÔÓ‡ASš9ìÍ‹ßÎêû±ùfW
Ë!¢º+¢+ЛÎù‰Hš÷J)!u3,h€=Æìþ,¼ãíD½FÄÚŠ<Ì5;ƒ|Ço9Ÿ=#‰·›=t×QЫz4÷¢Æ•ÄjdÃzÒ‰°u@ÑqºEG1Èr>ÞZ4SŽ“Ý*=_‰%‰?ë$bû©}PzÈw•hyÅ!e°/®Ãq`
d? ð¸¶}kÚ: ´¼®4^éA@í¢¥9òâF1¤ñ²‚È£¸ØnxÂëeß„)ó)ÄòoûŠ}5¸*à/gu“‚–rÖnBJ›¿LÚš½ž1*š¯j¡‘©Ç”
`¥jiúRÒÐa¤îó-¥Acaß´/³Vw˜‹KˆxGœmi?â8— u¨KœÂ-ca/Oì]T·ngã\túUCé˜øy‚“¡”JsÅ\ðÒÆûf-ÅAQ2„.¼®¢în°9[ü?ç¹~‡Gaq!öÊÝQàÃÖcÙ;fQg–ØJaÿ¶°(…OCNÀoüöê¦"6?#]‚ùjŸRÃ)¾
ü€SÙûAeŸå@Ј\è'f¨uãËPÇ7ú§U‰Éà÷íÇ(ˆtì…´K(Ý{û6“ßtâ”{ðI¾ÃÍÃv”ÅÚ%Ù›¢™0¥¨¨‘þ•5—ׄXcqf+ôKßÚô°ËyIYwSB%U6J»éû—ÚÓ]«P}ó³aÏEÒé!œŽ2‘à¢ÚDöU¼
èà‡BÖ6–×ô7¨ÁÚ¨2…‘9Ÿs7Üò‘±JEýÂWRu„máªÔ®MBxöÍEf•í{_³4D‡„C"0šXq¨¹Eô§´´=L÷ÑÉcð¨}!nâÎ)çM“<‘´Åï°«]Zå¿‹òtSN4\v¿l™1üÌ›ÀÚjºAöµ²×¯°$¨ï`j'›µG¢ ¸3¯ìOîà`E-xÃÂSÈ„„¤‰&0äµ žºEû³çæM,zµrD¼Ë"ôõ[,d@ì¸Î²–®»fÔ- ò ma–ü\»)ðYi7—EøBµÑ”²¿Ði¾q˜J¤?j<Ÿ|Úm¦¦nxLÍ´(Å3ÄØÄzKÓ§
®-XÜE1õÔ†¿=:¬æ¯°D«(Tk÷¨4ÔÐ ¿{˦|¦DHùë>ý0iµ¸±;Gë°Çh8„sÝ8ïx·–'³*òñ…(þÍ|8Cm×çÐ}åý÷ÍÝ&4|†™#AÉUûßîÿl몊BžíÇ'/@tz EÉ/?8Þ¨QHÏ¿JzYÞ±ài,ºÍeîÐÛ9Í‹Þäׄ:kþÉü6!•´´î£X¢2("4$à´Eqq€Ì$jï…Š‰Ñ TÝòoQyiÞýß20ñ½hC®!÷›+œ¡‘b ¯oXfuÀ·PÝÇýþfîvö+T¬òR£z ¼÷ŽîÛaSPŠ™}}×Vf1ÖV3‚ëÂýís"ýA)~˜ /˜Ä^ì׿wŠòLXî‰hV‚·Óz7”õç¾Áð]úb«ù¨¥—^
ÌC¯ªw$Þ’‚V‹þ8/|kfå/Ȉ7öVëÄ´Š–òK‰’†f¢Ï•[L0R)ó ôXî:ÎØé~[œ:Š¿ªi½ÇªÕж÷¶ôV;cÕ˜‹ý”ûÌnl‚´…ÿîúBdoÑ„Û[?#–zW,
zZ®îÊšû’ÁÛÖ?á%ýtàälW9ˆƒuéRªKÓ\lO…ed|E!›º%†Ì0 ÞYÊ<%”בՋ9¼ò´ë.|q8•[dÖ1vÓ¶ÒÛy$¥@/L#×ðnÒ¾ÿªYáùñΙd-1£«÷Y{v8b-—ô2^µNHÍlº«³þŸ•jºFÃøV²Ç¶$×Ô0˜ãž`iò±õ&~Ôo<‚œ³NbfÆÀZmvÛqh¤ ˆ¿F…1ø½¯ówü¾?ý§âI¦o¬Ï_'FO€8nðáÕ¤h̹ñ§¦
´Ž™æÌ<ï&‚ŠÁsksÌ´«„ê-Z.ý-КòÿÌ^¹>;ÞØhYƒ
}ÈjªQ?Ç~b‘Uß9¤y „“þ*Ÿ$´e²•J²AŠô¯ñSû¦Rjßî°þ^aÃ{ G„ žH—ö¼€¨¨ô‡èÞE´™ì˜¬ËÞ*þ)›²Ž†cE
÷£Àê—X|»qDFþÛ-Ö†Àbío;ÈUuÁ£ÿÛó‘ÈfqGJ(1Ô‹›È
¢¸ÌæúBUª‰ÅB¤S†×Ö/ܬeÓD+A@¬n»fp‹^ì±.&,þ°¡¥@Ιqà˜Ä¤…"Äo–¢¯Ó#G€™ÐªmnW×oÞTXAB²1&ÖcÚŒèq(\þîºñŠTgb¬q{û&6ûê7X`Ia†Î<\:e±þ¾KëÔFhmô–³ÕÉW(¶ÖžÒ¸Û’•‹CW>