00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "CalibMuon/DTCalibration/plugins/DTT0CalibrationNew.h"
00011 #include "CalibMuon/DTCalibration/interface/DTCalibDBUtils.h"
00012
00013 #include "FWCore/Framework/interface/Event.h"
00014 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00015
00016 #include "Geometry/Records/interface/MuonGeometryRecord.h"
00017 #include "Geometry/Records/interface/MuonNumberingRecord.h"
00018
00019 #include "DataFormats/DTDigi/interface/DTDigiCollection.h"
00020 #include "CondFormats/DTObjects/interface/DTT0.h"
00021
00022 #include <CondFormats/DTObjects/interface/DTTtrig.h>
00023 #include <CondFormats/DataRecord/interface/DTTtrigRcd.h>
00024
00025 #include "TH1I.h"
00026 #include "TFile.h"
00027 #include "TKey.h"
00028 #include "TSpectrum.h"
00029 #include "TF1.h"
00030
00031 using namespace std;
00032 using namespace edm;
00033
00034
00035
00036 DTT0CalibrationNew::DTT0CalibrationNew(const edm::ParameterSet& pset) {
00037
00038 debug = pset.getUntrackedParameter<bool>("debug");
00039 if(debug)
00040 cout << "[DTT0CalibrationNew]Constructor called!" << endl;
00041
00042
00043 digiLabel = pset.getUntrackedParameter<string>("digiLabel");
00044
00045 dbLabel = pset.getUntrackedParameter<string>("dbLabel", "");
00046
00047
00048 string rootFileName = pset.getUntrackedParameter<string>("rootFileName","DTT0PerLayer.root");
00049 theFile = new TFile(rootFileName.c_str(), "RECREATE");
00050
00051 theCalibWheel = pset.getUntrackedParameter<string>("calibWheel", "All");
00052 if(theCalibWheel != "All") {
00053 stringstream linestr;
00054 int selWheel;
00055 linestr << theCalibWheel;
00056 linestr >> selWheel;
00057 cout << "[DTT0CalibrationNewPerLayer] chosen wheel " << selWheel << endl;
00058 }
00059
00060
00061 theCalibSector = pset.getUntrackedParameter<string>("calibSector", "All");
00062 if(theCalibSector != "All") {
00063 stringstream linestr;
00064 int selSector;
00065 linestr << theCalibSector;
00066 linestr >> selSector;
00067 cout << "[DTT0CalibrationNewPerLayer] chosen sector " << selSector << endl;
00068 }
00069
00070 vector<string> defaultCell;
00071 defaultCell.push_back("None");
00072 cellsWithHistos = pset.getUntrackedParameter<vector<string> >("cellsWithHisto", defaultCell);
00073 for(vector<string>::const_iterator cell = cellsWithHistos.begin(); cell != cellsWithHistos.end(); cell++){
00074 if((*cell) != "None"){
00075 stringstream linestr;
00076 int wheel,sector,station,sl,layer,wire;
00077 linestr << (*cell);
00078 linestr >> wheel >> sector >> station >> sl >> layer >> wire;
00079 wireIdWithHistos.push_back(DTWireId(wheel,station,sector,sl,layer,wire));
00080 }
00081 }
00082
00083 hT0SectorHisto=0;
00084
00085 nevents=0;
00086 eventsForLayerT0 = pset.getParameter<unsigned int>("eventsForLayerT0");
00087 eventsForWireT0 = pset.getParameter<unsigned int>("eventsForWireT0");
00088 tpPeakWidth = pset.getParameter<double>("tpPeakWidth");
00089 tpPeakWidthPerLayer = pset.getParameter<double>("tpPeakWidthPerLayer");
00090 timeBoxWidth = pset.getParameter<unsigned int>("timeBoxWidth");
00091 rejectDigiFromPeak = pset.getParameter<unsigned int>("rejectDigiFromPeak");
00092
00093 spectrum = new TSpectrum(5);
00094 retryForLayerT0 = 0;
00095 }
00096
00097
00098 DTT0CalibrationNew::~DTT0CalibrationNew(){
00099 if(debug)
00100 cout << "[DTT0CalibrationNew]Destructor called!" << endl;
00101
00102 delete spectrum;
00103 theFile->Close();
00104 }
00105
00107 void DTT0CalibrationNew::analyze(const edm::Event & event, const edm::EventSetup& eventSetup) {
00108 if(debug || event.id().event() % 500==0)
00109 cout << "--- [DTT0CalibrationNew] Analysing Event: #Run: " << event.id().run()
00110 << " #Event: " << event.id().event() << endl;
00111 nevents++;
00112
00113
00114 Handle<DTDigiCollection> digis;
00115 event.getByLabel(digiLabel, digis);
00116
00117
00118 eventSetup.get<MuonGeometryRecord>().get(dtGeom);
00119
00120
00121 edm::ESHandle<DTTtrig> tTrigMap;
00122 eventSetup.get<DTTtrigRcd>().get(dbLabel,tTrigMap);
00123
00124
00125 DTDigiCollection::DigiRangeIterator dtLayerIt;
00126 for (dtLayerIt = digis->begin();
00127 dtLayerIt != digis->end();
00128 ++dtLayerIt){
00129
00130 const DTDigiCollection::Range& digiRange = (*dtLayerIt).second;
00131
00132
00133 const DTLayerId layerId = (*dtLayerIt).first;
00134 const DTChamberId chamberId = layerId.superlayerId().chamberId();
00135
00136 if((theCalibWheel != "All") && (layerId.superlayerId().chamberId().wheel() != selWheel))
00137 continue;
00138 if((theCalibSector != "All") && (layerId.superlayerId().chamberId().sector() != selSector))
00139 continue;
00140
00141
00142
00143
00144
00145 float tTrig,tTrigRMS, kFactor;
00146 tTrigMap->get(layerId.superlayerId(), tTrig, tTrigRMS, kFactor, DTTimeUnits::counts );
00147 if(debug&&(nevents <= 1)){
00148 cout << " Superlayer: " << layerId.superlayerId() << endl
00149 << " tTrig,tTrigRMS= " << tTrig << ", " << tTrigRMS << endl;
00150 }
00151
00152
00153 for (DTDigiCollection::const_iterator digi = digiRange.first;
00154 digi != digiRange.second;
00155 digi++) {
00156 double t0 = (*digi).countsTDC();
00157
00158
00159 if(nevents < eventsForLayerT0){
00160
00161 TH1I *hT0LayerHisto = theHistoLayerMap[layerId];
00162
00163 if(hT0LayerHisto == 0){
00164 theFile->cd();
00165 float hT0Min = tTrig - 2*tTrigRMS;
00166 float hT0Max = hT0Min + timeBoxWidth;
00167 hT0LayerHisto = new TH1I(getHistoName(layerId).c_str(),
00168 "T0 from pulses by layer (TDC counts, 1 TDC count = 0.781 ns)",
00169 timeBoxWidth,hT0Min,hT0Max);
00170 if(debug)
00171 cout << " New T0 per Layer Histo: " << hT0LayerHisto->GetName() << endl;
00172 theHistoLayerMap[layerId] = hT0LayerHisto;
00173 }
00174
00175
00176 theFile->cd();
00177 if(hT0LayerHisto != 0) {
00178
00179
00180 hT0LayerHisto->Fill(t0);
00181 }
00182 }
00183
00184
00185 if(nevents>eventsForLayerT0){
00186
00187 const DTWireId wireId(layerId, (*digi).wire());
00188 if(debug) {
00189 cout << " Wire: " << wireId << endl
00190 << " time (TDC counts): " << (*digi).countsTDC()<< endl;
00191 }
00192
00193
00194 vector<DTWireId>::iterator it = find(wireIdWithHistos.begin(),wireIdWithHistos.end(),wireId);
00195 if (it!=wireIdWithHistos.end()){
00196
00197 TH1I *hT0WireHisto = theHistoWireMap[wireId];
00198
00199 if(hT0WireHisto == 0){
00200 theFile->cd();
00201 hT0WireHisto = new TH1I(getHistoName(wireId).c_str(),"T0 from pulses by wire (TDC counts, 1 TDC count = 0.781 ns)",7000,0,7000);
00202
00203
00204 if(debug)
00205 cout << " New T0 per wire Histo: " << hT0WireHisto->GetName() << endl;
00206 theHistoWireMap[wireId] = hT0WireHisto;
00207 }
00208
00209 theFile->cd();
00210 if(hT0WireHisto != 0) {
00211
00212
00213 hT0WireHisto->Fill(t0);
00214 }
00215 }
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 if(fabs(theTPPeakMap[layerId] - t0) > rejectDigiFromPeak){
00232 if(debug)
00233 cout<<"digi skipped because t0 too far from peak " << theTPPeakMap[layerId] << endl;
00234 continue;
00235 }
00236
00237
00238 theSumT0ByChamber[chamberId] = theSumT0ByChamber[chamberId] + t0;
00239 theCountT0ByChamber[chamberId]++;
00240
00241
00242 if(nevents< (eventsForLayerT0 + eventsForWireT0)){
00243 if(!nDigiPerWire_ref[wireId]){
00244 mK_ref[wireId] = 0;
00245 }
00246 nDigiPerWire_ref[wireId] = nDigiPerWire_ref[wireId] + 1;
00247 mK_ref[wireId] = mK_ref[wireId] + (t0-mK_ref[wireId])/nDigiPerWire_ref[wireId];
00248 }
00249
00250 else if(nevents>(eventsForLayerT0 + eventsForWireT0)){
00251 if(abs(t0-mK_ref[wireId]) > tpPeakWidth)
00252 continue;
00253 if(!nDigiPerWire[wireId]){
00254 theAbsoluteT0PerWire[wireId] = 0;
00255 qK[wireId] = 0;
00256 mK[wireId] = 0;
00257 }
00258 nDigiPerWire[wireId] = nDigiPerWire[wireId] + 1;
00259 theAbsoluteT0PerWire[wireId] = theAbsoluteT0PerWire[wireId] + t0;
00260
00261 qK[wireId] = qK[wireId] + ((nDigiPerWire[wireId]-1)*(t0-mK[wireId])*(t0-mK[wireId])/nDigiPerWire[wireId]);
00262 mK[wireId] = mK[wireId] + (t0-mK[wireId])/nDigiPerWire[wireId];
00263 }
00264 }
00265 }
00266 }
00267
00268
00269 if(nevents == eventsForLayerT0){
00270 bool increaseEvtsForLayerT0 = false;
00271 for(map<DTLayerId, TH1I*>::const_iterator lHisto = theHistoLayerMap.begin();
00272 lHisto != theHistoLayerMap.end();
00273 lHisto++){
00274 if(debug)
00275 cout<<"Reading histogram "<<(*lHisto).second->GetName()<<" with mean "<<(*lHisto).second->GetMean()<<" and RMS "<<(*lHisto).second->GetRMS() << endl;
00276
00277
00278
00279
00280 int npeaks = spectrum->Search((*lHisto).second,(tpPeakWidthPerLayer/2.),"",0.3);
00281
00282 float *peaks = spectrum->GetPositionX();
00283
00284 vector<float> peakMeans(peaks,peaks + npeaks);
00285
00286 sort(peakMeans.begin(),peakMeans.end());
00287
00288
00289 float tTrig,tTrigRMS, kFactor;
00290 tTrigMap->get((*lHisto).first.superlayerId(), tTrig, tTrigRMS, kFactor, DTTimeUnits::counts );
00291
00292 float timeBoxCenter = (2*tTrig + (float)timeBoxWidth)/2.;
00293 float hMin = (*lHisto).second->GetXaxis()->GetXmin();
00294 float hMax = (*lHisto).second->GetXaxis()->GetXmax();
00295 vector<float>::const_iterator tpPeak = peakMeans.end();
00296 for(vector<float>::const_iterator it = peakMeans.begin(); it != peakMeans.end(); ++it){
00297 float mean = *it;
00298
00299 int bin = (*lHisto).second->GetXaxis()->FindBin(mean);
00300 float yp = (*lHisto).second->GetBinContent(bin);
00301 if(debug) cout << "Peak : (" << mean << "," << yp << ")" << endl;
00302
00303
00304 float previous_peak = (it == peakMeans.begin())?hMin:*(it - 1);
00305 float next_peak = (it == (peakMeans.end()-1))?hMax:*(it + 1);
00306
00307 float rangemin = mean - (mean - previous_peak)/8.;
00308 float rangemax = mean + (next_peak - mean)/8.;
00309 int binmin = (*lHisto).second->GetXaxis()->FindBin(rangemin);
00310 int binmax = (*lHisto).second->GetXaxis()->FindBin(rangemax);
00311 (*lHisto).second->GetXaxis()->SetRange(binmin,binmax);
00312
00313 float rms_seed = (*lHisto).second->GetRMS();
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 if(rms_seed > tpPeakWidthPerLayer) continue;
00335
00336 if(fabs(mean - timeBoxCenter) < fabs(*tpPeak - timeBoxCenter)) tpPeak = it;
00337 }
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 float selPeak = (tpPeak != peakMeans.end())?*tpPeak:(*lHisto).second->GetBinCenter((*lHisto).second->GetMaximumBin());
00348 if(debug) cout << "Peak selected at " << selPeak << endl;
00349
00350 theTPPeakMap[(*lHisto).first] = selPeak;
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384 }
00385
00386
00387
00388
00389
00390
00391
00392
00393 if(increaseEvtsForLayerT0){
00394 cout<<"[DTT0CalibrationNew]: t0 per layer are still uncorrect: trying with greater number of events"<<endl;
00395 eventsForLayerT0 = eventsForLayerT0*2;
00396 return;
00397 }
00398 }
00399 }
00400
00401 void DTT0CalibrationNew::endJob() {
00402
00403 DTT0* t0s = new DTT0();
00404 DTT0* t0sWRTChamber = new DTT0();
00405
00406 if(debug)
00407 cout << "[DTT0CalibrationNewPerLayer]Writing histos to file!" << endl;
00408
00409 theFile->cd();
00410
00411 for(map<DTWireId, TH1I*>::const_iterator wHisto = theHistoWireMap.begin();
00412 wHisto != theHistoWireMap.end();
00413 wHisto++) {
00414 (*wHisto).second->Write();
00415 }
00416 for(map<DTLayerId, TH1I*>::const_iterator lHisto = theHistoLayerMap.begin();
00417 lHisto != theHistoLayerMap.end();
00418 lHisto++) {
00419 (*lHisto).second->Write();
00420 }
00421
00422 if(debug)
00423 cout << "[DTT0CalibrationNew] Compute and store t0 and sigma per wire" << endl;
00424
00425 for(map<DTChamberId,double>::const_iterator chamber = theSumT0ByChamber.begin();
00426 chamber != theSumT0ByChamber.end();
00427 ++chamber) theRefT0ByChamber[(*chamber).first] = theSumT0ByChamber[(*chamber).first]/((double)theCountT0ByChamber[(*chamber).first]);
00428
00429 for(map<DTWireId, double>::const_iterator wiret0 = theAbsoluteT0PerWire.begin();
00430 wiret0 != theAbsoluteT0PerWire.end();
00431 wiret0++){
00432 if(nDigiPerWire[(*wiret0).first]){
00433 double t0 = (*wiret0).second/nDigiPerWire[(*wiret0).first];
00434 DTChamberId chamberId = ((*wiret0).first).chamberId();
00435
00436 theRelativeT0PerWire[(*wiret0).first] = t0 - theRefT0ByChamber[chamberId];
00437 cout<<"Wire "<<(*wiret0).first<<" has t0 "<<t0<<"(absolute) "<<theRelativeT0PerWire[(*wiret0).first]<<"(relative)";
00438
00439
00440 theSigmaT0PerWire[(*wiret0).first] = sqrt(qK[(*wiret0).first]/nDigiPerWire[(*wiret0).first]);
00441 cout<<" sigma "<<theSigmaT0PerWire[(*wiret0).first]<<endl;
00442 }
00443 else{
00444 cout<<"[DTT0CalibrationNew] ERROR: no digis in wire "<<(*wiret0).first<<endl;
00445 abort();
00446 }
00447 }
00448
00450
00451 const vector<DTSuperLayer*> superLayers = dtGeom->superLayers();
00452
00453 for(vector<DTSuperLayer*>::const_iterator sl = superLayers.begin();
00454 sl != superLayers.end(); sl++) {
00455
00456
00457
00458 double oddLayersMean=0;
00459 double evenLayersMean=0;
00460 double oddLayersDen=0;
00461 double evenLayersDen=0;
00462 for(map<DTWireId, double>::const_iterator wiret0 = theRelativeT0PerWire.begin();
00463 wiret0 != theRelativeT0PerWire.end();
00464 wiret0++){
00465 if((*wiret0).first.layerId().superlayerId() == (*sl)->id()){
00466 if(debug)
00467 cout<<"[DTT0CalibrationNew] Superlayer "<<(*sl)->id()
00468 <<"layer " <<(*wiret0).first.layerId().layer()<<" with "<<(*wiret0).second<<endl;
00469 if(((*wiret0).first.layerId().layer()) % 2){
00470 oddLayersMean = oddLayersMean + (*wiret0).second;
00471 oddLayersDen++;
00472 }
00473 else{
00474 evenLayersMean = evenLayersMean + (*wiret0).second;
00475 evenLayersDen++;
00476 }
00477 }
00478 }
00479 oddLayersMean = oddLayersMean/oddLayersDen;
00480 evenLayersMean = evenLayersMean/evenLayersDen;
00481 if(debug && oddLayersMean)
00482 cout<<"[DTT0CalibrationNew] Relative T0 mean for odd layers "<<oddLayersMean<<" even layers"<<evenLayersMean<<endl;
00483
00484
00485 double oddLayersSigma=0;
00486 double evenLayersSigma=0;
00487 for(map<DTWireId, double>::const_iterator wiret0 = theRelativeT0PerWire.begin();
00488 wiret0 != theRelativeT0PerWire.end();
00489 wiret0++){
00490 if((*wiret0).first.layerId().superlayerId() == (*sl)->id()){
00491 if(((*wiret0).first.layerId().layer()) % 2){
00492 oddLayersSigma = oddLayersSigma + ((*wiret0).second - oddLayersMean) * ((*wiret0).second - oddLayersMean);
00493 }
00494 else{
00495 evenLayersSigma = evenLayersSigma + ((*wiret0).second - evenLayersMean) * ((*wiret0).second - evenLayersMean);
00496 }
00497 }
00498 }
00499 oddLayersSigma = oddLayersSigma/oddLayersDen;
00500 evenLayersSigma = evenLayersSigma/evenLayersDen;
00501 oddLayersSigma = sqrt(oddLayersSigma);
00502 evenLayersSigma = sqrt(evenLayersSigma);
00503
00504 if(debug && oddLayersMean)
00505 cout<<"[DTT0CalibrationNew] Relative T0 sigma for odd layers "<<oddLayersSigma<<" even layers"<<evenLayersSigma<<endl;
00506
00507
00508 double oddLayersFinalMean=0;
00509 double evenLayersFinalMean=0;
00510 for(map<DTWireId, double>::const_iterator wiret0 = theRelativeT0PerWire.begin();
00511 wiret0 != theRelativeT0PerWire.end();
00512 wiret0++){
00513 if((*wiret0).first.layerId().superlayerId() == (*sl)->id()){
00514 if(((*wiret0).first.layerId().layer()) % 2){
00515 if(abs((*wiret0).second - oddLayersMean) < (2*oddLayersSigma))
00516 oddLayersFinalMean = oddLayersFinalMean + (*wiret0).second;
00517 }
00518 else{
00519 if(abs((*wiret0).second - evenLayersMean) < (2*evenLayersSigma))
00520 evenLayersFinalMean = evenLayersFinalMean + (*wiret0).second;
00521 }
00522 }
00523 }
00524 oddLayersFinalMean = oddLayersFinalMean/oddLayersDen;
00525 evenLayersFinalMean = evenLayersFinalMean/evenLayersDen;
00526 if(debug && oddLayersMean)
00527 cout<<"[DTT0CalibrationNew] Final relative T0 mean for odd layers "<<oddLayersFinalMean<<" even layers"<<evenLayersFinalMean<<endl;
00528
00529 for(map<DTWireId, double>::const_iterator wiret0 = theRelativeT0PerWire.begin();
00530 wiret0 != theRelativeT0PerWire.end();
00531 wiret0++){
00532 if((*wiret0).first.layerId().superlayerId() == (*sl)->id()){
00533 double t0=-999;
00534 if(((*wiret0).first.layerId().layer()) % 2)
00535 t0 = (*wiret0).second + (evenLayersFinalMean - oddLayersFinalMean);
00536 else
00537 t0 = (*wiret0).second;
00538
00539 cout<<"[DTT0CalibrationNew] Wire "<<(*wiret0).first<<" has t0 "<<(*wiret0).second<<" (relative, after even-odd layer corrections) "
00540 <<" sigma "<<theSigmaT0PerWire[(*wiret0).first]<<endl;
00541
00542 t0s->set((*wiret0).first, t0, theSigmaT0PerWire[(*wiret0).first],DTTimeUnits::counts);
00543 }
00544 }
00545 }
00546
00548 if(debug)
00549 cout << "[DTT0CalibrationNew]Computing relative t0 wrt to chamber average" << endl;
00550
00551 map<DTChamberId,double> sumT0ByChamber;
00552 map<DTChamberId,int> countT0ByChamber;
00553 for(DTT0::const_iterator tzero = t0s->begin();
00554 tzero != t0s->end(); tzero++) {
00555
00556
00557
00558
00559
00560 int channelId = tzero->channelId;
00561 if ( channelId == 0 ) continue;
00562 DTWireId wireId(channelId);
00563 DTChamberId chamberId(wireId.chamberId());
00564
00565
00566 float t0mean_f;
00567 float t0rms_f;
00568 t0s->get(wireId,t0mean_f,t0rms_f,DTTimeUnits::counts);
00569 sumT0ByChamber[chamberId] = sumT0ByChamber[chamberId] + t0mean_f;
00570
00571 countT0ByChamber[chamberId]++;
00572 }
00573
00574
00575 for(DTT0::const_iterator tzero = t0s->begin();
00576 tzero != t0s->end(); tzero++) {
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589 int channelId = tzero->channelId;
00590 if ( channelId == 0 ) continue;
00591 DTWireId wireId( channelId );
00592 DTChamberId chamberId(wireId.chamberId());
00593
00594
00595
00596 float t0mean_f;
00597 float t0rms_f;
00598 t0s->get(wireId,t0mean_f,t0rms_f,DTTimeUnits::counts);
00599 double t0mean = t0mean_f - (sumT0ByChamber[chamberId]/countT0ByChamber[chamberId]);
00600 double t0rms = t0rms_f;
00601
00602 t0sWRTChamber->set(wireId,
00603 t0mean,
00604 t0rms,
00605 DTTimeUnits::counts);
00606 if(debug){
00607
00608
00609 cout<<"Changing t0 of wire "<<wireId<<" from "<<tzero->t0mean<<" to "<<t0mean<<endl;
00610 }
00611 }
00612
00614 if(debug)
00615 cout << "[DTT0CalibrationNew]Writing values in DB!" << endl;
00616
00617 string t0Record = "DTT0Rcd";
00618
00619 DTCalibDBUtils::writeToDB(t0Record, t0sWRTChamber);
00620 }
00621
00622 string DTT0CalibrationNew::getHistoName(const DTWireId& wId) const {
00623 string histoName;
00624 stringstream theStream;
00625 theStream << "Ch_" << wId.wheel() << "_" << wId.station() << "_" << wId.sector()
00626 << "_SL" << wId.superlayer() << "_L" << wId.layer() << "_W"<< wId.wire() <<"_hT0Histo";
00627 theStream >> histoName;
00628 return histoName;
00629 }
00630
00631 string DTT0CalibrationNew::getHistoName(const DTLayerId& lId) const {
00632 string histoName;
00633 stringstream theStream;
00634 theStream << "Ch_" << lId.wheel() << "_" << lId.station() << "_" << lId.sector()
00635 << "_SL" << lId.superlayer() << "_L" << lId.layer() <<"_hT0Histo";
00636 theStream >> histoName;
00637 return histoName;
00638 }
00639