Index: Evidence/DColl.cc
===================================================================
--- Evidence/DColl.cc	(revision 209)
+++ Evidence/DColl.cc	(revision 212)
@@ -225,6 +225,5 @@
 	char *Token = strtok(Info->getString(), "+-!@");	
 	while (Token != NULL) {
-	  if (*Info->getString()=='-' || *Info->getString()=='!') RemoveService(string(Token)+"/SERVICE_LIST");	  
-	  else AddService(string(Token)+"/SERVICE_LIST");
+	  if (*Info->getString()=='+') AddService(string(Token)+"/SERVICE_LIST");
 	  Token = strtok(NULL, "|"); // Skip server IP address
 	  Token = strtok(NULL, "@");
@@ -243,6 +242,5 @@
       if (strstr(Type, "|CMD")==NULL && strstr(Type, "|RPC")==NULL) {
 	    // Add or remove service
-	    if (*Info->getString()=='-' || *Info->getString()=='!') RemoveService(Name);
-		else AddService(Name);
+	    if (*Info->getString()=='+') AddService(Name);
 	  }
 	  Name = strtok(NULL, "|");
Index: Evidence/Edd/Edd.cc
===================================================================
--- Evidence/Edd/Edd.cc	(revision 209)
+++ Evidence/Edd/Edd.cc	(revision 212)
@@ -58,5 +58,4 @@
 //////////////////////////////////////////
 
-// Constructor
 EddLineDisplay::EddLineDisplay(QString Name, int Index, QWidget *P):
 	QLineEdit(P), ServiceName(Name), Index(Index) {
@@ -192,9 +191,25 @@
 
 
+//////////////////////////////////////////
+// Sending string command to DIM server //
+//////////////////////////////////////////
+
+EddCommand::EddCommand(QString Name, QWidget *P): QLineEdit(P), Name(Name) {
+
+  setToolTip("Send command "+Name);  
+  connect(this, SIGNAL(returnPressed()), SLOT(SendCommand()));
+}
+
+// Send command
+void EddCommand::SendCommand() {
+
+  DimClient::sendCommand(Name.toAscii().data(), text().toAscii().data());
+}
+
+
 //////////////////////////////////
 // History plot for DIM service //
 //////////////////////////////////
 
-// Constructor
 EddPlot::EddPlot(QString DIMService, int Index, QWidget *P): EddBasePlot(P) {
 
@@ -269,12 +284,11 @@
 	// If buffer empty, request new history buffer
     if (List[ItemNo].Signal->dataSize() == 0) {
-	  int Time, Size;
+	  int Time, Size, Count=0;
 	  void *Data;
-
-	  class EvidenceHistory *HistClass = Handler->GetHistory(List[ItemNo].Name);
-	  
-	  if (HistClass->GetHistory()) {
+	  class EvidenceHistory *Hist;
+
+	  if ((Hist = Handler->GetHistory(List[ItemNo].Name)) != NULL) {
 		double Number=0;
-		while (HistClass->Next(Time, Size, Data)) {
+		while (Hist->Next(Time, Size, Data)) {
 		  switch (Format[0].toUpper().toAscii()) {
     		case 'I':
@@ -287,8 +301,9 @@
 		  }
 		  AddPoint(ItemNo, Time, Number);
+		  Count++;
 		}
 
 		// Local buffer at least twice as large as longest history
-		if (SizeLimit < 2*List[ItemNo].Signal->dataSize()) SizeLimit = 2*List[ItemNo].Signal->dataSize();
+		if (SizeLimit < 2*Count) SizeLimit = 2*Count;
 	  }
 	}
@@ -708,9 +723,8 @@
 	int Time, Size;
 	void *Data;
-
-	class EvidenceHistory *HistClass = Handler->GetHistory(Name);
-
-	if (HistClass->GetHistory()) {
-	  while (HistClass->Next(Time, Size, Data)) {
+	class EvidenceHistory *Hist;
+
+	if ((Hist = Handler->GetHistory(Name)) != NULL) {
+	  while (Hist->Next(Time, Size, Data)) {
 		moveCursor (QTextCursor::Start);
 		insertPlainText(QString("(")+QDateTime::fromTime_t(Time).toString()+") ");	  
@@ -770,4 +784,5 @@
   TotalVolume = 0;
 
+  // Timer to calculate data rates
   QTimer *Timer = new QTimer(this);
   Timer->connect(Timer, SIGNAL(timeout()), this, SLOT(UpdateStatistics()));
@@ -783,4 +798,5 @@
 
   for (int i=0; i<HistoryList.size(); i++) delete HistoryList[i].HistClass;
+
   delete Mutex;
 }
@@ -795,5 +811,5 @@
   for (int i=0; i<ServiceList.size(); i++) if (ServiceList[i].Name == Name) {
 	ServiceList[i].Count++;
-	// If service already reveived, reemit for new subscriber
+	// If service already received, reemit for new subscriber
 	if (!ServiceList[i].ByteArray.isEmpty()) {
 	  YEP(Name, ServiceList[i].TimeStamp, ServiceList[i].ByteArray, ServiceList[i].Format, ServiceList[i].Text);
@@ -832,18 +848,26 @@
 class EvidenceHistory *EddDim::GetHistory(QString Name) {
 
-  // If history already available, return this
+  // History already available (only request again if too old)
   for (int i=0; i<HistoryList.size(); i++) if (HistoryList[i].Name == Name) {
 	HistoryList[i].Count++;
-	return HistoryList[i].HistClass;
-  }
-
+	if (time(NULL)-HistoryList[i].LastUpdate < 5) {
+	  HistoryList[i].HistClass->Rewind();
+	  return HistoryList[i].HistClass;
+	}
+	HistoryList[i].LastUpdate = time(NULL);
+	if (HistoryList[i].HistClass->GetHistory()) return HistoryList[i].HistClass;
+	else return NULL;
+  }
+
+  // Create new history class
   struct HistItem New;
   New.Name = Name;
   New.HistClass = new EvidenceHistory(Name.toStdString());
   New.Count = 1;
+  New.LastUpdate = time(NULL);
   HistoryList.append(New);
 
-  return New.HistClass;
-
+  if (New.HistClass->GetHistory()) return New.HistClass;
+  else return NULL;
 }
 
@@ -906,5 +930,5 @@
 EventScope::EventScope(QWidget *P): EddBasePlot(P), PixelMap("../../config/PixelMap.txt", false) {
 
-  Name = "Feedback/EventData";
+  Name = "drsdaq/EventData";
 
   Tmpfile = tmpfile();
@@ -1048,5 +1072,5 @@
   else setAxisTitle(QwtPlot::xBottom, "Time from trigger minus one revolution (ns)");
   
-  // Loop through event data
+  // Loop through event data to update event scope
   RunHeader *R = RD->RHeader;
   for (int i=0; i<List.size(); i++) {
@@ -1081,4 +1105,25 @@
 
   UpdatePlot();
+
+  // Loop through event data for pixel display
+  QVector<double> Pixel(R->NBoards*R->NChips*R->NChannels);
+  int Count = 0;
+
+  for (unsigned int Board=0; Board<R->NBoards; Board++) {
+  for (unsigned int Chip=0; Chip<R->NChips; Chip++) {
+  for (unsigned int Channel=0; Channel<R->NChannels; Channel++) {
+    Pixel[Count] = DBL_MIN;
+
+	for (unsigned int i=0; i<R->Samples; i++) {
+	  y = *((short *) (RD->Data + R->NBoards*R->NChips*sizeof(int)) +
+		Board*R->NChips*R->NChannels*R->Samples + Chip*R->NChannels*R->Samples +
+		Channel*R->Samples + i) * RD->BStruct[Board].ScaleFactor;
+
+	  if (y > Pixel[Count]) Pixel[Count] = y;
+    }
+	Count++;	  
+  }}}
+  
+  emit(PixelData(Pixel));
 }
 
@@ -1092,9 +1137,11 @@
 }
 
-//
-// Tab page classes
-//
-
+//------------------------------------------------------------------
+//**************************** Tab pages ***************************
+//------------------------------------------------------------------
+
+//
 // Environment page
+//
 TP_Environment::TP_Environment() {
 
@@ -1104,5 +1151,5 @@
   EddLineDisplay *Line = new EddLineDisplay("ARDUINO/Status");
   Line->setMaximumWidth(200);
-  Layout->addWidget(Line, 0, 0, 1, 3);      
+  Layout->addWidget(Line, 0, 0, 1, 2);      
 
   // Generate plot and data displays
@@ -1113,5 +1160,5 @@
     Plot->AddService("ARDUINO/Data", i);
   }
-  Layout->addWidget(Plot, 0, 3, 6, 4);      
+  Layout->addWidget(Plot, 0, 2, 8, 7);      
 
   // Night sky monitor
@@ -1120,5 +1167,7 @@
 }
 
+//
 // Bias page
+//
 TP_Bias::TP_Bias() {
 
@@ -1143,10 +1192,15 @@
   Layout->addWidget(Line, 0, 0, 1, 3);      
 
-  EddText *Text = new EddText("Bias/Textout", true);
+  EddCommand *Command = new EddCommand("Bias/Command");
+  Layout->addWidget(Command, 10, 0, 1, 4);    
+
+  EddText *Text = new EddText("Bias/StdOut", true);
   Text->setFixedWidth(400);
-  Layout->addWidget(Text, 10, 0, 4, 4);      
-}
-
+  Layout->addWidget(Text, 11, 0, 4, 4);      
+}
+
+//
 // Feedback page
+//
 TP_Feedback::TP_Feedback() {
 
@@ -1156,9 +1210,10 @@
   EddPlot *Plot = new EddPlot();
   for (int i=0; i<36; i++) {
-    Line = new EddLineDisplay("Feedback/Average", i);
+    Line = new EddLineDisplay("drsdaq/Average", i);
+	Line->setMaximumWidth(60);
     Layout->addWidget(Line, i%9+1, 0+i/9, 1, 1);
-    Plot->AddService("Feedback/Average", i);
-  }
-  Layout->addWidget(Plot, 0, 4, 11, 3);
+    Plot->AddService("drsdaq/Average", i);
+  }
+  Layout->addWidget(Plot, 0, 4, 12, 10);
 
   //Graph = new EddPlot();
@@ -1169,9 +1224,10 @@
   //FeedbackLayout->addWidget(Graph, 10, 0, 10, 3);
 
-  Line = new EddLineDisplay("Feedback/Status");
+  Line = new EddLineDisplay("drsdaq/Status");
   Line->setMaximumWidth(200);
-  Layout->addWidget(Line, 0, 0, 1, 3);      
-  Line = new EddLineDisplay("Feedback/Count");
-  Layout->addWidget(Line, 0, 3, 1, 1);      
+  Layout->addWidget(Line, 0, 0, 1, 2);      
+  Line = new EddLineDisplay("drsdaq/Count");
+  Line->setMaximumWidth(60);
+  Layout->addWidget(Line, 0, 2);      
 
   QWidget *Button = new QPushButton("Details");
@@ -1188,14 +1244,17 @@
   EddPlot *Plot = new EddPlot();
   for (int i=0; i<36; i++) {
-    Line = new EddLineDisplay("Feedback/Sigma", i);
+    Line = new EddLineDisplay("drsdaq/Sigma", i);
+	Line->setMaximumWidth(50);
     Layout->addWidget(Line, i%9+1, 0+i/9, 1, 1);
-    Plot->AddService("Feedback/Sigma", i);
-  }
-  Layout->addWidget(Plot, 0, 4, 11, 3);
+    Plot->AddService("drsdaq/Sigma", i);
+  }
+  Layout->addWidget(Plot, 0, 4, 12, 10);
   
   Widget->show();
 }
 
-// DAQ page
+//
+// Event scope page
+//
 TP_DAQ::TP_DAQ() {
 
@@ -1217,5 +1276,5 @@
   TabWidget->addTab(RunHeaderDisplay, "&Run Header");
   TabWidget->addTab(EventHeaderDisplay, "&Event Header");
-  Layout->addWidget(TabWidget, 0, 1, 3, 3);
+  Layout->addWidget(TabWidget, 0, 1, 5, 3);
 
   connect(Scope, SIGNAL(RunHeaderChanged(QString)), RunHeaderDisplay, SLOT(setPlainText(QString)));
@@ -1250,5 +1309,5 @@
   FormLayout->addRow("Board", Board);
   FormLayout->addRow("Pixel ID", PixelID);
-  Layout->addLayout(FormLayout, 0, 0);
+  Layout->addLayout(FormLayout, 0, 0, 2, 1);
   
   // Add trace permanently
@@ -1258,6 +1317,43 @@
   Layout->addWidget(Button, 2, 0);
   connect(Button, SIGNAL(clicked()), SLOT(KeepCurrent()));
-}
-
+
+  // Button to show event display
+  QPushButton *PixDisplay = new QPushButton("Pixel display");
+  PixDisplay->setFont(QFont("Times", 10, QFont::Bold));
+  PixDisplay->setToolTip("Show event display window");
+  Layout->addWidget(PixDisplay, 4, 0);
+  connect(PixDisplay, SIGNAL(clicked()), SLOT(ShowPixelDisplay()));
+
+  // Event display window
+  Display = new QWidget();
+  Display->setWindowTitle("Edd - Event display");
+  
+  Pixel = new QPushButton *[MAXPIXEL];
+  int Count = 0;
+  double x,y;
+  
+  for (int ix=-22; ix<=22; ix++) for (int iy=-19; iy<=20; iy++) {  
+    if (Count == MAXPIXEL) break;
+	
+	x = ix*0.866;
+	y = iy - (ix%2==0 ? 0.5:0);
+    if ((pow(x,2)+pow(y,2) >= 395) && !(abs(ix)==22 && iy==7)) continue;
+	
+    Pixel[Count] = new QPushButton(Display);
+	Pixel[Count]->setAutoFillBackground(true);
+	Pixel[Count]->setGeometry(x*12.5 + 250, y*12.5 + 250, 10, 10);
+	Pixel[Count]->show();
+	Count++;
+  }
+
+  connect(Scope, SIGNAL(PixelData(QVector<double>)), SLOT(SetPixelData(QVector<double>)));
+}
+
+TP_DAQ::~TP_DAQ() {
+
+  delete[] Pixel;
+}
+
+// Translate pixel ID to board, chip, channel
 void TP_DAQ::TranslatePixelID() {
   
@@ -1287,5 +1383,24 @@
 }
 
-// DAQ page
+// Show/hide pixel display
+void TP_DAQ::ShowPixelDisplay() {
+
+  Display->show();
+  Display->raise();
+}
+
+void TP_DAQ::SetPixelData(QVector<double> Data) {
+
+  QwtLinearColorMap Map;
+
+  for (int i=0; i<Data.size(); i++) {
+	Pixel[i]->setPalette(QPalette(Map.color(QwtDoubleInterval(300, 400), Data[i])));
+  }
+}
+
+
+//
+// Evidence page
+//
 TP_Evidence::TP_Evidence() {
 
@@ -1367,5 +1482,5 @@
   // Arrangement in tabs
   TabWidget = new QTabWidget(Central);
-  TabWidget->addTab(new TP_DAQ, "&drsdaq");
+  TabWidget->addTab(new TP_DAQ, "Event scope");
   TabWidget->addTab(new TP_Bias, "&Bias");
   TabWidget->addTab(new TP_Feedback, "&Feedback");
Index: Evidence/Edd/Edd.h
===================================================================
--- Evidence/Edd/Edd.h	(revision 209)
+++ Evidence/Edd/Edd.h	(revision 212)
@@ -19,4 +19,5 @@
 #include <qwt_plot_marker.h>
 #include <qwt_data.h>
+#include <qwt_color_map.h>
 
 #include <limits.h>
@@ -118,4 +119,17 @@
 };
 
+// Sending command to DIM server
+class EddCommand: public QLineEdit {
+    Q_OBJECT
+
+	QString Name;
+	
+  public:
+    EddCommand(QString, QWidget * = NULL);
+
+  private slots:
+	void SendCommand();	
+};
+
 // Graph class for history display 
 class EddPlot: public EddBasePlot {
@@ -213,4 +227,5 @@
 	  QString Name;
 	  int Count;
+	  int LastUpdate;
 	  class EvidenceHistory *HistClass;
 	};
@@ -277,4 +292,5 @@
 	void RunHeaderChanged(QString);
 	void EventHeaderChanged(QString);
+	void PixelData(QVector<double>);
 };
 
@@ -307,4 +323,5 @@
 class TP_DAQ: public QWidget {
   Q_OBJECT
+  static const int MAXPIXEL = 1440;
 
   private:
@@ -315,4 +332,6 @@
  	QLineEdit *PixelID;
  	QFormLayout *FormLayout;
+	QWidget *Display;
+	QPushButton **Pixel;
 
   private slots:
@@ -320,7 +339,10 @@
 	void UpdateScope(int);
 	void KeepCurrent();
+	void ShowPixelDisplay();
+	void SetPixelData(QVector<double>);
 
   public:
 	TP_DAQ();	
+	~TP_DAQ();	
 };
 
Index: Evidence/Evidence.cc
===================================================================
--- Evidence/Evidence.cc	(revision 209)
+++ Evidence/Evidence.cc	(revision 212)
@@ -370,11 +370,15 @@
 }
 
-// Requests service history
+// Requests service history (returns true if data received OK)
 bool EvidenceHistory::GetHistory() {
 
   DimRpcInfo R((char *) "ServiceHistory", NO_LINK);
   R.setData((char *) Name.c_str());
+
+  // Check if data OK
   if (!EvidenceServer::ServiceOK(&R)) return false;
-
+  if (R.getSize() == 0) return false;
+  
+  // Copy data to buffer
   delete[] Buffer;
   BufferSize = R.getSize();
@@ -382,5 +386,5 @@
 
   memcpy(Buffer, R.getData(), BufferSize);
-  Offset = *(int *) Buffer;
+  Rewind();
   
   return true;
@@ -406,2 +410,8 @@
   return true;
 }
+
+// Reset to start of buffer
+void EvidenceHistory::Rewind() {
+
+  if (Buffer != NULL) Offset = *(int *) Buffer;
+}
Index: Evidence/Evidence.h
===================================================================
--- Evidence/Evidence.h	(revision 209)
+++ Evidence/Evidence.h	(revision 212)
@@ -91,4 +91,5 @@
 	bool GetHistory();
 	bool Next(int &, int &, void *&);
+	void Rewind();
 };
 #endif
Index: Evidence/readme.txt
===================================================================
--- Evidence/readme.txt	(revision 209)
+++ Evidence/readme.txt	(revision 212)
@@ -28,4 +28,5 @@
 			When regular expression compiling results in error, State is set to ERROR, not
 			FATAL. The erroneous expression is ignored in the following.
+25/5/2010	Service history remains available if service itself become unavailable
 			
 
