File: DETECUSE\detecuse.cpp

    1 /*
    2 $Header: /vol/baal-vol3/projekt98/quellen/XCTL_32/DETECUSE/detecuse.cpp,v 1.40 2004/08/16 13:55:14 reinecke Exp $
    3 
    4 Projekt   : XCTL
    5 Subsystem : Detektoren
    6 Autor     : Jan Picard <picard@informatik.hu-berlin.de> 2001-2002
    7           Institut fuer Informatik,
    8           Humboldt-Universitaet Berlin
    9 Inhalt    : Code fuer das Interface des Detektoren-Subsystems
   10 */
   11 
   12 #include "utils\u_utils.h"
   13 #include "winresrc\rc_def.h" // Ressourcen-IDs
   14 #include <string.h>
   15 
   16 // TCurve
   17 //#include "datavisa\datavisa.h"
   18 
   19 #include "detecuse\detecuse.h"
   20 #include "detecuse\detecmes.h"
   21 #include "detecuse\detecgui.h"
   22 
   23 #include "utils\CheckMemory.h"  //DUMPMEM
   24 
   25 //--||--\\--||--//--||--\\--||--//--||--\\--||--//--||--\\--||--//--||--\\--||--
   26 
   27 // #############################################################################
   28 // Implementationsdetails fuer TDetectorManager
   29 //
   30 // Da BC45 den STL-Datentyp vector<TDetector*> nicht unterstuetzt,
   31 // hier eine Implementation als verkettete Liste.
   32 // Diese Details sind absichtlich ausserhalb der Klassendeklaration von
   33 // TDetectorManager realisiert, damit diese Implementation nach Umstieg auf VC++
   34 // geaendert werden kann.
   35 // #############################################################################
   36 
   37 //! Verkettete Liste von Zeigern auf TDetector-Objekte
   38 class TDListNode
   39 {
   40 public:
   41         TDListNode();
   42         ~TDListNode();
   43 
   44         //! fuegt einen TDetector-Zeiger zum Container hinzu
   45         void push_back(TDetector*);
   46 
   47         //! gibt den im entsprechenden Knoten gespeicherten TDetector-Zeiger zurueck
   48         TDetector* node()
   49         {
   50                 return m_detector;
   51         };
   52 
   53         //! gibt den naechsten Knoten der verketteten Liste zurueck
   54         TDListNode* next()
   55         {
   56                 return m_next;
   57         };
   58 
   59         //! gibt die Laenge der Liste zurueck
   60         int size()
   61         {
   62                 return m_size;
   63         };
   64 
   65 private:
   66 
   67         //! der in diesem Knoten gespeicherte Detektor
   68         TDetector* m_detector;
   69 
   70         //! Zeiger auf den naechsten Knoten der Liste
   71         TDListNode* m_next;
   72 
   73         //! Laenge der Liste
   74         int m_size;
   75 };
   76 
   77 TDListNode::TDListNode()
   78 {
   79         m_next= 0;
   80         m_detector= 0;
   81         m_size= 0;
   82 }
   83 
   84 TDListNode::~TDListNode()
   85 {
   86         // rekursive Destruktion
   87         _FREEOBJ(m_next);
   88 
   89         _FREEOBJ(m_detector);
   90 }
   91 
   92 void TDListNode::push_back(TDetector* param)
   93 {
   94         if ( m_detector == 0 )
   95                 m_detector= param;
   96         else
   97         {
   98                 if (m_next == 0)
   99                         m_next= new TDListNode();
  100 
  101                 m_next->push_back(param);
  102         }
  103         m_size++;
  104 }
  105 
  106 static TDListNode* DetectorContainer;
  107 
  108 //******************************************************************************
  109 //########### Methoden zum Verwalten der Detektoren ############################
  110 //******************************************************************************
  111 
  112 TDetectorManager::TDetectorManager()
  113 {
  114         SetInfo("Erstellen der Detektoren-Liste");
  115 
  116         DetectorContainer= new TDListNode();
  117 
  118         int id= 0;
  119         char Ident[20];
  120         char buf[127];
  121 
  122         // Alle "deviceX"-Abschnitte der hardware.ini abarbeiten,
  123         // fuer jeden gueltigen Abschnitt wird ein TDetector-Objekt erstellt
  124         do
  125         {
  126                 sprintf( Ident, "Device%d", id );
  127                 GetPrivateProfileString( Ident, "Type", "", buf, MaxString, GetHWFile() );
  128 
  129                 // Der kuerzeste Typ ist "PSD", jeder kuerzere Wert ist entweder falsch
  130                 // oder gar nicht deklariert ( buf == "" )
  131                 if ( strlen(buf) < 3)
  132                         break;
  133 
  134                 CreateDetector(buf, id);
  135                 id++;
  136         }
  137         while (1);
  138 
  139         if (DetectorContainer->node() == 0)
  140         {
  141                 MessageBox(0, "Es wurde kein nutzbarer Detektor gefunden.\n"
  142                                    "Das Programm wird jetzt beendet",
  143                                    "Kritischer Fehler", MBFAILURE);
  144 
  145                 _FREEOBJ(DetectorContainer);    //hp
  146                 exit(4);
  147         }
  148 
  149         ActiveDetector= DetectorContainer->node();
  150 }
  151 
  152 TDetectorManager::~TDetectorManager( void )
  153 {
  154         _FREEOBJ(DetectorContainer);
  155 };
  156 
  157 TDetectorManager& TDetectorManager::DetectorManager()
  158 {
  159         // die Singleton-Instanz
  160         static TDetectorManager theDetectorManager;
  161 
  162         return theDetectorManager;
  163 }
  164 
  165 void TDetectorManager::CreateDetector(const char* type, int id)
  166 {
  167         TDetector* newDetector;
  168 
  169         char szDetectorType[MaxString];
  170         strcpy(szDetectorType, type);
  171         strupr(szDetectorType);
  172 
  173         if ( strcmp( szDetectorType, "GENERIC" ) == 0)
  174                 newDetector= new TGenericDetector(id);
  175         else
  176                 if ( strcmp( szDetectorType, "STOE-PSD" ) == 0)
  177                         newDetector= new TStoePsd(id);
  178                 else
  179                         if ( strcmp( szDetectorType, "RADICON" ) == 0)
  180                                 newDetector= new TRadicon(id);
  181                         else
  182                                 if ( strcmp( szDetectorType, "BRAUN-PSD" ) == 0)
  183                                         newDetector= new TBraunPsd(id);
  184                                 else
  185                                         if ( strcmp( szDetectorType, "PSD" ) == 0)
  186                                                 newDetector= new TOneDimTestDetector(id);
  187                                         else
  188                                                 if ( strcmp( szDetectorType, "TEST" ) == 0)
  189                                                         newDetector= new Testdev(id);
  190                                                 else
  191                                                         newDetector= new TZeroDimSimpleTestDetector(id);
  192 
  193         char buf[127];
  194         sprintf( buf, "Initialisieren des Detektors %s",
  195                          newDetector->GetCharacteristic() );
  196         SetInfo( buf );
  197 
  198         // Versuch, den Detektor zu initalisieren. Gibt Initialize() FALSE
  199         // zurueck, ist der Detektor nicht nutzbar. Das Detektor-Objekt
  200         // wird zerstoert und nicht in den DetectorContainer eingefuegt.
  201         if (newDetector->Initialize())
  202                 DetectorContainer->push_back(newDetector);
  203         else
  204         {
  205                 sprintf( buf, "Detektor %s konnte nicht initialisiert werden.",
  206                                  newDetector->GetCharacteristic() );
  207                 MessageBox( GetFocus( ), buf, "Detector-Fehler", MBSTOP );
  208 
  209                 _FREEOBJ(newDetector);
  210         }
  211 }
  212 
  213 BOOL TDetectorManager::DimAvailable(int dimension) const
  214 {
  215         // Da sich die Liste der nutzbaren Detektoren nicht nach der Erstellung
  216         // nicht mehr aendert, kann das Ergebnis zwischengespeichert werden.
  217         static BOOL bDim[3]= { FALSE, FALSE, FALSE };
  218         static BOOL bIsCached= FALSE;
  219 
  220         if ( ( dimension < 0 ) || ( dimension > 2) )
  221                 return FALSE;
  222 
  223         if ( bIsCached == FALSE )
  224         {
  225                 TDListNode* DCIterator= DetectorContainer;
  226 
  227                 // Iterieren ueber den Container und Ermitteln, ob von jeder Dimension
  228                 // mindestens ein Detektor nutzbar ist.
  229                 while ( ( DCIterator != 0 ) && ( DCIterator->node() != 0 ) )
  230                 {
  231                         bDim[DCIterator->node()->GetDimension()]= TRUE;
  232                         DCIterator= DCIterator->next();
  233                 }
  234 
  235                 bIsCached= TRUE;
  236         }
  237 
  238         return bDim[dimension];
  239 }
  240 
  241 BOOL TDetectorManager::IsValidId(int n) const
  242 {
  243         return ( ( n >= 0 ) && ( n <= DetectorContainer->size()) );
  244 }
  245 
  246 TDetector* TDetectorManager::GetDetector( void ) const
  247 {
  248         return ActiveDetector;
  249 }
  250 
  251 TDetector* TDetectorManager::GetDetector( int n, int nFilterDimension ) const
  252 {
  253         if (! IsValidId(n) )
  254                 return ActiveDetector;
  255 
  256         TDListNode* DCIterator= DetectorContainer;
  257         TDetector* theDetector;
  258         int nCounter= 0;
  259 
  260         // nur wenn die Dimension gefiltert wird
  261         if ( nFilterDimension == 0 || nFilterDimension == 1 )
  262         {
  263                 while ( ( DCIterator != 0 ) && ( DCIterator->node() != 0 ) )
  264                 {
  265                         theDetector= DCIterator->node();
  266                         if ( theDetector->GetDimension() == nFilterDimension )
  267                         {
  268                                 // nur wenn es der nte Detektor der gesuchten Dimension ist
  269                                 if ( nCounter == n )
  270                                         return theDetector;
  271 
  272                                 nCounter++;
  273                         }
  274                         DCIterator= DCIterator->next();
  275                 }
  276                 // nicht gefunden
  277                 return ActiveDetector;
  278         }
  279 
  280         while ( ( DCIterator != 0 ) && ( DCIterator->node() != 0 ) )
  281         {
  282                 // den nten Detektor zurueckgeben
  283                 if ( nCounter == n )
  284                         return DCIterator->node();
  285                 nCounter++;
  286 
  287                 DCIterator= DCIterator->next();
  288         }
  289 
  290         return ActiveDetector;
  291 }
  292 
  293 BOOL TDetectorManager::SetDetector( int n, int nFilterDimension )
  294 {
  295         if (! IsValidId(n) )
  296                 return FALSE;
  297 
  298         TDListNode* DCIterator= DetectorContainer;
  299         TDetector* theDetector;
  300         int nCounter= 0;
  301 
  302         // nur wenn die Dimension gefiltert wird
  303         if ( nFilterDimension == 0 || nFilterDimension == 1 )
  304         {
  305                 while ( ( DCIterator != 0 ) && ( DCIterator->node() != 0 ) )
  306                 {
  307                         theDetector= DCIterator->node();
  308                         if ( theDetector->GetDimension() == nFilterDimension )
  309                         {
  310                                 // nur wenn es der nte Detektor der gesuchten Dimension ist
  311                                 if ( nCounter == n )
  312                                 {
  313                                         ActiveDetector= theDetector;
  314                                         return TRUE;
  315                                 }
  316 
  317                                 nCounter++;
  318                         }
  319                         DCIterator= DCIterator->next();
  320                 }
  321                 return FALSE;
  322         }
  323 
  324         while ( ( DCIterator != 0 ) && ( DCIterator->node() != 0 ) )
  325         {
  326                 // den nten Detektor aktivieren
  327                 if ( nCounter == n )
  328                 {
  329                         ActiveDetector= DCIterator->node();
  330                         return TRUE;
  331                 }
  332                 nCounter++;
  333                 DCIterator= DCIterator->next();
  334         }
  335 
  336         return FALSE;
  337 }
  338 
  339 BOOL TDetectorManager::SetDetector( const TDetector* newDetector )
  340 {
  341         TDListNode* DCIterator= DetectorContainer;
  342         TDetector* theDetector;
  343 
  344         // nur wenn dieser Detektor in unserer Liste vorkommt
  345         // eigentlich eine Vorsichtsmassnahmen
  346         while ( ( DCIterator != 0 ) && ( DCIterator->node() != 0 ) )
  347         {
  348                 theDetector= DCIterator->node();
  349                 if ( theDetector == newDetector )
  350                 {
  351                         ActiveDetector= theDetector;
  352                         return TRUE;
  353                 }
  354                 DCIterator= DCIterator->next();
  355         }
  356         return FALSE;
  357 }
  358 
  359 void TDetectorManager::FillDetectorComboBox( HWND comboBox, int nFilterDimension) const
  360 {
  361         TDListNode* DCIterator= DetectorContainer;
  362         TDetector* theDetector;
  363 
  364         while ( ( DCIterator != 0 ) && ( DCIterator->node() != 0 ) )
  365         {
  366                 theDetector= DCIterator->node();
  367                 switch (nFilterDimension)
  368                 {
  369                         case 0:
  370                         case 1:
  371                         case 2:
  372                                 if ( theDetector->GetDimension() == nFilterDimension )
  373                                         ComboBox_AddString( comboBox, theDetector->GetCharacteristic() );
  374                                 break;
  375 
  376                         default:
  377                                 ComboBox_AddString( comboBox, theDetector->GetCharacteristic() );
  378                                 break;
  379                 }
  380                 DCIterator= DCIterator->next();
  381         }
  382 }
  383 
  384 int TDetectorManager::GetIdByDescription( LPCSTR detectorname ) const
  385 {
  386         int nCounter= 0;
  387 
  388         TDListNode* DCIterator= DetectorContainer;
  389 
  390         while ( ( DCIterator != 0 ) && ( DCIterator->node() != 0 ) )
  391         {
  392                 if ( strcmp( DCIterator->node()->GetCharacteristic(), detectorname ) == 0 )
  393                         return nCounter;
  394 
  395                 nCounter++;
  396                 DCIterator= DCIterator->next();
  397         }
  398         return -1;
  399 }
  400 
  401 //******************************************************************************
  402 // TDetector
  403 //******************************************************************************
  404 
  405 TDetector::TDetector(int id)
  406 {
  407         nId= id;
  408         exposure= TExposureSettings( 0.7f, 20000 );
  409         fIntensity= 1.0f;
  410         fSigma= 0.1f;
  411         bDataValid= FALSE;
  412         bActive= FALSE;
  413         hWndFrame= GetFrameHandle();
  414         hControlWnd= NULL;
  415         hCounterWnd= NULL;
  416         uAskTime= 300;
  417 
  418         LoadDetectorSettings();
  419 }
  420 
  421 TDetector::~TDetector( )
  422 {
  423         SaveDetectorSettings();
  424 }
  425 
  426 void TDetector::LoadDetectorSettings()
  427 {
  428         char buf[ MaxString ];
  429 
  430         GetPrivateProfileString( "Name", "Counter", szCharacteristic);
  431 
  432         GetPrivateProfileString( "Debug", "0", buf);
  433         bDebug= ( atoi( buf ) != 0 );
  434 
  435         GetPrivateProfileString( "ExposureTime", "4.0", buf);
  436         exposure.SetExposureTime( atof( buf ));
  437 
  438         GetPrivateProfileString( "ExposureCounts", "10000", buf);
  439         exposure.SetExposureCounts( atol( buf ));
  440 }
  441 
  442 void TDetector::SaveDetectorSettings() const
  443 {
  444         char buf[ MaxString ];
  445 
  446         sprintf( buf, "%.2f", exposure.GetExposureTime() );
  447         WritePrivateProfileString( "ExposureTime", buf);
  448         sprintf( buf, "%ld", exposure.GetExposureCounts() );
  449         WritePrivateProfileString( "ExposureCounts", buf);
  450 }
  451 
  452 BOOL TDetector::SetExposureSettings (const TExposureSettings& newExposureSettings)
  453 {
  454         exposure= newExposureSettings;
  455 
  456         return SetParameters();
  457 }
  458 
  459 BOOL TDetector::Initialize( void )
  460 {
  461         PushSettings( );
  462         return TRUE;
  463 }
  464 
  465 void TDetector::UpdateViews(BOOL bDisplayOnly) const
  466 {
  467         if ( GetCounterWnd() )
  468                 // Display benachrichtigen
  469                 PostMessage( GetCounterWnd(), WM_COMMAND, cm_CounterSet, nId );
  470 
  471         if ( bDisplayOnly )
  472                 return;
  473 
  474         if ( GetControlWnd() )
  475                 // Daten-Empfaenger benachrichtigen
  476                 PostMessage( GetControlWnd(), WM_COMMAND, cm_CounterSet, nId );
  477 }
  478 
  479 BOOL TDetector::SetParameters( void )
  480 {
  481         // Wenn keine Messung lief, einfach Parameter setzen
  482         if ( bActive == FALSE )
  483                 return _SetParameters();
  484 
  485         // Sonst Messung erst beenden, Parameter setzen und Messung wieder starten
  486         MeasureStop();
  487         BOOL bRetCode= _SetParameters();
  488         MeasureStart();
  489         return bRetCode;
  490 }
  491 
  492 TDetector::PushSettings( void )
  493 {
  494         Settings.exposure= exposure;
  495         return TRUE;
  496 }
  497 
  498 TDetector::PopSettings( void )
  499 {
  500         exposure= Settings.exposure;
  501 
  502         SetParameters( );
  503 
  504         return TRUE;
  505 }
  506 
  507 //! Einfache Refaktorisierung (Methode extrahieren)
  508 //! Laedt den Wert fuer einen angegebenen Schluessel aus der hardware.ini
  509 //! und schreibt bei Bedarf einen Default-Wert zurueck.
  510 DWORD TDetector::GetPrivateProfileString(LPCSTR lpKeyName, LPCSTR lpDefault, LPSTR lpReturnedString, UINT iMaxLen ) const
  511 {
  512         char Ident[20];
  513         sprintf( Ident, "Device%d", GetId() );
  514 
  515         DWORD ret= ::GetPrivateProfileString(
  516                                         Ident, lpKeyName, lpDefault, lpReturnedString, iMaxLen, GetHWFile() );
  517 
  518         if ( CreateIniDefaults() )
  519                 ::WritePrivateProfileString( Ident, lpKeyName, lpReturnedString, GetHWFile());
  520 
  521         return ret;
  522 }
  523 
  524 DWORD
  525 TDetector::WritePrivateProfileString( LPCSTR lpKeyName, LPCSTR lpString) const
  526 {
  527         char Ident[20];
  528         sprintf( Ident, "Device%d", GetId() );
  529 
  530         return ::WritePrivateProfileString( Ident, lpKeyName, lpString, GetHWFile());
  531 }
  532 
  533 float TDetector::CalculateSigma(float intensity, float factor)
  534 {
  535         if ( intensity == 0.0 )
  536                 return 1.0;
  537 
  538         return factor * sqrt(intensity) / intensity;
  539 }
  540 
  541 double TDetector::MillisecondsToSeconds( DWORD milliseconds )
  542 {
  543         double integerPart= ( (double)milliseconds ) / 1000.0;
  544         double fractionalPart= ( (double)(milliseconds % 1000) ) / 1000.0;
  545         return ( integerPart + fractionalPart );
  546 }
  547 
  548 //############################################################################
  549 // TZeroDimDetector
  550 //############################################################################
  551 
  552 // time event handling
  553 int nEventsToCall;
  554 int nEvent;
  555 int nEventsCalled;
  556 float fEventIntensity;
  557 HWND hEventControlWnd;
  558 BOOL bEventDataValid;
  559 
  560 TZeroDimDetector::TZeroDimDetector(int id) : TDetector(id)
  561 {
  562         bSound= FALSE;
  563         LoadDetectorSettings();
  564 }
  565 
  566 TZeroDimDetector::~TZeroDimDetector()
  567 {
  568         SaveDetectorSettings();
  569 }
  570 
  571 void TZeroDimDetector::SetSound(BOOL bSoundParam)
  572 {
  573         bSound= bSoundParam;
  574 }
  575 
  576 void TZeroDimDetector::LoadDetectorSettings()
  577 {
  578         char buf[ MaxString ];
  579 
  580         GetPrivateProfileString( "Sound", "1", buf);
  581         bSound= atoi( buf );
  582 }
  583 
  584 void TZeroDimDetector::SaveDetectorSettings() const
  585 {
  586         char buf[ MaxString ];
  587 
  588         sprintf( buf, "%d", bSound );
  589         WritePrivateProfileString( "Sound", buf);
  590 }
  591 
  592 BOOL TZeroDimDetector::Initialize( void )
  593 {
  594         return TDetector::Initialize();
  595 }
  596 
  597 int TZeroDimDetector::MeasureStart( void )
  598 {
  599         if (bActive)
  600                 MeasureStop( );
  601 
  602         if ( bDebug )
  603                 SetInfo( "MStart" );
  604 
  605         if ( ! GetControlWnd() && ! GetCounterWnd() )
  606                 return R_Failure;
  607 
  608         uAskTime= TRange<UINT>(500, 7000).ForceIntoRange(
  609                                    GetExposureSettings().GetExposureTime() * 1100 );
  610 
  611         SetTimer( hWndFrame, DetectorTimerIdStart + GetId(), uAskTime, NULL );
  612         bDataValid= FALSE;
  613         bActive= TRUE;
  614         return R_MeasOk;
  615 }
  616 
  617 int TZeroDimDetector::MeasureStop( void )
  618 {
  619         if ( !bActive )
  620                 return R_MeasOk;
  621 
  622         KillTimer( hWndFrame, DetectorTimerIdStart + GetId() );
  623 
  624         if ( bDebug && bActive )
  625                 SetInfo( "MStop" );
  626 
  627         bActive= FALSE;
  628 
  629         return R_MeasOk;
  630 }
  631 
  632 int TZeroDimDetector::GetIntegral( float &data )
  633 {
  634         data= 0.0;
  635 
  636         if ( !bDataValid )
  637                 return R_Failure;
  638 
  639         data= fIntensity;
  640 
  641         fSigma= CalculateSigma ( fIntensity );
  642 
  643         return R_OK;
  644 }
  645 
  646 //! Methode wird periodisch aufgerufen (Initialisierung in InitializeEvent)
  647 //! realisiert Intensitaetsmessung waehrend dem zeitintervall zwischen zwei
  648 //! Aufrufen der Methode (fuer kontinuierlichen Scan)
  649 //! anschliessend wird das Scanfenster benachrichtigt
  650 //! (cm_CounterSet waehrend messung; cm_SteeringReady bei letzter Messung)
  651 //! hier nur Simulation
  652 CALLBACK TZeroDimDetector::EventHandler( UINT, UINT, DWORD, DWORD, DWORD )
  653 {
  654         double angx;
  655 
  656         nEventsCalled++;
  657         // mlGetDistance(angx);
  658         angx= ( nEventsCalled - nEventsToCall / 2 ) * 0.246;
  659         angx= angx * angx / 11.3;
  660         fEventIntensity= 32000 / ( 1 + 1.8 * angx * angx ) + ( rand( ) % 80 ) + 270;
  661 
  662         //! Messwert gueltig
  663         bEventDataValid= TRUE;
  664         PostMessage( hEventControlWnd, WM_COMMAND, cm_CounterSet, nEventsCalled );
  665 
  666         if ( nEventsCalled == nEventsToCall )
  667         {
  668                 timeKillEvent( nEvent );
  669                 PostMessage( hEventControlWnd, WM_COMMAND, cm_SteeringReady, 0l );
  670                 //    bEventDataValid= FALSE;
  671         }
  672 
  673         return R_OK;
  674 }
  675 
  676 //! macht dem Detektor das Fenster bekannt, an das er innerhalb von EventHandler
  677 //! seine Nachrichten schicken soll
  678 //! (fuer kontinuierlichen Scan)
  679 void TZeroDimDetector::SetEventHost( HWND hwnd)
  680 {
  681         hEventControlWnd= hwnd;
  682 }
  683 
  684 //! loescht Detektor-Event
  685 //! sorgt, dafuer dass Eventhandler nicht mehr aufgerufen wird
  686 //! (fuer kontinuierlichen Scan)
  687 void TZeroDimDetector::KillEvent(void)
  688 {
  689         timeKillEvent( nEvent );
  690 }
  691 
  692 //! liefert die durch EventHandler gemessene Intensitaet im Parameter zurueck
  693 //! Rueckkehrcode TRUE
  694 //! nur einmal Auslesen eines Wertes erlaubt
  695 //! bei wiederholtem Ausleseversuch 0 in Parameter und
  696 //! Rueckkehrcode FALSE
  697 //! (fuer kontinuierlichen Scan)
  698 BOOL TZeroDimDetector::GetEventIntensity( float &data)
  699 {
  700         data= 0;
  701 
  702         if (!bEventDataValid)
  703                 return FALSE;
  704 
  705         data= fEventIntensity;
  706 
  707         bEventDataValid= FALSE;
  708 
  709         return TRUE;
  710 }
  711 
  712 //! initialisiert ein periodisches Aufrufen der Methode EventHandler
  713 //! 2. Parameter gibt Anzahl der Aufrufe an
  714 //! Aufrufintervall entspricht der Messzeit
  715 //! Rueckkehrcode FALSE wenn Aufrufintervall < 0.1 sek.
  716 //! sonst TRUE (wenn erfolgreich)
  717 //! (fuer kontinuierlichen Scan)
  718 BOOL TZeroDimDetector::InitializeEvent( HWND hwnd, int ec )
  719 {
  720         int EventTime= 1000.0 * exposure.GetExposureTime();
  721 
  722         SetControlWnd(hwnd);
  723         nEventsCalled= 0;
  724         nEventsToCall= ec;
  725         // check calltime
  726 
  727         if ( EventTime <= 100 )
  728         {
  729                 MessageBox( GetFocus( ), "Meßzeit wurde zu klein gewählt !", "InitializeEvent", MBINFO );
  730                 return FALSE;
  731         }
  732 
  733         if ( NULL != GetControlWnd() )
  734                 nEvent= timeSetEvent( EventTime, 1, ( LPTIMECALLBACK ) TZeroDimDetector::EventHandler, 0, TIME_PERIODIC );
  735 
  736         bDataValid= FALSE;
  737 
  738         return TRUE;
  739 }
  740 
  741 //############################################################################
  742 // TOneDimDetector
  743 //############################################################################
  744 TOneDimDetector::TOneDimDetector(int id) : TDetector(id), hCountBuf(0)
  745 {
  746         SetDataType( PsdPositionData );
  747         bSoftOverflow= bHardOverflow= bSignalGrowUp= bHVControl= FALSE;
  748         m_Axis= (EAxisType)0;
  749 
  750         strcpy(szUnit, "");
  751         LoadDetectorSettings();
  752 }
  753 
  754 TOneDimDetector::~TOneDimDetector( )
  755 {
  756         //21.08.2004 MEMCORRECT if (hCountBuf) HeapFree(GetProcessHeap(),0,hCountBuf);  hCountBuf= 0;
  757         _FREELIST(hCountBuf);
  758 
  759         SaveDetectorSettings();
  760 }
  761 
  762 void TOneDimDetector::LoadDetectorSettings()
  763 {
  764         char buf[ MaxString ];
  765 
  766         GetPrivateProfileString( "EnergyScale", "2", buf);
  767         SetEnergyScale( (UINT)atoi(buf) );
  768 
  769         GetPrivateProfileString( "PositionScale", "1", buf);
  770         SetPositionScale( (UINT)atoi(buf) );
  771 
  772         GetPrivateProfileString( "OverflowIntensity", "50000.0", buf);
  773         OverflowIntensity= atof( buf );
  774 
  775         GetPrivateProfileString( "SignalGrowUp", "0", buf);
  776         bSignalGrowUp= ( atoi( buf ) != 0 );
  777 
  778         GetPrivateProfileString( "HVRegelung", "0", buf);
  779         bHVControl= ( atoi( buf ) != 0 );
  780 
  781         GetPrivateProfileString( "ReadLeftFirst", "1", buf);
  782         bReadLeftFirst= ( atoi ( buf ) != 0 );
  783 
  784         GetPrivateProfileString( "Unit", "Sekunden", szUnit, _MAXLENUNIT);
  785         eUnit= UnitEnum( szUnit );
  786 
  787         GetPrivateProfileString( "AngleStep", "1.0", buf);
  788         fAngleStep= atof( buf ); // in Motoreinheit und für Scale=0 lesen; d.h. nicht SetAngleStep benutzen - 
  789 
  790         GetPrivateProfileString( "Digits", "5", buf ); // Nachkommastellen für die Kanalbreite in arcsec
  791     nDigits= atoi( buf );
  792 
  793         GetPrivateProfileString( "MaxChannels", "4096", buf);
  794         nMaxChannels= atoi( buf );
  795 
  796         // First- und LastChannel direkt einlesen, später bei SetChannelRange ggf. korrigieren
  797         GetPrivateProfileString( "FirstChannel", "0", buf);
  798         int firstCh= atoi( buf );
  799 
  800         GetPrivateProfileString( "LastChannel", "4095", buf);
  801         int lastCh= atoi( buf );
  802 
  803         // benötigt <uPositionScale>, <nMaxChannels> und <eDataType>==PsdPositionData
  804         SetChannelRange( firstCh, lastCh );
  805 
  806         // benötigt First und LastChannel
  807         GetPrivateProfileString( "AddedChannels", "4", buf);
  808         SetAddedChannels( atoi( buf ) );
  809 
  810         GetPrivateProfileString( "SteeringAxis", "0", buf);
  811         m_Axis= mlParsingAxis(buf); // ggf. (TAxisType)0
  812 }
  813 
  814 void TOneDimDetector::SaveDetectorSettings() const
  815 {
  816         char aBuf[ MaxString ];
  817         char aFormat[ MaxString ];
  818 
  819         sprintf( aBuf, "%u", uEnergyScale );
  820         WritePrivateProfileString( "EnergyScale", aBuf);
  821 
  822         sprintf( aBuf, "%u", uPositionScale );
  823         WritePrivateProfileString( "PositionScale", aBuf);
  824 
  825         sprintf( aBuf, "%d", ( bHVControl ? 1 : 0 ) );
  826         WritePrivateProfileString( "HVRegelung", aBuf);
  827 
  828         WritePrivateProfileString( "Unit", szUnit);
  829 
  830         sprintf( aBuf, "%d", nMaxChannels);
  831         WritePrivateProfileString( "MaxChannels", aBuf);        
  832 
  833         sprintf( aBuf, "%d", GetFirstChannel() ); // umrechnen auf Scale
  834         WritePrivateProfileString( "FirstChannel", aBuf);
  835 
  836         sprintf( aBuf, "%d", GetLastChannel() ); // umrechnen auf Scale
  837         WritePrivateProfileString( "LastChannel", aBuf );
  838 
  839         sprintf( aBuf, "%d", nAddedChannels );
  840         WritePrivateProfileString( "AddedChannels", aBuf);
  841 
  842         sprintf( aBuf, "%f", OverflowIntensity );
  843         WritePrivateProfileString( "OverflowIntensity", aBuf);
  844 
  845         sprintf( aBuf, "%d", ( bSignalGrowUp ? 1 : 0 ) );
  846         WritePrivateProfileString( "SignalGrowUp", aBuf);
  847 
  848         sprintf( aBuf, "%d", ( bReadLeftFirst ? 1 : 0 ) );
  849         WritePrivateProfileString( "ReadLeftFirst", aBuf);
  850 
  851         sprintf( aBuf, "%d", nDigits );
  852         WritePrivateProfileString( "Digits", aBuf); // Nachkommastellen der Kanalbreite in arcsec speichern
  853                 
  854         sprintf(aFormat, "%s%d%s", "%.", nDigits, "f"); // Anzahl der Nachkommastellen beachten
  855         sprintf( aBuf, aFormat, fAngleStep ); // in Motoreinheit und für Scale=0 speichern; d.h. nicht GetAngleStep benutzen
  856         WritePrivateProfileString( "AngleStep", aBuf);
  857 
  858         WritePrivateProfileString( "MJ_Channel", "0"); // 10.12.2002 Kulllmann, Reinecker Kanal-Offset löschen
  859 }
  860 
  861 BOOL TOneDimDetector::Initialize( void )
  862 {
  863         TDetector::Initialize( );
  864 
  865         if ( GetWidth() == 0.0 )
  866         {
  867                 MessageBox( GetFocus( ), "Psd ist nicht kalibriert !", "Meldung", MBSTOP );
  868                 fAngleStep= 1.0;
  869                 SetAddedChannels( 4 );
  870         }
  871 
  872         // allocate memory
  873         //21.08.2004 MEMCORRECT hCountBuf= (HGLOBAL)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,GetBufferSize() * sizeof(DWORD));
  874         hCountBuf= new char[ GetBufferSize() * sizeof(DWORD) ];
  875 
  876         //hp initial hardware check
  877         if (PsdInit() != R_OK)
  878                 return(false);
  879 
  880         PushSettings( );
  881 
  882         return TRUE;
  883 }
  884 
  885 BOOL TOneDimDetector::RunSpecificParametersDlg( HWND aParentWnd )
  886 {
  887         //! neu Kullmann+Reinecker: TheModeless durch PsdParamDlg ersetzt; extern entfernt
  888         static TModelessDlg *PsdParamDlg= 0;
  889 
  890         if ( (!PsdParamDlg) || (!PsdParamDlg->GetHandle()) )
  891         { //! GetHandle() ist wichtig für den Fall, dass sich das Dialogfenster selbst zerstört hat !!!
  892                 PsdParamDlg= new TPsdParametersDlg(&PsdParamDlg);
  893                 if ( PsdParamDlg ) PsdParamDlg->Initialize( dlGetInstance(), aParentWnd );
  894                 return TRUE;
  895         }
  896         else
  897         {
  898                 _FREEOBJ(PsdParamDlg);
  899                 return FALSE;
  900         }
  901 }
  902 
  903 void TOneDimDetector::SetAddedChannels(int nParam)
  904 {
  905         nAddedChannels= TRange<int>(1, GetChannelNumber()).ForceIntoRange(nParam);
  906 }
  907 
  908 int TOneDimDetector::GetFirstChannel() const 
  909 {
  910         if ( eDataType == PsdEnergyData )               
  911                 return 0; // volle Kanalbreite benutzen
  912         else
  913                 // FirstChannel auf Scale umrechnen
  914                 return max( 0, min(GetScaledMaxChannels(uPositionScale)-1, nFirstChannel >> uPositionScale) );
  915 };
  916 
  917 int TOneDimDetector::GetLastChannel() const 
  918 {
  919         if ( eDataType == PsdEnergyData )               
  920                 return GetScaledMaxChannels(uEnergyScale)-1; // volle Kanalbreite benutzen
  921         else
  922                 // LastChannel auf Scale umrechnen
  923                 return max( 0, min(GetScaledMaxChannels(uPositionScale)-1, nLastChannel >> uPositionScale) );
  924 };
  925 
  926 void TOneDimDetector::SetChannelRange(int first, int last)
  927 {
  928         if ( eDataType == PsdEnergyData ) return; // First- und LastChannel nicht verändern (sind bei PsdEnergyData allein abhängig von nMaxChannels und EnergyScale)
  929 
  930         // nochrechnen auf <MaxChannels>-Kanäle - siehe PsdReadOut
  931         TRange<int> limit(0, nMaxChannels-1);
  932         first= limit.ForceIntoRange(first << uPositionScale);
  933         last= limit.ForceIntoRange(last << uPositionScale);
  934 
  935         nFirstChannel= min(first, last);
  936         nLastChannel= max(first, last);
  937 }
  938 
  939 UINT TOneDimDetector::GetMaximumChannel( void ) const
  940 {
  941         if ( bReadLeftFirst )
  942                 return uMaximumChannel;
  943 
  944         return ( GetChannelNumber() - uMaximumChannel );
  945 }
  946 
  947 // NEU: Berücksichtigt alle Messwerte und überträgt diese in die Kurve
  948 int TOneDimDetector::FillInCurve( TCurve &curve, EUnitType aMotorUnit )
  949 {
  950         // Vorbedingungen
  951         if ( bHardOverflow )
  952                 return R_HardOverflow;
  953 
  954         UINT addC= max(1, nAddedChannels);
  955 
  956         LPDWORD lpdwCountBuf= (LPDWORD)hCountBuf;
  957 
  958         curve.New( );
  959         // 07.05.2004 curve.FastOpen( );
  960 
  961         double dAngle= 0.0;
  962         double intens= 0.0;
  963         double dWidth= CalcValueInUnit( aMotorUnit, GetAngleStep() ); // GetAngleStep - unabhängig von <AddedChannels>
  964         for ( int idx= 0;idx<GetChannelNumber(); idx++ ) {              
  965                 int index;
  966                 if ( bReadLeftFirst )
  967                         index= idx;
  968                 else // Lesereihenfolge umdrehen (hinten anfangen und dann nach vorn)
  969                         index= (GetChannelNumber()-1) - idx; 
  970 
  971                 intens+= (float)lpdwCountBuf[index]; // <intens> zuerst inkrementieren
  972                 if ( (idx+1) % addC==0 ) { // Kanalgruppe vollständig
  973                         // Zwischenspeichern in floats, da curve.PAdd Referenzen verlangt
  974                         float x= dAngle;
  975                         float y= intens;
  976                         float z= idx;
  977                         curve.PAdd( x, y, z ); // 07.05.2004 FastP...
  978                         intens= 0; // neue Kanalgruppe beginnt
  979                 }
  980                 dAngle += dWidth; // <dAngle> als letztes inkrementieren
  981         }
  982 
  983         // 07.05.2004 curve.FastClose( );
  984 
  985         //! neu akk     
  986         fIntensity= dwIntegratedCounts; //fIntensity= dwIntegratedCounts / dRealTime;
  987         fSigma= CalculateSigma( fIntensity );
  988 
  989         // Ist ein "weicher" Overflow aufgetreten ?
  990         if ( fIntensity >= OverflowIntensity )
  991         {
  992                 bSoftOverflow= TRUE;
  993                 return R_SoftOverflow;
  994         }
  995 
  996         return R_OK;
  997 }
  998 
  999 /*10.07.2004 // ALT: Nicht alle Messwerte werden berücksichtigt, es fehlt IMMER der letzte Wert.
 1000 int TOneDimDetector::FillInCurve( TCurve &curve, EUnitType aMotorUnit )
 1001 {
 1002         // Vorbedingungen
 1003         if ( bHardOverflow )
 1004                 return R_HardOverflow;
 1005 
 1006         UINT addC= max(1, nAddedChannels);
 1007 
 1008         LPDWORD lpdwCountBuf= (LPDWORD)hCountBuf;
 1009 
 1010         curve.New( );
 1011         // 07.05.2004 curve.FastOpen( );
 1012 
 1013         double dAngle= 0.0;
 1014         double intens= 0.0;
 1015         double dWidth= CalcValueInUnit( aMotorUnit, GetWidth()); // GetWidth - berücksichtigt <AddedChannels>
 1016         for ( int idx= 0;idx < (GetChannelNumber() - addC); idx += addC )
 1017         {
 1018                 intens= 0.0;
 1019 
 1020                 for ( int i= 0; i < addC; i++ )
 1021                 {
 1022                         int index;
 1023                         // Summe pro Kanalgruppe ermitteln
 1024                         index= idx + i;
 1025                         if ( !bReadLeftFirst )
 1026                                 index= ( GetChannelNumber() - 1 ) - index;
 1027 
 1028                         intens += ( float ) lpdwCountBuf[index];
 1029                 }
 1030 
 1031                 // Zwischenspeichern in floats, da curve.PAdd Referenzen verlangt
 1032                 float x= dAngle;
 1033                 float y= intens;
 1034                 float z= idx;
 1035                 curve.PAdd( x, y, z ); // 07.05.2004 FastP...
 1036 
 1037                 dAngle += dWidth;
 1038         }
 1039 
 1040         // 07.05.2004 curve.FastClose( );
 1041 
 1042         //! neu akk     
 1043         fIntensity= dwIntegratedCounts; //fIntensity= dwIntegratedCounts / dRealTime;
 1044         fSigma= CalculateSigma( fIntensity );
 1045 
 1046         // Ist ein "weicher" Overflow aufgetreten ?
 1047         if ( fIntensity >= OverflowIntensity )
 1048         {
 1049                 bSoftOverflow= TRUE;
 1050                 return R_SoftOverflow;
 1051         }
 1052 
 1053         return R_OK;
 1054 }*/
 1055 
 1056 int TOneDimDetector::GetIntegral( float &integral )
 1057 {
 1058         integral= 0.0;
 1059 
 1060         if ( bHardOverflow )
 1061                 return R_HardOverflow;
 1062 
 1063         integral= fIntensity= dwIntegratedCounts;
 1064         fSigma= CalculateSigma( fIntensity );
 1065 
 1066         // Ist ein "weicher" Overflow aufgetreten ?
 1067         if ( fIntensity >= OverflowIntensity )
 1068         {
 1069                 bSoftOverflow= TRUE;
 1070                 return R_SoftOverflow;
 1071         }
 1072 
 1073         return R_OK;
 1074 }
 1075 
 1076 int TOneDimDetector::MeasureStart( void )
 1077 {
 1078         if (bActive)
 1079                 MeasureStop( );
 1080 
 1081         if ( !GetControlWnd() && !GetCounterWnd() )
 1082                 return R_Failure;
 1083 
 1084         bSoftOverflow= FALSE;
 1085         bHardOverflow= FALSE;
 1086         bFirstReadOut= TRUE;
 1087 
 1088         if ( R_Failure == PsdStart( ) )
 1089                 return R_Failure;
 1090 
 1091         uAskTime= TRange<UINT>(500, 2000).ForceIntoRange(
 1092                                    GetExposureSettings().GetExposureTime() * 1020 );
 1093 
 1094         // Start-Zeit merken
 1095         dwStartTime= timeGetTime( );
 1096 
 1097         SetTimer( hWndFrame, DetectorTimerIdStart + GetId( ), uAskTime, NULL );
 1098 
 1099         bActive= TRUE;
 1100         bDataValid= FALSE;
 1101 
 1102         return R_MeasOk;
 1103 }
 1104 
 1105 int TOneDimDetector::MeasureStop( void )
 1106 {
 1107         if ( !bActive )
 1108                 return R_MeasOk;
 1109 
 1110         KillTimer( hWndFrame, DetectorTimerIdStart + GetId( ) );
 1111 
 1112         bDataValid= FALSE;
 1113 
 1114         PsdStop( );
 1115 
 1116         bActive= FALSE;
 1117 
 1118         return R_MeasOk;
 1119 }
 1120 
 1121 int TOneDimDetector::PollDetector( void )
 1122 {
 1123         char buf[ MaxString ];
 1124         int retval= R_MeasOk;
 1125 
 1126         KillTimer( hWndFrame, DetectorTimerIdStart + GetId( ) );
 1127 
 1128         if ( !bActive )
 1129                 return R_Failure;
 1130 
 1131         bActive= FALSE;
 1132 
 1133         dwElapsedTime= timeGetTime( ) - dwStartTime;
 1134 
 1135         if ( MillisecondsToSeconds( dwElapsedTime ) < GetExposureSettings().GetExposureTime() )
 1136         {
 1137                 retval= R_MeasInProcess;
 1138                 bActive= TRUE;
 1139 
 1140                 if ( !bSignalGrowUp )
 1141                 {
 1142                         //*** Kein stufenweiser Signalaufbau
 1143                         SetTimer( hWndFrame, DetectorTimerIdStart + GetId( ), uAskTime, NULL );
 1144                         return R_MeasInProcess;
 1145                 }
 1146 
 1147                 //*** Stufenweiser Signalaufbau
 1148                 //FEHLER? Akkumuierter Signalaufbau von TStoePSD::PollDetector übernehmen!
 1149                 if ( PsdReadOut( IntermediateRead ) == R_Failure )
 1150                         return R_Failure;
 1151 
 1152                 dRealTime= MillisecondsToSeconds( dwElapsedTime );
 1153 
 1154                 bFirstReadOut= FALSE;
 1155 
 1156                 long lWaitTime= GetExposureSettings().GetExposureTime() * 1020 - dwElapsedTime;
 1157 
 1158                 uAskTime= TRange<UINT>(500, 2000).ForceIntoRange( lWaitTime );
 1159 
 1160                 SetTimer( hWndFrame, DetectorTimerIdStart + GetId( ), uAskTime, NULL );
 1161 
 1162                 goto SendNotify;
 1163         }
 1164 
 1165         if ( PsdStop( ) == R_Failure )
 1166                 return R_Failure;
 1167 
 1168         dRealTime= MillisecondsToSeconds( dwElapsedTime );
 1169 
 1170         if ( PsdReadOut( FinalRead ) == R_Failure )
 1171                 return R_Failure;
 1172 
 1173         bDataValid= TRUE;
 1174 
 1175 SendNotify:      //*** Benachrichtigen der entsprechenden Fenster ***
 1176 
 1177         if ( dRealTime == 0.0 )
 1178         {
 1179                 SetInfo( "dRealTime == 0.0 Fehler Psd" );
 1180                 DelayTime( 300 );
 1181                 dRealTime= 1.0;
 1182                 PsdStop( );
 1183                 bDataValid= FALSE;
 1184                 return R_Failure;
 1185         }
 1186 
 1187         if ( bHardOverflow )
 1188         {
 1189                 strcpy( buf, "Überlauf Psd ( Hochspannung ? )" );
 1190                 MessageBeep( 0 );
 1191                 retval= R_HardOverflow;
 1192         }
 1193 
 1194         UpdateViews();
 1195 
 1196         return retval;
 1197 }
 1198 
 1199 void TOneDimDetector::SetAngleRange( float )
 1200 {
 1201         //JP!!!!
 1202         return;
 1203 }
 1204 
 1205 BOOL TOneDimDetector::PushSettings( void )
 1206 {
 1207         TDetector::PushSettings( );
 1208         Settings.nAddedChannels= nAddedChannels;
 1209         return TRUE;
 1210 }
 1211 
 1212 BOOL TOneDimDetector::PopSettings( void )
 1213 {
 1214         TDetector::PopSettings( );
 1215         nAddedChannels= Settings.nAddedChannels;
 1216         return TRUE;
 1217 }
 1218 
 1219 float TOneDimDetector::GetAngleStep() const
 1220 {
 1221         // auf Scale umrechnen; ">>" geht nicht, da <fValParam> float ist
 1222         return fAngleStep * pow(2, uPositionScale); // Kanalbreite nur bei Positionspektrum (Energiespektrum hat nur Kanaldarstellung)
 1223 };
 1224 void TOneDimDetector::SetAngleStep( float stp )
 1225 {
 1226         // nochrechnen auf <MaxChannels>-Kanäle: "<<" geht nicht, da <stp> float ist
 1227         fAngleStep= stp / pow(2, uPositionScale); // Kanalbreite nur bei Positionspektrum (Energiespektrum hat nur Kanaldarstellung)
 1228 };
 1229 
 1230 float TOneDimDetector::GetWidth() const
 1231 {
 1232         return nAddedChannels * GetAngleStep(); 
 1233 }
 1234 
 1235 float TOneDimDetector::GetAngleRange() const 
 1236 {
 1237         return GetChannelNumber() * GetAngleStep();  
 1238 }
 1239 
 1240 UINT TOneDimDetector::GetAngleStepDigits( void ) const
 1241 {
 1242         return nDigits;
 1243 }
 1244 
 1245 void TOneDimDetector::SetAngleStepDigits(UINT aDigits) 
 1246 {
 1247         nDigits = aDigits;
 1248 }
 1249 
 1250 void TOneDimDetector::CheckMaximumChannel(UINT channel, DWORD counts)
 1251 {
 1252         // Kanal mit Maximum ermitteln
 1253         if ( dwMaxCounts < counts )
 1254         {
 1255                 uMaximumChannel= channel;
 1256                 dwMaxCounts= counts;
 1257         }
 1258 }
 1259 
 1260 UINT TOneDimDetector::SetEnergyScale(UINT aEnergyScale)
 1261 {
 1262         UINT result= uEnergyScale;
 1263         uEnergyScale= max( 0x0, min(0x3, aEnergyScale) );
 1264         return result;
 1265 }
 1266 
 1267 UINT TOneDimDetector::SetPositionScale(UINT aPositionScale) 
 1268 {
 1269         UINT result= uPositionScale;
 1270         uPositionScale= max( 0x0, min(0x3, aPositionScale) );
 1271         return result;
 1272 };
 1273 
 1274 //##############################################################################
 1275 // TExposureSettings
 1276 //##############################################################################
 1277 
 1278 TExposureSettings::TExposureSettings(
 1279         float exposureTime, DWORD exposureCounts)
 1280                 : CountBounds(10, 300000L), TimeBounds(0.1f, 500.0f)
 1281 {
 1282         SetExposureTime( exposureTime );
 1283         SetExposureCounts( exposureCounts );
 1284 }
 1285 
 1286 void TExposureSettings::SetExposureTime(float exposureTime)
 1287 {
 1288         fExposureTime= TimeBounds.ForceIntoRange( exposureTime );
 1289 }
 1290 
 1291 void TExposureSettings::SetExposureCounts( DWORD exposureCounts )
 1292 {
 1293         dwExposureCounts= CountBounds.ForceIntoRange( exposureCounts );
 1294 }
 1295 
 1296 //##############################################################################
 1297 // TDetectorGUI
 1298 //##############################################################################
 1299 
 1300 void TDetectorGUI::RunPsdCalibrateDialog(HWND hwnd, TCurve &curve)
 1301 {
 1302         TModalDlg *dlg= new TCalibratePsdDlg( curve );
 1303         if ( dlg ) dlg->ExecuteDialog( hwnd );
 1304         _FREEOBJ(dlg);
 1305 }
 1306 
 1307 void TDetectorGUI::RunCommonDevParamDialog( HWND hwnd )
 1308 {
 1309         TModalDlg* dlg= new TCommonDevParamDlg();
 1310         if ( dlg ) dlg->ExecuteDialog( hwnd );
 1311         _FREEOBJ(dlg);
 1312 }
 1313