void DoCrop(OptionsCls &options) { char name[MAX_PATH_LENGTH]; char destName[MAX_PATH_LENGTH]; int i; Image loader; Acq saver; int mode = 0; i = 0; bool allocate = true; int nameListLen; char **nameList; int maxMode=2; //@WARNING: >must< copy beadfind_post_0000 if it exists, or Analysis will >fail to complete< on PGM run crops // This is an inobvious bug due to the fact that the Image routine "ReadyToLoad" checks for >the next< acq file // or explog_final.txt, >or< beadfind_post. If none of those three exist, we wait forever. // not all runs appear to have explog_final.txt copied around, so can't depend on that. const char* defaultNameList[] = {"beadfind_pre_0000.dat", "beadfind_pre_0001.dat", "beadfind_pre_0002.dat", "beadfind_pre_0003.dat", "beadfind_post_0000.dat", "beadfind_post_0001.dat", "beadfind_post_0002.dat", "beadfind_post_0003.dat", "prerun_0000.dat", "prerun_0001.dat", "prerun_0002.dat", "prerun_0003.dat" }; // if requested...do not bother waiting for the files to show up if ( options.dont_retry ) loader.SetTimeout ( 1,1 ); if ( options.oneFile != NULL ) { nameList = &options.oneFile; nameListLen = 1; maxMode=1; } else { nameList = const_cast<char**> ( defaultNameList ); nameListLen = sizeof ( defaultNameList ) /sizeof ( defaultNameList[0] ); } // Create results folder umask ( 0 ); // make permissive permissions so its easy to delete. if ( mkdir ( options.destPath, 0777 ) ) { if ( errno == EEXIST ) { //already exists? well okay... } else { perror ( options.destPath ); exit ( 1 ); } } if(!options.skipCopy) { // Copy explog.txt file: all .txt files char cmd[1024]; sprintf ( cmd, "cp -v %s/*.txt %s", options.expPath, options.destPath ); if(system ( cmd ) != 0 ) printf("failed to copy txt files from src\n"); // Copy lsrowimage.txt file const char *filesToMove[] = { "lsrowimage.dat", "gainimage.dat", "reimage.dat", "rmsimage.dat" }; for(int iFile=0; iFile < 4; iFile++) { sprintf ( cmd, "cp -v %s/%s %s", options.expPath, filesToMove[iFile], options.destPath); if(system ( cmd ) == 1) fprintf (stdout, "No %s file found\n",filesToMove[iFile]); } } while ( mode < maxMode ) { if ( mode == 1 ) { sprintf ( name, "%s/acq_%04d.dat", options.expPath, i ); sprintf ( destName, "%s/acq_%04d.dat", options.destPath, i ); } else if ( mode == 0 ) { if ( i >= nameListLen ){ mode++; i=0; continue; } sprintf ( name, "%s/%s", options.expPath, nameList[i] ); sprintf ( destName, "%s/%s", options.destPath, nameList[i] ); } else break; if ( loader.LoadRaw ( name, 0, allocate, false, false ) ) { allocate = false; const RawImage *raw = loader.GetImage(); DetermineCropWidthAndHeight ( options.cropx, options.cropy, options.cropw, options.croph, raw->cols, raw->rows ); struct timeval tv; double startT; double stopT; gettimeofday ( &tv, NULL ); startT = ( double ) tv.tv_sec + ( ( double ) tv.tv_usec/1000000 ); if(options.OverSample_skip || options.OverSample_combine) DoOverSample(options,loader); if(options.chipType) ChipIdDecoder::SetGlobalChipId(options.chipType); if(options.applyXtalkCorrection1){ PairPixelXtalkCorrector xtalkCorrector; xtalkCorrector.Correct(loader.raw, options.applyXtalkCorrection1); } if(options.applyRowCorrection){ printf("Applying row noise correction\n"); CorrNoiseCorrector rnc; rnc.CorrectCorrNoise(loader.raw,options.applyColCorrection?3:1,true,true,false ); } else if(options.applyColCorrection){ printf("Applying column noise correction\n"); CorrNoiseCorrector rnc; rnc.CorrectCorrNoise(loader.raw,0,true,true,false ); } if(options.applyXtalkCorrection2){ PairPixelXtalkCorrector xtalkCorrector; xtalkCorrector.Correct(loader.raw, options.applyXtalkCorrection2); } if(options.doColumnCorrectionTn) { ComparatorNoiseCorrector cnc; cnc.CorrectComparatorNoiseThumbnail(loader.raw, NULL, 50,50, false); } else if(options.doColumnCorrection){ ComparatorNoiseCorrector cnc; bool beadfind = false;//((strstr(name,"beadfind_pre"))?true:false); cnc.CorrectComparatorNoise(loader.raw, NULL, false, options.cncType,beadfind ); } if(options.cmpFile){ // subtract this file before continuing Image loader2; loader2.LoadRaw ( options.cmpFile, 0, allocate, 2 ); if(options.OverSample_skip || options.OverSample_combine) DoOverSample(options,loader2); if(options.doColumnCorrectionTn) { ComparatorNoiseCorrector cnc; cnc.CorrectComparatorNoiseThumbnail(loader2.raw, NULL, 100,100, false); } else if(options.doColumnCorrection){ ComparatorNoiseCorrector cnc; bool beadfind = ((strstr(options.cmpFile,"beadfind_pre"))?true:false); cnc.CorrectComparatorNoise(loader2.raw, NULL, 0, options.cncType,beadfind ); } { short int *rawPtr = loader.raw->image; short int *rawPtr2 = loader2.raw->image; int frameStride=loader.raw->cols*loader.raw->rows; for(int frame=0;frame<loader.raw->frames;frame++){ for(int idx=0;idx<frameStride;idx++){ *rawPtr -= *rawPtr2; *rawPtr += 8192; rawPtr++; rawPtr2++; } } } printf("subtracted %s from the file\n",options.cmpFile); } if(options.subtractAverage) { // subtract off the mean trace SubtractOffMean(loader); printf("subtracted mean from trace\n"); } // testing of lossy compression if(!options.pfc && ImageTransformer::PCATest[0]) { AdvComprTest(name,&loader,ImageTransformer::PCATest,true ); } saver.SetData ( &loader ); if(options.T0Test) saver.doT0Compression(); if ( options.regBasedAcq && i == 0 ) { if ( options.excludeMask ) saver.GenerateExcludeMaskRegions ( ( const char* ) options.excludeMaskFile ); if ( options.useSeparatorT0File ) saver.PopulateCroppedRegionalAcquisitionWindow ( ( const char* ) options.separatorIn, "t0Map.txt", options.cropx, options.cropy, options.cropw, options.croph, raw->timestamps[0] ); else saver.ParseT0File ( ( const char* ) options.t0In, "t0Map.txt", options.cropx, options.cropy, options.cropw, options.croph, raw->timestamps[0] ); } printf ( "Converting raw data %d %d frames: %d UncompFrames: %d\n", raw->cols, raw->rows, raw->frames, raw->uncompFrames ); if ( options.doAscii ) { if ( !saver.WriteAscii ( destName, options.cropx, options.cropy, options.cropw, options.croph ) ) break; } else { if ( options.vfc ) { if(options.pfc) { saver.WritePFV(destName, options.cropx, options.cropy, options.cropw, options.croph, options.PCAOpts); } else if ( options.regBasedAcq ) { if ( !saver.WriteFrameAveragedRegionBasedAcq ( destName, options.cropx, options.cropy, options.cropw, options.croph ) ) break; } else if ( options.TimeBasedAcq ) { if ( !saver.WriteTimeBasedAcq ( destName, options.cropx, options.cropy, options.cropw, options.croph ) ) break; } else { if ( !saver.WriteVFC ( destName, options.cropx, options.cropy, options.cropw, options.croph ) ) break; } } else { if ( !saver.Write ( destName, options.cropx, options.cropy, options.cropw, options.croph ) ) break; } } gettimeofday ( &tv, NULL ); stopT = ( double ) tv.tv_sec + ( ( double ) tv.tv_usec/1000000 ); printf ( "Converted: %s in %0.2lf sec\n", name,stopT - startT ); fflush ( stdout ); i++; } else { if ( ( mode == 0 && i >= 12 ) || ( mode ==1 ) ) { mode++; i = 0; allocate = true; } else i++; } } }
void *FileLoadWorker ( void *arg ) { WqInfo_t *wqinfo = (WqInfo_t *)arg; int threadNum=wqinfo->threadNum; WorkerInfoQueue *q = wqinfo->wq; assert ( q ); bool done = false; char dateStr[256]; struct tm newtime; time_t ltime; double T1=0,T2=0,T3,T4; char name[20]; sprintf(name,"FileLdWkr%d",threadNum); prctl(PR_SET_NAME,name,0,0,0); const double noiseThreshold = 0.; // to be set by command line option FluidPotentialCorrector fpCorr(noiseThreshold); while ( !done ) { WorkerInfoQueueItem item = q->GetItem(); if ( item.finished == true ) { // we are no longer needed...go away! done = true; q->DecrementDone(); continue; } ImageLoadWorkInfo *one_img_loader = ( ImageLoadWorkInfo * ) item.private_data; ClockTimer timer; Timer tmr; Image *img = &one_img_loader->img[one_img_loader->cur_buffer]; if (one_img_loader->inception_state->img_control.threaded_file_access) { tmr.restart(); if ( !img->LoadRaw ( one_img_loader->name) ) { fprintf ( stdout, "ERROR: Failed to load raw image %s\n", one_img_loader->name ); exit ( EXIT_FAILURE ); } T1=tmr.elapsed(); tmr.restart(); if(img->raw->imageState & IMAGESTATE_QuickPinnedPixelDetect) one_img_loader->pinnedInFlow->QuickUpdate ( one_img_loader->flow, img); else one_img_loader->pinnedInFlow->Update ( one_img_loader->flow, img,(ImageTransformer::gain_correction?ImageTransformer::gain_correction:0)); T2=tmr.elapsed(); } tmr.restart(); // correct in-channel electrical cross-talk ImageTransformer::XTChannelCorrect ( one_img_loader->img[one_img_loader->cur_buffer].raw, one_img_loader->img[one_img_loader->cur_buffer].results_folder ); // buffer_ix // testing of lossy compression if(ImageTransformer::PCATest[0]) { AdvComprTest(one_img_loader->name,&one_img_loader->img[one_img_loader->cur_buffer],ImageTransformer::PCATest,false/*one_img_loader->inception_state->img_control.col_flicker_correct*/ ); } // col noise correction (if done during lossy compression will already have happened. else if ( !(img->raw->imageState & IMAGESTATE_ComparatorCorrected) && one_img_loader->inception_state->img_control.col_flicker_correct ) { if( one_img_loader->inception_state->img_control.col_pair_pixel_xtalk_correct ){ PairPixelXtalkCorrector xtalkCorrector; float xtalk_fraction = one_img_loader->inception_state->img_control.pair_xtalk_fraction; xtalkCorrector.Correct(one_img_loader->img[one_img_loader->cur_buffer].raw, xtalk_fraction); } if (one_img_loader->inception_state->img_control.corr_noise_correct){ CorrNoiseCorrector rnc; rnc.CorrectCorrNoise(one_img_loader->img[one_img_loader->cur_buffer].raw,3,one_img_loader->inception_state->bfd_control.beadfindThumbnail ); } if(one_img_loader->inception_state->bfd_control.beadfindThumbnail) { //ComparatorNoiseCorrector ComparatorNoiseCorrector cnc; cnc.CorrectComparatorNoiseThumbnail(one_img_loader->img[one_img_loader->cur_buffer].raw, one_img_loader->mask, one_img_loader->inception_state->loc_context.regionXSize,one_img_loader->inception_state->loc_context.regionYSize, one_img_loader->inception_state->img_control.col_flicker_correct_verbose); } else { ComparatorNoiseCorrector cnc; cnc.CorrectComparatorNoise(one_img_loader->img[one_img_loader->cur_buffer].raw, one_img_loader->mask, one_img_loader->inception_state->img_control.col_flicker_correct_verbose, one_img_loader->inception_state->img_control.aggressive_cnc,false,threadNum ); } } //#define DEBUG_IMAGE_CORR_ISSUES 1 #ifdef DEBUG_IMAGE_CORR_ISSUES char newName[1024]; char *nptr,*ptr=one_img_loader->name; while((nptr = strstr(ptr,"/")))ptr=nptr+1; if(*ptr == '/') ptr++; sprintf(newName,"%s_proc",one_img_loader->name); Acq saver; saver.SetData ( &one_img_loader->img[one_img_loader->cur_buffer] ); saver.WriteVFC(newName, 0, 0, one_img_loader->img[one_img_loader->cur_buffer].raw->cols, one_img_loader->img[one_img_loader->cur_buffer].raw->rows); #endif T3=tmr.elapsed(); tmr.restart(); // Fluid potential corrector const bool correctFluidPotential = one_img_loader->inception_state->img_control.fluid_potential_correct; const double noiseThreshold = (double) one_img_loader->inception_state->img_control.fluid_potential_threshold; if (correctFluidPotential){ fpCorr.setThreshold(noiseThreshold); // parse rowsum file name to load const std::string datFileName = one_img_loader->name; printf("dat file name %s\n", datFileName.c_str()); const size_t pos1 = datFileName.find_last_of('/'); const size_t pos2 = datFileName.find_last_of('.'); const std::string rowsumFileName = datFileName.substr(0, pos1) + "/../rowsum/" + datFileName.substr(pos1+1, pos2-pos1-1) + ".hwsum"; // printf("rowsum file name %s pos1 %u pos2 %u\n", rowsumFileName.c_str(), (uint32_t) pos1, (uint32_t) pos2); // determine if the data file is thumbnail or block const bool isThumbnail = one_img_loader->inception_state->bfd_control.beadfindThumbnail; if(isThumbnail){ fpCorr.setIsThumbnail(); } // set image const unsigned int regionXSize = one_img_loader->inception_state->loc_context.regionXSize; const unsigned int regionYSize = one_img_loader->inception_state->loc_context.regionYSize; const char nucChar = one_img_loader->inception_state->flow_context.ReturnNucForNthFlow(one_img_loader->flow); fpCorr.setImage(one_img_loader->img[one_img_loader->cur_buffer].raw, one_img_loader->mask, regionYSize, regionXSize, nucChar); //printf("nucChar is %c\n", nucChar); // load sensing electrode data if (isThumbnail){ const unsigned int numRows = one_img_loader->img[one_img_loader->cur_buffer].raw->rows; fpCorr.loadSensingElectrodeDataThumbnail(rowsumFileName, numRows); } else { // determine startRow and endRow one_img_loader->img[one_img_loader->cur_buffer].SetOffsetFromChipOrigin(one_img_loader->name); const unsigned int startRow = one_img_loader->img[one_img_loader->cur_buffer].raw->chip_offset_y; const unsigned int endRow = startRow + one_img_loader->img[one_img_loader->cur_buffer].raw->rows; // printf("offset x y = %d %d, start and end rows are %u,%u\n", one_img_loader->img[one_img_loader->cur_buffer].raw->chip_offset_x,one_img_loader->img[one_img_loader->cur_buffer].raw->chip_offset_y, startRow, endRow); fpCorr.loadSensingElectrodeData(rowsumFileName, startRow, endRow); } // correct fluid potential if (fpCorr.readRowSumIsSuccess()){ fpCorr.doCorrection(); } else { printf("fluidPotentialCorrector skipped: Cannot find rowsum file %s \n", rowsumFileName.c_str()); } } // dump dc offset one_img_loaderrmation before we do any normalization DumpDcOffset ( one_img_loader ); int buffer_ix = one_img_loader->cur_buffer; // setting the mean of frames to zero will be done by the bkgmodel as soon as its loaded. // the traces will be zero'd by the bknd model loader anyway, no need to do them here. // img->SetMeanOfFramesToZero ( one_img_loader->normStart, one_img_loader->normEnd,0 ); // calculate the smooth pH step amplitude in empty wells across the whole image if ( one_img_loader->doEmptyWellNormalization ) { // this is redundant with what's in the EmptyTrace class, but this method of spatial normalization // is going to go away soon, so not worth fixing MaskType referenceMask = MaskReference; if ( one_img_loader->inception_state->bkg_control.trace_control.use_dud_and_empty_wells_as_reference ) referenceMask = ( MaskType ) ( MaskReference | MaskDud ); one_img_loader->img[buffer_ix].CalculateEmptyWellLocalScaleForFlow ( * ( one_img_loader->pinnedInFlow ),one_img_loader->mask,one_img_loader->flow,referenceMask,one_img_loader->smooth_span ); #if 0 char fname[512]; sprintf ( fname,"ewampimg_%04d.txt",one_img_loader->flow ); FILE *ewampfile = fopen ( fname,"w" ); for ( int row=0;row < one_img_loader->img[buffer_ix].GetRows();row++ ) { int col; for ( col=0;col < ( one_img_loader->img[buffer_ix].GetCols()-1 ); col++ ) fprintf ( ewampfile,"%9.5f\t",one_img_loader->img[buffer_ix].getEmptyWellAmplitude ( row,col ) ); fprintf ( ewampfile,"%9.5f\n",one_img_loader->img[buffer_ix].getEmptyWellAmplitude ( row,col ) ); } fclose ( ewampfile ); #endif } // dump pH step debug one_img_loader to file (its really fast, don't worry) DumpStep ( one_img_loader ); if ( one_img_loader->doRawBkgSubtract ) { one_img_loader->img[buffer_ix].SubtractLocalReferenceTrace ( one_img_loader->mask, MaskBead, MaskReference, one_img_loader->NNinnerx, one_img_loader->NNinnery,one_img_loader->NNouterx,one_img_loader->NNoutery, false, true, true ); if ( one_img_loader->flow==0 ) // absolute first flow,not flow buffer printf ( "Notify user: NN empty subtraction in effect. No further warnings will be given. %d \n",one_img_loader->flow ); } T4=tmr.elapsed(); // printf ( "Allow model to go %d \n", one_img_loader->flow ); SetReadCompleted(one_img_loader); size_t usec = timer.GetMicroSec(); ltime=time(<ime); localtime_r(<ime, &newtime); strftime(dateStr,sizeof(dateStr),"%H:%M:%S", &newtime); fprintf ( stdout, "FileLoadWorker: ImageProcessing time for flow %d: %0.2lf(ld=%.2f pin=%.2f cnc=%.2f xt=%.2f sem=%.2lf cache=%.2lf) sec %s\n", one_img_loader->flow , usec / 1.0e6, T1, T2, T3, T4, img->SemaphoreWaitTime, img->CacheAccessTime, dateStr); fflush(stdout); fprintf(stdout, "File: %s\n", one_img_loader->name); fflush(stdout); q->DecrementDone(); } return ( NULL ); }