Changeset 1300 in Sophya for trunk/SophyaExt
- Timestamp:
- Nov 8, 2000, 11:02:58 AM (25 years ago)
- Location:
- trunk/SophyaExt/FitsIOServer
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/SophyaExt/FitsIOServer/fitsbntbllineRW.cc
r1231 r1300 21 21 InitNull(); 22 22 inFits_ = new FitsInFile (inputfile); 23 inFits_->Read FInit(hdunum);23 inFits_->ReadHeader(hdunum); 24 24 25 25 // if (!fn->IsFitsTable()) … … 52 52 for (k=0; k<nbcols;k++) 53 53 { 54 // char ss= fn->ColTypeFromFits(k); 55 char ss= inFits_->ColTypeFromFits(k); 56 if (ss == 'D') DfitsCol.push_back(k); 57 else if (ss == 'E') FfitsCol.push_back(k); 58 else if (ss == 'I') IfitsCol.push_back(k); 59 else if (ss == 'S') SfitsCol.push_back(k); 54 FitsFile::FitsDataType ss= inFits_->ColTypeFromFits(k); 55 if (ss == FitsFile::FitsDataType_double) DfitsCol.push_back(k); 56 else if (ss == FitsFile::FitsDataType_float) FfitsCol.push_back(k); 57 else if (ss == FitsFile::FitsDataType_int) IfitsCol.push_back(k); 58 else if (ss == FitsFile::FitsDataType_char) SfitsCol.push_back(k); 60 59 else { 61 60 cout << " FITS_XNTuple: colonne fits " << k << " type= " << ss << endl; -
trunk/SophyaExt/FitsIOServer/fitsbntbllineRW.h
r1231 r1300 48 48 49 49 FitsInFile* inFits_; 50 51 50 long nextLineToBeRead_; 51 BnTblLine ligne_; 52 52 }; 53 53 -
trunk/SophyaExt/FitsIOServer/fitsfile.cc
r1281 r1300 104 104 void FitsIOHandler::Read(FitsInFile& is, int hdunum) 105 105 { 106 is.Read FInit(hdunum);106 is.ReadHeader(hdunum); 107 107 ReadFromFits(is); 108 108 } … … 224 224 void FitsInFile::InitNull() 225 225 { 226 227 bitpix_ = 0; 226 imageDataType_ = FitsDataType_NULL; 228 227 naxis_ = 0; 229 228 nbData_ = 0; … … 236 235 dvl_.Clear(); 237 236 238 239 237 } 240 238 … … 268 266 { 269 267 typeOfExtension = FitsExtensionType_IMAGE; 270 int bitpix; 271 GetImageParameters (fileptr, bitpix, naxis, naxisn); 272 if(bitpix == DOUBLE_IMG) dataType = FitsDataType_double; 273 else 274 if(bitpix == FLOAT_IMG) dataType = FitsDataType_float; 275 else 276 if(bitpix == LONG_IMG || bitpix == SHORT_IMG ) dataType = FitsDataType_int; 277 else 278 if (bitpix == BYTE_IMG) dataType = FitsDataType_char; 279 else 280 { 281 cout << " bitpix= " << bitpix << endl; 282 throw PException(" FitsFile::GetBlockType : unsupprted FITS data type"); 283 } 284 268 GetImageParameters (fileptr, dataType, naxis, naxisn); 285 269 } 286 270 else … … 289 273 int nrows = 0; 290 274 vector<string> noms; 291 vector< char> types;275 vector<FitsDataType> types; 292 276 vector<int> taille_des_chaines; 293 277 GetBinTabParameters(fileptr, naxis, nrows, naxisn, noms, types, taille_des_chaines); … … 302 286 { 303 287 typeOfExtension = FitsExtensionType_BINARY_TBL; 304 if(types[0] == 'D') dataType = FitsDataType_double; 305 else 306 if(types[0] == 'E') dataType = FitsDataType_float; 307 else 308 if(types[0] == 'I' ) dataType = FitsDataType_int; 309 else 310 if(types[0] == 'S' ) dataType = FitsDataType_char; 311 else 312 { 313 cout << " types[0]= " << types[0] << endl; 314 throw PException(" FitsFile::GetBlockType : unsupprted FITS data type"); 315 } 288 dataType = types[0]; 316 289 } 317 290 } … … 327 300 328 301 329 void FitsInFile::Read FInit(int hdunum)330 { 331 InitNull();302 void FitsInFile::ReadHeader(int hdunum) 303 { 304 // InitNull(); 332 305 int status = 0; 333 306 … … 352 325 353 326 354 void FitsInFile::GetImageParameters (fitsfile* fileptr, int& bitpix,int& naxis,vector<int>& naxisn)327 void FitsInFile::GetImageParameters (fitsfile* fileptr,FitsDataType& dataType,int& naxis,vector<int>& naxisn) 355 328 { 356 329 int hdunum=0; … … 359 332 360 333 // bits per pixels 334 int bitpix=0; 361 335 fits_read_key(fileptr,TINT,"BITPIX",&bitpix,NULL,&status); 362 336 if( status ) printerror( status ); 337 if(bitpix == DOUBLE_IMG) dataType = FitsDataType_double; 338 else if(bitpix == FLOAT_IMG) dataType = FitsDataType_float; 339 else if(bitpix == LONG_IMG || bitpix == SHORT_IMG ) dataType = FitsDataType_int; 340 else if (bitpix == BYTE_IMG) dataType = FitsDataType_char; 341 else 342 { 343 cout << " bitpix= " << bitpix << endl; 344 throw PException(" FitsFile::GetImageParameters : unsupported FITS data type"); 345 } 363 346 364 347 // number of dimensions in the FITS array … … 401 384 void FitsInFile::getHeader() 402 385 { 386 // si hdunum_ > 1 lit le header correspondant 387 // si hdunum_ = 1 se positionne au (et lit le) premier header qui 388 // contient reellement un objet 403 389 int status=0; 404 390 if (hdunum_ < 1) throw PException(" attempt to read hdunum < 1"); 391 InitNull(); 405 392 if (hdunum_ == 1) 406 393 { … … 412 399 { 413 400 hdutype_ = IMAGE_HDU; 414 GetImageParameters (fptr_, bitpix_, naxis_, naxisn_);401 GetImageParameters (fptr_, imageDataType_, naxis_, naxisn_); 415 402 nbData_ = 1; 416 403 int k; … … 436 423 if(hdutype_ == IMAGE_HDU) 437 424 { 438 GetImageParameters (fptr_, bitpix_, naxis_, naxisn_);425 GetImageParameters (fptr_, imageDataType_, naxis_, naxisn_); 439 426 nbData_ = 1; 440 427 int k; … … 509 496 */ 510 497 511 charFitsInFile::ColTypeFromFits(int nocol) const498 FitsFile::FitsDataType FitsInFile::ColTypeFromFits(int nocol) const 512 499 { 513 500 if(hdutype_ != ASCII_TBL && hdutype_ != BINARY_TBL) … … 548 535 for (k=0; k<=nocol; k++) 549 536 { 550 if (types_[k] == 'S') index++;537 if (types_[k] == FitsDataType_char) index++; 551 538 } 552 539 return taille_des_chaines_[index]; … … 578 565 switch (types_[ncol]) 579 566 { 580 case 'D':567 case FitsDataType_double : 581 568 fits_read_col(fptr_,TDOUBLE,ncol+1,NoLine+1,1,1,&dnull,&ddata[dcount++],&anull,&status); 582 569 break; 583 case 'E':570 case FitsDataType_float : 584 571 fits_read_col(fptr_,TFLOAT,ncol+1,NoLine+1,1,1,&fnull,&fdata[fcount++],&anull,&status); 585 572 break; 586 case 'I':573 case FitsDataType_int : 587 574 fits_read_col(fptr_,TINT,ncol+1,NoLine+1,1,1,&inull,&idata[icount++], 588 575 &anull,&status); 589 576 break; 590 case 'S':577 case FitsDataType_char : 591 578 fits_read_col(fptr_,TSTRING,ncol+1,NoLine+1,1,1,cnull,&cdata[ccount++],&anull,&status); 592 579 break; … … 621 608 switch (types_[ncol]) 622 609 { 623 case 'D':610 case FitsDataType_double : 624 611 fits_read_col(fptr_,TDOUBLE,ncol+1,NoLine+1,1,1,&dnull,&ligne.ddata_[dcount++],&anull,&status); 625 626 case 'E':612 break; 613 case FitsDataType_float : 627 614 fits_read_col(fptr_,TFLOAT,ncol+1,NoLine+1,1,1,&fnull,&ligne.fdata_[fcount++],&anull,&status); 628 615 break; 629 case 'I':616 case FitsDataType_int : 630 617 fits_read_col(fptr_,TINT,ncol+1,NoLine+1,1,1,&inull,&ligne.idata_[icount++], 631 618 &anull,&status); 632 619 break; 633 case 'S':620 case FitsDataType_char : 634 621 char* chaine = new char[taille_des_chaines_[ccount]]; 635 622 fits_read_col(fptr_,TSTRING,ncol+1,NoLine+1,1,1,cnull,&chaine,&anull,&status); … … 789 776 long repeat,width; 790 777 fits_get_coltype(fptr_, NoCol+1,&DTYPE,&repeat,&width,&status); 791 if( DTYPE != TSTRING )792 { 793 throw IOExc("FitsFile::GetBinTabFCol, tentative de lecture non float");778 if( DTYPE != TSTRING && DTYPE != TBYTE) 779 { 780 throw IOExc("FitsFile::GetBinTabFCol, tentative de lecture non string"); 794 781 } 795 782 long nels=nentries; … … 821 808 { 822 809 823 if( bitpix_ != DOUBLE_IMG)810 if(imageDataType_ != FitsDataType_double) 824 811 { 825 812 cout << " The data type on fits file is not double..."; … … 855 842 if(hdutype_ == IMAGE_HDU) 856 843 { 857 if( bitpix_ != FLOAT_IMG)844 if(imageDataType_ != FitsDataType_float) 858 845 { 859 846 cout << " The data type on fits file is not float "; … … 888 875 if(hdutype_ == IMAGE_HDU) 889 876 { 890 if( bitpix_ != LONG_IMG)877 if(imageDataType_ != FitsDataType_int) 891 878 { 892 879 cout << " The data type on fits file is not int "; … … 916 903 vector<int>& repeat, 917 904 vector<string>& noms, 918 vector< char>& types,905 vector<FitsDataType>& types, 919 906 vector<int>& taille_des_chaines) 920 907 { … … 961 948 if( status ) printerror( status,"erreur lecture des noms de colonne"); 962 949 int rept=0; 963 for(ii = 0; ii < nbcols; ii++) 964 { 965 int DTYPE; 966 long width; 967 long repete = 0; 968 fits_get_coltype(fileptr,ii+1,&DTYPE,&repete,&width,&status); 969 if( status ) printerror( status,"erreur lecture type de colonne"); 970 rept = repete; 971 noms.push_back(string(ttype[ii])); 972 switch (DTYPE) 973 { 974 case TDOUBLE : 975 types.push_back('D'); 976 break; 977 case TFLOAT : 978 types.push_back('E'); 979 break; 980 case TLONG : 981 types.push_back('I'); 982 break; 983 case TINT : 984 types.push_back('I'); 985 break; 986 case TSHORT : 987 types.push_back('I'); 988 break; 989 case TSTRING : 990 types.push_back('S'); 991 taille_des_chaines.push_back(width); 992 rept/=width; 993 break; 994 default : 995 cout << " field " << ii+1 << " DTYPE= " << DTYPE << endl; 996 throw IOExc("FitsFile:: unknown type of field"); 997 } 998 repeat.push_back(rept); 950 if(hdutype == ASCII_TBL) 951 { 952 for(ii = 0; ii < nbcols; ii++) 953 { 954 int DTYPE; 955 long width; 956 long repete = 0; 957 fits_get_coltype(fileptr,ii+1,&DTYPE,&repete,&width,&status); 958 if( status ) printerror( status,"erreur lecture type de colonne"); 959 rept = repete; 960 noms.push_back(string(ttype[ii])); 961 switch (DTYPE) 962 { 963 case TDOUBLE : 964 types.push_back(FitsDataType_double); 965 break; 966 case TFLOAT : 967 types.push_back(FitsDataType_float); 968 break; 969 case TLONG : 970 types.push_back(FitsDataType_int); 971 break; 972 case TSHORT : 973 types.push_back(FitsDataType_int); 974 break; 975 case TSTRING : 976 types.push_back(FitsDataType_char); 977 taille_des_chaines.push_back(width); 978 rept/=width; 979 break; 980 default : 981 cout << " field " << ii+1 << " DTYPE= " << DTYPE << endl; 982 throw IOExc("FitsFile::GetBinTabParameters, unsupported data type of field, for ASCII table"); 983 } 984 repeat.push_back(rept); 985 } 986 } 987 else 988 { 989 for(ii = 0; ii < nbcols; ii++) 990 { 991 int DTYPE; 992 long width; 993 long repete = 0; 994 fits_get_coltype(fileptr,ii+1,&DTYPE,&repete,&width,&status); 995 if( status ) printerror( status,"erreur lecture type de colonne"); 996 rept = repete; 997 noms.push_back(string(ttype[ii])); 998 switch (DTYPE) 999 { 1000 case TDOUBLE : 1001 types.push_back(FitsDataType_double); 1002 break; 1003 case TFLOAT : 1004 types.push_back(FitsDataType_float); 1005 break; 1006 case TLONG : 1007 types.push_back(FitsDataType_int); 1008 break; 1009 case TINT : 1010 types.push_back(FitsDataType_int); 1011 break; 1012 case TSHORT : 1013 types.push_back(FitsDataType_int); 1014 break; 1015 case TSTRING : 1016 types.push_back(FitsDataType_char); 1017 taille_des_chaines.push_back(width); 1018 rept/=width; 1019 break; 1020 case TBYTE : 1021 types.push_back(FitsDataType_char); 1022 taille_des_chaines.push_back(width); 1023 rept/=width; 1024 break; 1025 default : 1026 cout << " field " << ii+1 << " DTYPE= " << DTYPE << endl; 1027 throw IOExc("FitsFile::GetBinTabParameters, unsupported data type of field, for BINTABLE"); 1028 } 1029 repeat.push_back(rept); 1030 } 999 1031 } 1000 1032 for (ii=0; ii < nbcols; ii++) delete [] ttype[ii]; … … 1292 1324 \param <taille_des_chaines> vector containing the number of characters of data for each char* typed column, with order of appearance in 'fieldType' 1293 1325 */ 1294 void FitsOutFile::makeHeaderBntblOnFits( 1326 void FitsOutFile::makeHeaderBntblOnFits(string fieldType, vector<string> Noms, int nentries, int tfields, DVList* ptr_dvl, string extname, vector<int> taille_des_chaines) 1295 1327 { 1296 1328 int k; 1297 1329 int status = 0; 1298 1330 long nrows; 1299 // verifications de coherence 1331 // verifications de coherences 1300 1332 1301 1333 if (fieldType.length() != tfields) -
trunk/SophyaExt/FitsIOServer/fitsfile.h
r1246 r1300 60 60 }; 61 61 enum FitsDataType { 62 FitsDataType_NULL, 62 63 FitsDataType_double, 63 64 FitsDataType_float, 64 65 FitsDataType_int, 65 66 FitsDataType_char, 66 FitsDataType_ASCII 67 FitsDataType_ASCII, 67 68 }; 68 69 … … 72 73 inline int statusF() const { return fits_status_;} 73 74 inline void firstImageOnPrimaryHeader(bool choice) {imageOnPrimary_=choice;} 75 inline int currentHeaderIndex() {return hdunum_;} 74 76 75 77 … … 81 83 inline void InitNull() {fptr_ = NULL; hdutype_= 0; hdunum_ = 0; 82 84 fits_status_ = 0; imageOnPrimary_ = true;} 83 84 85 fitsfile *fptr_; /**< pointer to the FITS file, defined in fitsio.h */ 85 86 int hdutype_; /**< image or bintable ? */ … … 102 103 static int NbBlocks(char flnm[]); 103 104 static void GetBlockType(char flnm[], int hdunum, FitsExtensionType& typeOfExtension, int& naxis, vector<int>& naxisn, FitsDataType& dataType, DVList& dvl ); 104 void Read FInit(int hdunum);105 void ReadHeader(int hdunum); 105 106 106 107 /*! \return a reference on a DVList containing the keywords from FITS file */ … … 139 140 inline int nbOfImageData() const { return nbData_; } 140 141 142 /*! \return data type of the current IMAGE extension */ 143 inline FitsFile::FitsDataType ImageType() const {return imageDataType_;} 141 144 142 145 … … 155 158 vector<int>& repeat, 156 159 vector<string>& noms, 157 vector< char>& types,160 vector<FitsDataType>& types, 158 161 vector<int>& taille_des_chaines); 159 charColTypeFromFits(int nocol) const;162 FitsDataType ColTypeFromFits(int nocol) const; 160 163 string ColNameFromFits(int nocol) const; 161 164 int ColStringLengthFromFits(int nocol) const; … … 188 191 void getHeader(); 189 192 static void KeywordsIntoDVList(fitsfile* fileptr, DVList& dvl, int hdunum); 190 static void GetImageParameters (fitsfile* fileptr, int& bitpix,int& naxis,vector<int>& naxisn);191 192 int bitpix_; /**< fits-Image parameter*/193 static void GetImageParameters (fitsfile* fileptr,FitsDataType& dataType,int& naxis,vector<int>& naxisn); 194 195 FitsDataType imageDataType_; /**< fits-Image parameter (bitpix)*/ 193 196 int naxis_; /**< fits-Image parameter */ 194 197 vector<int> naxisn_; /**< fits-Image parameters : sizes of dimensions */ … … 198 201 int nbcols_; /**< Bintable parameter */ 199 202 vector<string> noms_; /**< Bintable parameter: column names */ 200 vector< char> types_; /**< Bintable parameters: types of columns (D: double, E: float, I: integers, A: char*) */203 vector<FitsDataType> types_; /**< Bintable parameters: types of columns (D: double, E: float, I: integers, A: char*) */ 201 204 DVList dvl_; /**< DVList for transferring keywords */ 202 205 vector<int> taille_des_chaines_; /**< Bintable parameters: length of the char* variables */ -
trunk/SophyaExt/FitsIOServer/fitslocalmap.cc
r1221 r1300 159 159 } 160 160 dvl["Content"]= "LocalMap"; 161 dvl.SetComment("Content", "name of SOPHYA object"); 161 162 // On ecrit les dataBlocks 162 163 vector<string> Noms; … … 182 183 #pragma define_template FITS_LocalMap<r_8> 183 184 #pragma define_template FITS_LocalMap<r_4> 185 #pragma define_template FITS_LocalMap<int_4> 184 186 #endif 185 187 #if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES) 186 188 template class FITS_LocalMap<r_8>; 187 189 template class FITS_LocalMap<r_4>; 190 template class FITS_LocalMap<int_4>; 188 191 #endif -
trunk/SophyaExt/FitsIOServer/fitsntuple.cc
r1221 r1300 89 89 for (k=0; k<nbcols;k++) 90 90 { 91 charss= is.ColTypeFromFits(k);91 FitsFile::FitsDataType ss= is.ColTypeFromFits(k); 92 92 string type; 93 if (ss != 'E')93 if (ss != FitsFile::FitsDataType_float) 94 94 { 95 if (ss == 'D') type= string("double");95 if (ss == FitsFile::FitsDataType_double) type= string("double"); 96 96 else 97 if (ss == 'I') type= string("integer");97 if (ss == FitsFile::FitsDataType_int) type= string("integer"); 98 98 else 99 if (ss == 'A') type = string("char*");99 if (ss == FitsFile::FitsDataType_char) type = string("char*"); 100 100 else 101 101 type = string("unknown"); … … 159 159 // get names and values from the join DVList object 160 160 DVList dvl= dobj_->Info(); 161 dvl["Content"]= "NTuple"; 162 dvl.SetComment("Content", "name of SOPHYA object"); 161 163 // extension name 162 164 string extname("NTuple_Binary_tbl"); -
trunk/SophyaExt/FitsIOServer/fitsspherehealpix.cc
r1250 r1300 97 97 dvl.SetComment("LASTPIX", "Last pixel # (0 based)"); 98 98 dvl["Content"]= "SphereHEALPix"; 99 99 dvl.SetComment("Content", "name of SOPHYA object"); 100 100 101 // On ecrit les dataBlocks 101 102 vector<string> Noms; … … 273 274 #pragma define_template FITS_SphereHEALPix<r_8> 274 275 #pragma define_template FITS_SphereHEALPix<r_4> 276 #pragma define_template FITS_SphereHEALPix<int_4> 275 277 #endif 276 278 #if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES) 277 279 template class FITS_SphereHEALPix<r_8>; 278 280 template class FITS_SphereHEALPix<r_4>; 281 template class FITS_SphereHEALPix<int_4>; 279 282 #endif -
trunk/SophyaExt/FitsIOServer/fitsspherehealpix.h
r1231 r1300 8 8 #include "spherehealpix.h" 9 9 #include "anydataobj.h" 10 #include "ppersist.h"11 10 #include "fitsfile.h" 12 11 -
trunk/SophyaExt/FitsIOServer/fitstarray.cc
r1221 r1300 134 134 } 135 135 cout << " nombre total d'elements a copier " << nbels << endl; 136 os.makeHeaderImageOnFits(type, nbdim, naxisn, &dobj_->Info()); 136 DVList dvl( dobj_->Info() ); 137 dvl["Content"]= "TArray"; 138 dvl.SetComment("Content", "name of SOPHYA object"); 139 os.makeHeaderImageOnFits(type, nbdim, naxisn, &dvl); 137 140 if (!dobj_->IsPacked()) 138 141 { … … 156 159 #pragma define_template FITS_TArray<r_8> 157 160 #pragma define_template FITS_TArray<r_4> 161 #pragma define_template FITS_TArray<int_4> 158 162 #endif 159 163 #if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES) 160 164 template class FITS_TArray<r_8>; 161 165 template class FITS_TArray<r_4>; 166 template class FITS_TArray<int_4>; 162 167 #endif -
trunk/SophyaExt/FitsIOServer/fitsxntuple.cc
r1221 r1300 80 80 for (k=0; k<nbcols;k++) 81 81 { 82 charss= is.ColTypeFromFits(k);83 if (ss == 'D') DfitsCol.push_back(k);84 else if (ss == 'E') FfitsCol.push_back(k);85 else if (ss == 'I') IfitsCol.push_back(k);86 else if (ss == 'S') SfitsCol.push_back(k);82 FitsFile::FitsDataType ss= is.ColTypeFromFits(k); 83 if (ss == FitsFile::FitsDataType_double) DfitsCol.push_back(k); 84 else if (ss == FitsFile::FitsDataType_float) FfitsCol.push_back(k); 85 else if (ss == FitsFile::FitsDataType_int) IfitsCol.push_back(k); 86 else if (ss == FitsFile::FitsDataType_char) SfitsCol.push_back(k); 87 87 else { 88 88 cout << " FITS_XNTuple: colonne fits " << k << " type= " << ss << endl; … … 126 126 if (ownobj_) 127 127 { 128 128 (*dobj_)= XNTuple(DfitsCol.size(), FfitsCol.size(), IfitsCol.size(), SfitsCol.size(),ColName); 129 129 } 130 130 else 131 131 { 132 if (DfitsCol.size() != dobj_->NDVar() || FfitsCol.size() != dobj_->NFVar() || IfitsCol.size() != dobj_->NIVar() || SfitsCol.size() != dobj_->NSVar()) 133 134 throw SzMismatchError("FITS_XNTuple : structure incorrecte du ntuple"); 132 if (DfitsCol.size() != dobj_->NDVar() || FfitsCol.size() != dobj_->NFVar() || IfitsCol.size() != dobj_->NIVar() || SfitsCol.size() != dobj_->NSVar()) 133 { 134 cout << " WARNING : FITS_XNTuple : XNTuple reconfigured " << endl; 135 (*dobj_)= XNTuple(DfitsCol.size(), FfitsCol.size(), IfitsCol.size(), SfitsCol.size(),ColName); 136 } 135 137 } 136 138 } … … 227 229 vector<int> StringSizes(dobj_->NSVar()); 228 230 for (k=0; k< StringSizes.size(); k++) StringSizes[k]=dobj_->mStrSz; 231 dvl["Content"]= "XNTuple"; 232 dvl.SetComment("Content", "name of SOPHYA object"); 229 233 os.makeHeaderBntblOnFits(types, Noms, nrows, ncols, &dvl, extname,StringSizes); 230 234
Note:
See TracChangeset
for help on using the changeset viewer.