From 0ef003646ee7557322fc0cffa18f9b5641f18236 Mon Sep 17 00:00:00 2001 From: bergamaschi Date: Thu, 31 May 2012 07:46:53 +0000 Subject: [PATCH] solved conflicts between detectors about config files git-svn-id: file:///afs/psi.ch/project/sls_det_software/svn/slsDetectorSoftware@184 951219d9-93cf-4727-9268-0efd64621fa3 --- .../multiSlsDetector/multiSlsDetector.cpp | 241 +----------- .../multiSlsDetector/multiSlsDetector.h | 22 +- .../mythenDetectorServer/firmware_funcs.c | 2 +- .../mythenDetectorServer/server_funcs.c | 14 +- .../slsDetector/slsDetector.cpp | 342 ++---------------- slsDetectorSoftware/slsDetector/slsDetector.h | 19 - .../slsDetector/slsDetectorUtils.cpp | 234 ++++++++++++ .../slsDetector/slsDetectorUtils.h | 18 + 8 files changed, 295 insertions(+), 597 deletions(-) diff --git a/slsDetectorSoftware/multiSlsDetector/multiSlsDetector.cpp b/slsDetectorSoftware/multiSlsDetector/multiSlsDetector.cpp index d5e8fc8be..28871881b 100644 --- a/slsDetectorSoftware/multiSlsDetector/multiSlsDetector.cpp +++ b/slsDetectorSoftware/multiSlsDetector/multiSlsDetector.cpp @@ -3149,7 +3149,7 @@ int multiSlsDetector::readConfigurationFile(string const fname){ std::cout<< "Read configuration file of " << iline << " lines" << std::endl; #endif - + setNumberOfModules(-1); return iline; @@ -3174,14 +3174,13 @@ int multiSlsDetector::writeConfigurationFile(string const fname){ "headerafter", \ "headerbeforepar", \ "headerafterpar", \ - "nmod", \ "badchannels", \ "angconv", \ "globaloff", \ "binsize", \ "threaded" }; - int nvar=15; + int nvar=14; char ext[100]; @@ -3206,6 +3205,7 @@ int multiSlsDetector::writeConfigurationFile(string const fname){ slsDetectorCommand *cmd=new slsDetectorCommand(this); // detector types!!! + cout << iv << " " << names[iv] << endl; strcpy(args[0],names[iv].c_str()); outfile << names[iv] << " " << cmd->executeLine(1,args,GET_ACTION) << std::endl; @@ -3220,6 +3220,8 @@ int multiSlsDetector::writeConfigurationFile(string const fname){ //other configurations for (iv=1; ivexecuteLine(1,args,GET_ACTION) << std::endl; } @@ -3251,239 +3253,6 @@ int multiSlsDetector::writeConfigurationFile(string const fname){ -int multiSlsDetector::dumpDetectorSetup(string const fname, int level){ - - slsDetectorCommand *cmd=new slsDetectorCommand(this); - - string names[]={ - "fname",\ - "index",\ - "flags",\ - "dr",\ - "settings",\ - "threshold",\ - "exptime",\ - "period",\ - "delay",\ - "gates",\ - "frames",\ - "cycles",\ - "probes",\ - "timing",\ - "fineoff",\ - "ratecorr",\ - "startscript",\ - "startscriptpar",\ - "stopscript",\ - "stopscriptpar",\ - "scriptbefore",\ - "scriptbeforepar",\ - "scriptafter",\ - "scriptafterpar",\ - "headerbefore",\ - "headerbeforepar",\ - "headerafter",\ - "headerafterpar",\ - "scan0script",\ - "scan0par",\ - "scan0prec",\ - "scan0steps",\ - "scan1script",\ - "scan1par",\ - "scan1prec",\ - "scan1steps",\ - "flatfield",\ - "badchannels",\ - "angconv" - }; - int nvar=39; - - - - char ext[100]; - - int iv=0; - string fname1; - - - - ofstream outfile; - char *args[2]; - for (int ia=0; ia<2; ia++) { - args[ia]=new char[1000]; - } - int nargs; - if (level==2) - nargs=2; - else - nargs=1; - - - if (level==2) { - fname1=fname+string(".config"); - writeConfigurationFile(fname1); - fname1=fname+string(".det"); - } else - fname1=fname; - - - - outfile.open(fname1.c_str(),ios_base::out); - if (outfile.is_open()) { - for (iv=0; ivexecuteLine(1,args,GET_ACTION) << std::endl; - } - - - strcpy(args[0],names[iv].c_str()); - if (level==2) { - fname1=fname+string(".ff"); - strcpy(args[1],fname1.c_str()); - } - outfile << names[iv] << " " << cmd->executeLine(nargs,args,GET_ACTION) << std::endl; - iv++; - - strcpy(args[0],names[iv].c_str()); - if (level==2) { - fname1=fname+string(".bad"); - strcpy(args[1],fname1.c_str()); - } - outfile << names[iv] << " " << cmd->executeLine(nargs,args,GET_ACTION) << std::endl; - iv++; - - - strcpy(args[0],names[iv].c_str()); - if (level==2) { - fname1=fname+string(".angoff"); - strcpy(args[1],fname1.c_str()); - } - outfile << names[iv] << " " << cmd->executeLine(nargs,args,GET_ACTION) << std::endl; - iv++; - - - - - - for (int i=0; inumberOfDetectors; i++) { - sprintf(ext,".det%d",i); - if (detectors[i]) { - iv+=detectors[i]->dumpDetectorSetup(fname+string(ext),outfile, level, i); - } - } - - outfile.close(); - } - else { - std::cout<< "Error opening parameters file " << fname1 << " for writing" << std::endl; - return FAIL; - } - -#ifdef VERBOSE - std::cout<< "wrote " <> sargname; - // if (ssstr.good()) { - strcpy(args[iargval],sargname.c_str()); -#ifdef VERBOSE - std::cout<< args[iargval] << std::endl; -#endif - iargval++; - // } - } - if (level==2) { - cmd=new multiSlsDetectorClient(iargval,args,PUT_ACTION,this); - } else { - if (string(args[0])==string("flatfield")) - ; - else if (string(args[0])==string("badchannels")) - ; - else if (string(args[0])==string("angconv")) - ; - else if (string(args[0])==string("trimbits")) - ; - else { - cmd=new multiSlsDetectorClient(iargval,args,PUT_ACTION,this); - } - } - } - iline++; - } - infile.close(); - - - } else { - std::cout<< "Error opening " << fname << " for reading" << std::endl; - return FAIL; - } -#ifdef VERBOSE - std::cout<< "Read " << iline << " lines" << std::endl; -#endif - return iline; - - -} - int multiSlsDetector::writeDataFile(string fname, float *data, float *err, float *ang, char dataformat, int nch) { diff --git a/slsDetectorSoftware/multiSlsDetector/multiSlsDetector.h b/slsDetectorSoftware/multiSlsDetector/multiSlsDetector.h index 85649bbec..88cdb1714 100644 --- a/slsDetectorSoftware/multiSlsDetector/multiSlsDetector.h +++ b/slsDetectorSoftware/multiSlsDetector/multiSlsDetector.h @@ -374,24 +374,7 @@ class multiSlsDetector : public slsDetectorUtils { int writeConfigurationFile(string const fname); - /* - It should be possible to dump all the settings of the detector (including trimbits, threshold energy, gating/triggering, acquisition time etc. - in a file and retrieve it for repeating the measurement with identicals ettings, if necessary - */ - /** - - Purely virtual function - Should be implemented in the specific detector class - /sa mythenDetector::dumpDetectorSetup - */ - int dumpMultiDetectorSetup(string const fname, int level=0); - /** - Purely virtual function - Should be implemented in the specific detector class - /sa mythenDetector::retrieveDetectorSetup - */ - int retrieveMultiDetectorSetup(string const fname, int level=0); - + /* I/O */ @@ -460,9 +443,6 @@ class multiSlsDetector : public slsDetectorUtils { - int dumpDetectorSetup(string const fname, int level=0); - int retrieveDetectorSetup(string const fname, int level=0); - diff --git a/slsDetectorSoftware/mythenDetectorServer/firmware_funcs.c b/slsDetectorSoftware/mythenDetectorServer/firmware_funcs.c index cd4f04098..8c665b502 100755 --- a/slsDetectorSoftware/mythenDetectorServer/firmware_funcs.c +++ b/slsDetectorSoftware/mythenDetectorServer/firmware_funcs.c @@ -701,7 +701,7 @@ int setNMod(int n) { #ifdef VERBOSE printf("SetNMod called arg %d -- dr %d shiftfifo %d\n",n,dynamicRange,shiftfifo); #endif - if (n>0 && n<=ntot) { + if (n>=0 && n<=ntot) { nModX=n; /*d isable the fifos relative to the unused modules */ diff --git a/slsDetectorSoftware/mythenDetectorServer/server_funcs.c b/slsDetectorSoftware/mythenDetectorServer/server_funcs.c index 8d391afe5..2e655decd 100755 --- a/slsDetectorSoftware/mythenDetectorServer/server_funcs.c +++ b/slsDetectorSoftware/mythenDetectorServer/server_funcs.c @@ -2584,7 +2584,7 @@ int set_port(int file_des) { sd=bindSocket(p_number); } - if (sd>=0) { + if (sd>=0 || sd==-10) { ret=OK; if (differentClients ) ret=FORCE_UPDATE; @@ -2592,11 +2592,7 @@ int set_port(int file_des) { ret=FAIL; sprintf(mess,"Could not bind port %d\n", p_number); printf("Could not bind port %d\n", p_number); - if (sd==-10) { - sprintf(mess,"Port %d already set\n", p_number); - printf("Port %d already set\n", p_number); - } } n = sendDataOnly(file_des,&ret,sizeof(ret)); @@ -2604,9 +2600,11 @@ int set_port(int file_des) { n = sendDataOnly(file_des,mess,sizeof(mess)); } else { n = sendDataOnly(file_des,&p_number,sizeof(p_number)); - closeConnection(file_des); - exitServer(sockfd); - sockfd=sd; + if (sd>=0) { + closeConnection(file_des); + exitServer(sockfd); + sockfd=sd; + } } diff --git a/slsDetectorSoftware/slsDetector/slsDetector.cpp b/slsDetectorSoftware/slsDetector/slsDetector.cpp index e45979657..b22f6a40e 100644 --- a/slsDetectorSoftware/slsDetector/slsDetector.cpp +++ b/slsDetectorSoftware/slsDetector/slsDetector.cpp @@ -470,7 +470,9 @@ int slsDetector::initializeDetectorSize(detectorType type) { thisDetector->nModMax[Y]=1; thisDetector->dynamicRange=24; thisDetector->moveFlag=1; +#ifdef VERBOSE cout << "move flag" << thisDetector->moveFlag<< endl; +#endif break; case PICASSO: thisDetector->nChans=128; @@ -4920,42 +4922,35 @@ int slsDetector::writeConfigurationFile(ofstream &outfile, int id){ string names[]={ \ "hostname", \ "port", \ - "dataport", \ "stopport", \ - "caldir", \ "settingsdir", \ - "trimen", \ "outdir", \ - "ffdir", \ - "headerbefore", \ - "headerafter", \ - "headerbeforepar", \ - "headerafterpar", \ - "nmod", \ - "badchannels", \ - "angconv", \ "angdir", \ "moveflag", \ - "globaloff", \ - "binsize", \ - "threaded", \ + "lock", \ + "caldir", \ + "ffdir", \ + "nmod", \ "waitstates", \ "setlength", \ "clkdivider", \ "extsig" }; + // to be added in the future + // "trimen", + // "dataport", + switch (thisDetector->myDetectorType) { case GOTTHARD: - names[6]="outdir"; - names[7]="clientip"; - names[8]="clientmac"; - names[9]="servermac"; - nvar=10; + names[9]="clientip"; + names[10]="clientmac"; + names[11]="servermac"; + nvar=12; break; case MYTHEN: nsig=4; default: - nvar=25; + nvar=15; } @@ -4967,21 +4962,22 @@ int slsDetector::writeConfigurationFile(ofstream &outfile, int id){ for (iv=0; iv=0) - outfile << id << ":"; + cout << iv << " " << names[iv] << endl; + if (names[iv]=="extsig") { + for (int is=0; isexecuteLine(1,args,GET_ACTION) << std::endl; - } - } else { - strcpy(args[0],names[iv].c_str()); - if (id>=0) - outfile << id << ":"; - outfile << names[iv] << " " << cmd->executeLine(1,args,GET_ACTION) << std::endl; - } + if (id>=0) + outfile << id << ":"; + + outfile << args[0] << " " << cmd->executeLine(1,args,GET_ACTION) << std::endl; + } + } else { + strcpy(args[0],names[iv].c_str()); + if (id>=0) + outfile << id << ":"; + outfile << names[iv] << " " << cmd->executeLine(1,args,GET_ACTION) << std::endl; + } } delete cmd; return iv; @@ -5000,151 +4996,6 @@ int slsDetector::writeConfigurationFile(ofstream &outfile, int id){ - /* - It should be possible to dump all the settings of the detector (including trimbits, threshold energy, gating/triggering, acquisition time etc. - in a file and retrieve it for repeating the measurement with identicals settings, if necessary - */ -int slsDetector::dumpDetectorSetup(string const fname, ofstream &outfile, int level, int id){ - slsDetectorCommand *cmd=new slsDetectorCommand(this); - string names[]={ - "fname",\ - "index",\ - "flags",\ - "dr",\ - "settings",\ - "threshold",\ - "exptime",\ - "period",\ - "delay",\ - "gates",\ - "frames",\ - "cycles",\ - "probes",\ - "timing",\ - "fineoff",\ - "ratecorr",\ - "startscript",\ - "startscriptpar",\ - "stopscript",\ - "stopscriptpar",\ - "scriptbefore",\ - "scriptbeforepar",\ - "scriptafter",\ - "scriptafterpar",\ - "headerbefore",\ - "headerbeforepar",\ - "headerafter",\ - "headerafterpar",\ - "scan0script",\ - "scan0par",\ - "scan0prec",\ - "scan0steps",\ - "scan1script",\ - "scan1par",\ - "scan1prec",\ - "scan1steps",\ - "flatfield",\ - "badchannels",\ - "angconv",\ - "trimbits",\ - "timing" - }; - int nvar=41; - int iv=0; - string fname1; - char *args[2]; - for (int ia=0; ia<2; ia++) { - args[ia]=new char[1000]; - } - int nargs; - if (level==2) - nargs=2; - else - nargs=1; - - - - if (level==2) { - fname1=fname+string(".config"); - strcpy(args[0],"config"); - strcpy(args[1],fname1.c_str()); - if (id>=0) - outfile << id << ":"; - outfile << names[iv] << " " << cmd->executeLine(2,args,GET_ACTION) << std::endl; - iv++; - } - - - - for (iv=0; iv=0) - outfile << id << ":"; - outfile << names[iv] << " " << cmd->executeLine(1,args,GET_ACTION) << std::endl; - iv++; - } - - - strcpy(args[0],names[iv].c_str()); - if (level==2) { - fname1=fname+string(".ff"); - strcpy(args[1],fname1.c_str()); - } - if (id>=0) - outfile << id << ":"; - outfile << names[iv] << " " << cmd->executeLine(nargs,args,GET_ACTION) << std::endl; - iv++; - - strcpy(args[0],names[iv].c_str()); - if (level==2) { - fname1=fname+string(".bad"); - strcpy(args[1],fname1.c_str()); - } - if (id>=0) - outfile << id << ":"; - outfile << names[iv] << " " << cmd->executeLine(nargs,args,GET_ACTION) << std::endl; - iv++; - - - strcpy(args[0],names[iv].c_str()); - if (level==2) { - fname1=fname+string(".angoff"); - strcpy(args[1],fname1.c_str()); - } - if (id>=0) - outfile << id << ":"; - outfile << names[iv] << " " << cmd->executeLine(nargs,args,GET_ACTION) << std::endl; - iv++; - - strcpy(args[0],names[iv].c_str()); - if (level==2) { - size_t c=fname.rfind('/'); - if (c=0) - outfile << id << ":"; - outfile << names[iv] << " " << cmd->executeLine(nargs,args,GET_ACTION) << std::endl; - iv++; - - strcpy(args[0],names[iv].c_str()); - // for (int is=0; is<4; is++) { - // sprintf(args[0],"%s:%d",names[iv].c_str(),is); - if (id>=0) - outfile << id << ":"; - outfile << args[0] << " " << cmd->executeLine(1,args,GET_ACTION) << std::endl; - // } - iv++; - delete cmd; - return 0; -} @@ -5163,36 +5014,9 @@ int slsDetector::dumpDetectorSetup(string const fname, ofstream &outfile, int le - /* - It should be possible to dump all the settings of the detector (including trimbits, threshold energy, gating/triggering, acquisition time etc. - in a file and retrieve it for repeating the measurement with identicals settings, if necessary - */ -int slsDetector::dumpDetectorSetup(string const fname, int level){ - - string fname1; - ofstream outfile; - int iv; - if (level==2) { - fname1=fname+string(".det"); - } else - fname1=fname; - outfile.open(fname1.c_str(),ios_base::out); - if (outfile.is_open()) { - iv=dumpDetectorSetup(fname, outfile, level); - outfile.close(); - } else { - std::cout<< "Error opening parameters file " << fname1 << " for writing" << std::endl; - return FAIL; - } - -#ifdef VERBOSE - std::cout<< "wrote " <> sargname; - // if (ssstr.good()) { - strcpy(args[iargval],sargname.c_str()); -#ifdef VERBOSE - std::cout<< args[iargval] << std::endl; -#endif - iargval++; - // } - } - if (level==2) { - ; - cmd->executeLine(iargval,args,PUT_ACTION); - } else { - if (string(args[0])==string("flatfield")) - ; - else if (string(args[0])==string("badchannels")) - ; - else if (string(args[0])==string("angconv")) - ; - else if (string(args[0])==string("trimbits")) - ; - else { - ; - cmd->executeLine(iargval,args,PUT_ACTION); - } - } - } - iline++; - } - infile.close(); - } else { - std::cout<< "Error opening " << fname << " for reading" << std::endl; - return FAIL; - } -#ifdef VERBOSE - std::cout<< "Read " << iline << " lines" << std::endl; -#endif - delete cmd; - return iline; - -}; - diff --git a/slsDetectorSoftware/slsDetector/slsDetector.h b/slsDetectorSoftware/slsDetector/slsDetector.h index 88aed66b0..427d330b7 100644 --- a/slsDetectorSoftware/slsDetector/slsDetector.h +++ b/slsDetectorSoftware/slsDetector/slsDetector.h @@ -324,25 +324,6 @@ typedef struct sharedSlsDetector { - /** - Saves the detector setup to file - \param fname file to write to - \param level if 2 reads also trimbits, flat field, angular correction etc. and writes them to files with automatically added extension - \returns OK or FAIL - - */ - int dumpDetectorSetup(string const fname, int level=0); - int dumpDetectorSetup(string const fname, ofstream &outfile, int level=0, int id=-1); - - - /** - Loads the detector setup from file - \param fname file to read from - \param level if 2 reads also reads trimbits, angular conversion coefficients etc. from files with default extensions as generated by dumpDetectorSetup - \returns OK or FAIL - - */ - int retrieveDetectorSetup(string const fname, int level=0); diff --git a/slsDetectorSoftware/slsDetector/slsDetectorUtils.cpp b/slsDetectorSoftware/slsDetector/slsDetectorUtils.cpp index a726ef6ac..3e992df8d 100644 --- a/slsDetectorSoftware/slsDetector/slsDetectorUtils.cpp +++ b/slsDetectorSoftware/slsDetector/slsDetectorUtils.cpp @@ -1,19 +1,24 @@ #include "slsDetectorUtils.h" #include "usersFunctions.h" +#include "slsDetectorCommand.h" #include #include slsDetectorUtils::slsDetectorUtils() { +#ifdef VERBOSE cout << "setting callbacks" << endl; +#endif registerGetPositionCallback(&defaultGetPosition); registerConnectChannelsCallback(&defaultConnectChannels); registerDisconnectChannelsCallback(&defaultDisconnectChannels); registerGoToPositionCallback(&defaultGoToPosition); registerGoToPositionNoWaitCallback(&defaultGoToPositionNoWait); registerGetI0Callback(&defaultGetI0); +#ifdef VERBOSE cout << "done " << endl; +#endif }; @@ -498,3 +503,232 @@ int slsDetectorUtils::testFunction(int times) { } + + +int slsDetectorUtils::retrieveDetectorSetup(string const fname1, int level){ + + + + slsDetectorCommand *cmd; + + + char ext[100]; + int skip=0; + string fname; + string str; + ifstream infile; + int iargval; + int interrupt=0; + char *args[2]; + for (int ia=0; ia<2; ia++) { + args[ia]=new char[1000]; + } + string sargname, sargval; + int iline=0; + + if (level==2) { +// fname=fname1+string(".config"); +// readConfigurationFile(fname); +#ifdef VERBOSE + cout << "config file read" << endl; +#endif + fname=fname1+string(".det"); + } else + fname=fname1; + + infile.open(fname.c_str(), ios_base::in); + if (infile.is_open()) { + cmd=new slsDetectorCommand(this); + while (infile.good() and interrupt==0) { + sargname="none"; + sargval="0"; + getline(infile,str); + iline++; +#ifdef VERBOSE + std::cout<< str << std::endl; +#endif + if (str.find('#')!=string::npos) { +#ifdef VERBOSE + std::cout<< "Line is a comment " << std::endl; + std::cout<< str << std::endl; +#endif + continue; + } else { + istringstream ssstr(str); + iargval=0; + while (ssstr.good()) { + ssstr >> sargname; + // if (ssstr.good()) { + strcpy(args[iargval],sargname.c_str()); +#ifdef VERBOSE + std::cout<< args[iargval] << std::endl; +#endif + iargval++; + // } + skip=0; + } + + if (level!=2) { + if (string(args[0])==string("flatfield")) + skip=1; + else if (string(args[0])==string("badchannels")) + skip=1; + else if (string(args[0])==string("trimbits")) + skip=1; + } + if (skip==0) + cmd->executeLine(iargval,args,PUT_ACTION); + } + iline++; + } + delete cmd; + infile.close(); + + } else { + std::cout<< "Error opening " << fname << " for reading" << std::endl; + return FAIL; + } +#ifdef VERBOSE + std::cout<< "Read " << iline << " lines" << std::endl; +#endif + return iline; + + +} + + +int slsDetectorUtils::dumpDetectorSetup(string const fname, int level){ + + slsDetectorCommand *cmd=new slsDetectorCommand(this); + + string names[]={ + "fname",\ + "index",\ + "flags",\ + "dr",\ + "settings",\ + "threshold",\ + "exptime",\ + "period",\ + "delay",\ + "gates",\ + "frames",\ + "cycles",\ + "probes",\ + "timing",\ + "fineoff",\ + "startscript",\ + "startscriptpar",\ + "stopscript",\ + "stopscriptpar",\ + "scriptbefore",\ + "scriptbeforepar",\ + "scriptafter",\ + "scriptafterpar",\ + "scan0script",\ + "scan0par",\ + "scan0prec",\ + "scan0steps",\ + "scan1script",\ + "scan1par",\ + "scan1prec",\ + "scan1steps",\ + "ratecorr",\ + "flatfield",\ + "badchannels",\ + "trimbits" + }; + int nvar=35; + + + + char ext[100]; + + int iv=0; + string fname1; + + + + ofstream outfile; + char *args[2]; + for (int ia=0; ia<2; ia++) { + args[ia]=new char[1000]; + } + int nargs; + if (level==2) + nargs=2; + else + nargs=1; + + + if (level==2) { + fname1=fname+string(".config"); + writeConfigurationFile(fname1); + fname1=fname+string(".det"); + } else + fname1=fname; + + + + outfile.open(fname1.c_str(),ios_base::out); + if (outfile.is_open()) { + for (iv=0; ivexecuteLine(1,args,GET_ACTION) << std::endl; + } + + + strcpy(args[0],names[iv].c_str()); + if (level==2) { + fname1=fname+string(".ff"); + strcpy(args[1],fname1.c_str()); + } + outfile << names[iv] << " " << cmd->executeLine(nargs,args,GET_ACTION) << std::endl; + iv++; + + strcpy(args[0],names[iv].c_str()); + if (level==2) { + fname1=fname+string(".bad"); + strcpy(args[1],fname1.c_str()); + } + outfile << names[iv] << " " << cmd->executeLine(nargs,args,GET_ACTION) << std::endl; + iv++; + + + + strcpy(args[0],names[iv].c_str()); + if (level==2) { + size_t c=fname.rfind('/'); + if (cexecuteLine(nargs,args,GET_ACTION) << std::endl; + iv++; + + + + + + outfile.close(); + } + else { + std::cout<< "Error opening parameters file " << fname1 << " for writing" << std::endl; + return FAIL; + } + +#ifdef VERBOSE + std::cout<< "wrote " <