#include #include #include #include #include #include "tankMap.h" #include #include #include #include extern vmeWfdNode* wfdBankGet(unsigned int wfdaddress); extern short findPeak(vmeWfdNode* wfdBank, short bit, int& bucket, int START_TIME, int END_TIME); extern eventNode *ev; static String hexLookup[16]={"0","1","2","3","4","5","6","7", "8","9","A","B","C","D","E","F"}; int StringToWfd(String tankSpec, unsigned int& wfdAdd, short& wbit, short& end); enum { PEAK, RANGE, ALL }; enum { DISC, ONEDISC, NODISC}; static float xloc=.1,yloc=.1; static float size=1; static float tmin=0,tmax=0; // global parameters for plotting static float vmin=0,vmax=0; static float numytics=0.,numxtics=0.; static float VT=0,HT=0; static int wfdChanListLength=0; static int wfdNodeListLength=0; static int wfdChanList[6]; static int wfdBitList[6]; static float bitMarkerMap[4]={24.0, 25.0, 26.0, 28.0}; static float bitColorMap[5]={7.0,1.0, 2.0, 3.0, 4.0}; static float bitLineMap[5]={14.0, 1.0, 3.0, 12.0, 13.0}; static vmeWfdNode* wfdNodeList[6]; static int plotMode=PEAK; static int discMode=DISC; static int linecolor=6; static int boxcolor=4; static int lcolor; extern struct { float rquest[100]; } quest_; static float xsiz,ysiz; void plotWfdPage(); void multiPlotEvent() { for (int i=0; i < ev->numChildren(vmeWfdType); i++) { vmeWfdNode* wfdBank; F_getChild(ev,wfdBank,i); if (dash_pri_lev_() == 0) { cout << "VME Addr: " << hex << wfdBank->chanAddr << dec << "( " << ((wfdBank->chanAddr - 0x1000000)>>16) << " dec)" << " " << wfdBank->numHits << " buckets" << endl; } } } void multiPlotTalk() { const float LEADING=200; // time to plot around a peak const float TRAILING=1000; int parsedBox=0; int len; char command[80]; String commandList="DUMP PEAK RANGE TRANGE BW COL ALL HELP " "BCOL SIZE XLOC YLOC LABEL LCOL XTICS YTICS VT HT HARDCOPY "; kugetc_(command,len,80); command[len]='\0'; String wanted = command; int idummy; int numArgs=kunpar_(idummy)-1; int processed=1; while(!(commandList.contains(wanted)) && processed<=numArgs) { //string wanted is not a command... is it a box? unsigned int wfdChan; short ends, wfdBit; if(StringToWfd(wanted,wfdChan,wfdBit,ends)) { if(dash_dbg_lev_()==1)cout << "Channel " << wfdChan << " \n"; //string was suceesfully parsed into a wfd channel //now add it to the plot list if(!parsedBox) { //initialize the wfd Arrays //(I did it this way to keep last plot in memory) wfdChanListLength=0; wfdNodeListLength=0; parsedBox=1; } for(int numSides=0; numSidestime[0], wfdNodeList[0]->time[wfdNodeList[0]->numHits-1]); vmax=10; if(peakBucket<0 || peakBucket>9987) { cout << "Peak not found within buffer!" << endl; peakBucket=0; } vmin=wfdNodeList[0]->mVolt(peakBucket, 26); tmin=wfdNodeList[0]->time[peakBucket]-TRAILING; tmax=wfdNodeList[0]->time[peakBucket]+LEADING; for(int i=1; itime[0], wfdNodeList[i]->time[wfdNodeList[i]->numHits-1]); vmintemp=wfdNodeList[i]->mVolt(peakBucket, 26); tmintemp=wfdNodeList[i]->time[peakBucket]-TRAILING; tmaxtemp=wfdNodeList[i]->time[peakBucket]+LEADING; if(vmintemptmax)tmax=tmaxtemp; } vmin*=1.1; vmax=-.1*vmin; } else if(wanted.at(0,4)=="RANG") { if(dash_dbg_lev_()==1)cout << "range \n"; if(!wfdNodeListLength) { cout << "No valid WFD Channels to Plot\n"; return; } // pop off four more parameters kugetr_(tmin); kugetr_(tmax); kugetr_(vmin); kugetr_(vmax); processed+=4; if(dash_dbg_lev_()==1)cout << tmin << " " << tmax << " " << vmin << " " << vmax << endl; } else if(wanted.at(0,4)=="TRAN") { if(dash_dbg_lev_()==1)cout << "trange \n"; // pop off two more parameters kugetr_(tmin); kugetr_(tmax); processed+=2; //now get the best voltage ranges using the same approach as in PEAK if(!wfdNodeListLength) { cout << "No valid WFD Channels to Plot\n"; return; } int peakBucket; short testpattern = 1 << (wfdBitList[0]-1); if(wfdBitList[0]==15)testpattern=wfdBitList[0]; findPeak(wfdNodeList[0], testpattern, peakBucket,int(tmin),int(tmax)); vmax=10; vmin=wfdNodeList[0]->mVolt(peakBucket, 26); for(int i=1; imVolt(peakBucket, 26); if(vmintemptime[0], wfdNodeList[0]->time[wfdNodeList[0]->numHits-1]); vmax=10; vmin=wfdNodeList[0]->mVolt(peakBucket, 26); tmin=wfdNodeList[0]->time[0]; tmax=wfdNodeList[0]->time[wfdNodeList[0]->numHits-1]; for(int i=1; itime[0], wfdNodeList[i]->time[wfdNodeList[i]->numHits-1]); vmintemp=wfdNodeList[i]->mVolt(peakBucket, 26); tmintemp=wfdNodeList[i]->time[0]; tmaxtemp=wfdNodeList[i]->time[wfdNodeList[i]->numHits-1]; if(vmintemptmax)tmax=tmaxtemp; } vmin*=1.1; vmax=-.1*vmin; } else { if(dash_dbg_lev_()==1)cout << "help \n"; if(!(wanted.at(0,4)=="HELP"))cout << wanted << " is not a valid command\n"; cout << endl; cout << "WFD Farfalla/DASH Plotting Module. \n\n"; cout << "To plot, simply list all the desired tanks (up to 6)\n"; cout << "followed by at least one option\n"; cout << endl; cout << "List each tank as:\n"; cout << "\tAn ERP Box (implicitly asks for two wfd channels)\n"; cout << "\tA WFD channel in HEX preceded by 0x\n"; cout << "\tA 6 character tank name\n"; cout << "\tA 4 character sub-name (also asks for both ends)\n"; cout << "EXAMPLES:\n"; cout << "TALK WFDPLOT 3T03-0 3C02-0 3B01-0 PEAK\n"; cout << "TALK WFDPLOT 201 202 ALL\n"; cout << "TALK WFDPLOT 3T03 3C02 3B01 TRANGE 998000 1000000\n"; cout << "TALK WFDPLOT 0x300 0x301 RANGE 998000 1000000 10 -4000\n"; cout << endl; cout << "Available Options"; cout << "PEAK autoplots around the peak in the channel\n"; cout << "ALL displays the entire waveform\n"; cout << "RANGE lets you specify the tmin, tmax, ymin, ymax\n"; cout << "TRANGE lets you specify just tmin and tmax\n"; cout << "DUMP dumps raw waveform data\n"; cout << "Finally, the HARDCOPY option must be sent by itself\n"; cout << "HARDCOPY file -generates postscript from last plot\n"; cout << "If no option is given, the ranges from the last plot\n"; cout << "are applied.\n"; return; } processed++; if(processed<=numArgs) { kugetc_(command,len,80); command[len]='\0'; wanted = command; } } if(wfdNodeList && (tmin || tmax) && (vmin || vmax) && parsedBox) { plotWfdPage(); return; } } int StringToWfd(String tankSpec, unsigned int& wfdAdd, short& wbit, short& end) { int len=tankSpec.length(); if(len==6) { //it might be a name end=1; tankMap plotTank(tankSpec, NAME_TANK); wfdAdd=plotTank.wfd(); wbit=plotTank.wfdDisc(); } else if (len==4) { //it might be a partial name (no -0 or -1) end=2; tankMap plotTank(tankSpec+"-0", NAME_TANK); wfdAdd=plotTank.wfd(); wbit=plotTank.wfdDisc(); } else if (len==5 && tankSpec.at(0,2)=="0X") // try a WFD address { String hexAddress=tankSpec.at(2,3); int power=16*16; end=1; wbit=15; wfdAdd=0; for(int hexDigit=0; hexDigit<3; hexDigit++) { for(int hexTest=0; hexTest<16; hexTest++) { if(hexAddress.at(hexDigit,1)==hexLookup[hexTest]) { wfdAdd+=hexTest * power; break; } } power=power/16; } } else if (len<=3) // try ERP deoding { String erpString=tankSpec; end=2; int power=1; int erpBox=0; for(int decDigit=len-1; decDigit>-1; decDigit--) { for(int decTest=0; decTest<10; decTest++) { if(erpString.at(decDigit,1)==hexLookup[decTest]) { erpBox+=decTest*power; break; } } power=power*10; } tankMap plotTank(erpBox,0,ERP_TANK); wfdAdd=plotTank.wfd(); wbit=plotTank.wfdDisc(); } return(wfdAdd>=0x100 && wfdAdd<=0x62b); } void multiPlotInit() { // Look at KWTYPE to see if graphics is initialized (this assumes // main routine initialized KWTYPE to -1) int kwtype; dash_inquire_("KWTYPE",kwtype,6); if (kwtype == -1) { iginit_(0); igwkty_(kwtype); if (kwtype!=0) { igsse_(6,kwtype); igzset_("GZ",2); // direct graphics to screen and to memory } dash_deposit_("KWTYPE",kwtype,6); } // OK, we don't know what these are but Colin uses them.... igset_("LWID",0.F,4); // line width igset_("MSCF",.5F,4); igset_("BORD",1.F,4); istxfp_(0,2); igset_("CHHE",35.F,4); // character height igset_("FACI",7.F,4); // fill area color index // Picture will be drawn in a roughly 8 1/2 x 11-shaped horizontal // rectangle centered vertically in the available display window xsiz = 9.5*2.54; ysiz = 7.*2.54; lcolor = 1; // Turn on color return; } void plotWfdPage() { igset_("CHHE", 35.F,4); igset_("FAIS",0); // set fill to none if (lcolor) { igset_("PLCI",7.F,4); // poly-line color index igset_("LTYP",1.F,4); // line type } else igset_("LTYP",3.F,4); // line type iclrwk_(0,0); izpict_(" ","S",1,1); // scratch old HIGZ pic izpict_(" ","M",1,1); // create new HIGZ pic igrng_(xsiz,ysiz); float ntx = quest_.rquest[14-1]; float nty = quest_.rquest[15-1]; float dntx = quest_.rquest[12-1]; float dnty = quest_.rquest[13-1]; float ymin; float ymax; // if for some reason the max and min are flipped, swap 'em if(tmin>tmax){float temp=tmin; tmin=tmax; tmax=temp;} if(vmin>vmax){float temp=vmin; vmin=vmax; vmax=temp;} // parameters for deciding window placement/sizes const float TWS=.13; // Time window scale factor const float VWS=.05; // Voltage window scale factor const float YSEP=nty/200.; // vertical separation between wfd channels const float TEXF=1/60.; //fraction of window text size should be // The workspace will be divided into one window per waveform // now make a big window to put all the labels on isvp_(99,0.f,dntx+ntx,0.f,dnty+nty); iswn_(99,0.f,dntx+ntx,0.F,dnty+nty); for(int window=0; windowchanAddr/0x10000,1,WFD_TANK); String tankName1=wfdTank1.name(); tankMap wfdTank2(wfdNodeList[window]->chanAddr/0x10000,2,WFD_TANK); String tankName2=wfdTank2.name(); tankMap wfdTank3(wfdNodeList[window]->chanAddr/0x10000,3,WFD_TANK); String tankName3=wfdTank3.name(); tankMap wfdTank4(wfdNodeList[window]->chanAddr/0x10000,4,WFD_TANK); String tankName4=wfdTank4.name(); float SIZE=.007; float OFF=.015; float YM=.02+.03*(wfdNodeListLength<4); float XM=.13; igtext_(ntx+dntx-XM,ymin+YM+4*OFF,tankName4,SIZE,0.0,"R",tankName1.length(),1); igtext_(ntx+dntx-XM,ymin+YM+3*OFF,tankName3,SIZE,0.0,"R",tankName2.length(),1); igtext_(ntx+dntx-XM,ymin+YM+2*OFF,tankName2,SIZE,0.0,"R",tankName3.length(),1); igtext_(ntx+dntx-XM,ymin+YM+1*OFF,tankName1,SIZE,0.0,"R",tankName4.length(),1); igtext_(ntx+dntx-XM,ymin+YM+0*OFF,"NOBITS" ,SIZE,0.0,"R",6,1); if(window==wfdNodeListLength-1) { igtext_(dntx+.03, ymax, "mV", .02, 0.0, "L", 2,1); } if(!window) { igtext_(.5*ntx+dntx, ymin-.05, "[m]sec", .02, 0.0, "C", 6,1); } for(int index=0; index<5; index++) { if (lcolor) { igset_("PLCI",bitColorMap[index],4); //line color igset_("PMCI",bitColorMap[index],4); //marker color } else { igset_("LTYP",bitLineMap[index],4); // line type } if(index) { igset_("MTYP",bitMarkerMap[index-1],4); //marker type igset_("MSCF",size); // marker size } float XOFF=.055; float XWID=.033; float MOFF=.04; float XX[2]={ntx-dntx-XM-XOFF-XWID,ntx-dntx-XM-XOFF}; float YY[2]={ymin+YM+index*OFF+.5*SIZE,ymin+YM+index*OFF+.5*SIZE}; ipl_(2,XX,YY); if(index) { XX[0]+=MOFF; ipm_(1,XX,YY); } } iselnt_(100+window*100); // here are parameters to help with plotting int sample=0; int overFlow=0; // flag so we know when to interpolate at the edge of window float thisTime=float(wfdNodeList[window]->time[sample]); int maxHits=wfdNodeList[window]->numHits; int sameColor=1; //flag for if color or point style has changed int oldBitColor=0, newBitColor=0; // the bit that sets the line color float newBitPoint[4]={0,0,0,0}; // the other bits only get markers float oldBitPoint[4]={0,0,0,0}; // scan forward to first point we wish to plot while( thisTimetime[sample]); } //Choose starting color and marker types //Currently it starts at 0, can we find a more suitable color? if(sampledBit[sample]) { // remember, wfdBitList is a number between 1 and 4 (not 0) oldBitColor=wfdBitList[window]; } } else if(sampledBit[sample]) { oldBitColor=i+1; } } } if(sampledBit[sample]) && (oldBitColor!=(marker+1))) { oldBitPoint[marker]=1; } } } // now read data in non-zero-suppressed chunks while(thisTime<=tmax && samplemVolt(sample,26); if(sample) { lastTime=thisTime-5.0; lastVolt=wfdNodeList[window]->mVolt(sample-1,26); } else { lastTime=wfdNodeList[window]->tStart-5; lastVolt=0; } if(dash_dbg_lev_()==1) { cout << "Popping off a piece of waveform" << endl; cout << "window edges:" << tmin << " " << tmax << " " << vmin << " " << vmax << endl; cout << "current color index:" << oldBitColor << endl; cout << "current polymarkers on:" ; if(oldBitPoint[0])cout << 1 << " "; if(oldBitPoint[1])cout << 2 << " "; if(oldBitPoint[2])cout << 3 << " "; if(oldBitPoint[3])cout << 4 ; cout << endl; cout << "sample\ttime\t\tmvolt\tdBit\n"; } while(((thisTime - lastTime) == 5.0 ) && sample=vmin && sameColor && thisTime<=tmax) { if(dash_dbg_lev_()==1) cout << sample << "\t" << thisTime << "\t" << wfdNodeList[window]->mVolt(sample,26) << "\t" << wfdNodeList[window]->dBit[sample] << endl; if(overFlow) { // the last point was out of range so to make things // prettier lets interpolate // (I have to do this because CLIP isn't working right) overFlow=0; if(sample) { if(thisTime-wfdNodeList[window]->time[sample-1]==5) { float prevVolt=wfdNodeList[window]->mVolt(sample-1,26); float slope=(thisVolt-prevVolt)/5.0; float deltat=(vmin-prevVolt)/slope; if(deltat>=0.0 || deltat<=5.0) { // interpolation successful timeChunk[n]=-(thisTime+deltat)/1000.; voltChunk[n]=vmin; n++; } } } } timeChunk[n]=-thisTime/1000.; voltChunk[n]=thisVolt; n++; sample++; if(sampletime[sample]); lastVolt=thisVolt; thisVolt=wfdNodeList[window]->mVolt(sample,26); // if we went under min, interpolate a point and set a flag if(thisVolt=0.0 || deltat<=5.0) { // interpolation successful timeChunk[n]=-(lastTime+deltat)/1000.; voltChunk[n]=vmin; n++; } } // now lets see if the colors changed newBitColor=oldBitColor; // default to color unchanged newBitPoint[0]=0; newBitPoint[1]=0; newBitPoint[2]=0; newBitPoint[3]=0; short thisdBit=wfdNodeList[window]->dBit[sample]; sameColor=1; if(!oldBitColor) { // we haven't plotted a real color yet, can we now? for(int i=0; i<4; i++) { if((1<mVolt(sample,26)=2) { if (lcolor) { igset_("PLCI",bitColorMap[oldBitColor],4); //line color igset_("PMCI",bitColorMap[oldBitColor],4); //marker color } else { igset_("LTYP",bitLineMap[oldBitColor],4); // line type } ipl_(n,timeChunk,voltChunk); for(int i =0; i< 4; i++) { if(oldBitPoint[i]) { igset_("MTYP",bitMarkerMap[i],4); //marker type ipm_(n,timeChunk,voltChunk); } } } // new colors become old colors sameColor=1; oldBitColor=newBitColor; for(int i=0; i<4; i++)oldBitPoint[i]=newBitPoint[i]; } } iuwk_(0,1); }