bool glfHandler::NextSection() { if (isStub) { endOfSection = true; data.recordType = 0; maxPosition = 1999999999; position = maxPosition + 1; return true; } while (!endOfSection && !ifeof(handle)) NextEntry(); endOfSection = false; int labelLength = 0; currentSection++; position = 0; if (ifread(handle, &labelLength, sizeof(int)) == sizeof(int)) { ifread(handle, label.LockBuffer(labelLength+1), labelLength * sizeof(char)); label.UnlockBuffer(); maxPosition = 0; ifread(handle, &maxPosition, sizeof(int)); return ((maxPosition > 0) && !ifeof(handle)); } return false; }
// Read the refSection from the specified file. Assumes the file is in // the correct position for reading the refSection. bool GlfRefSection::read(IFILE filePtr) { // Read the reference sequence name length int numRead = 0; int32_t refNameLen = 0; int byteLen = sizeof(int32_t); numRead = ifread(filePtr, &refNameLen, byteLen); if(numRead != byteLen) { // If no bytes were read and it is the end of the file, then return // false, but do not throw an exception. This is not an error, just // the end of the file. if((numRead == 0) && ifeof(filePtr)) { return(false); } String errorMsg = "Failed to read the length of the reference sequence name ("; errorMsg += byteLen; errorMsg += " bytes). Only read "; errorMsg += numRead; errorMsg += " bytes."; std::string errorString = errorMsg.c_str(); throw(GlfException(GlfStatus::FAIL_IO, errorString)); return(false); } // Read the refSection from the file. numRead = myRefName.readFromFile(filePtr, refNameLen); if(numRead != refNameLen) { String errorMsg = "Failed to read the reference sequence name ("; errorMsg += refNameLen; errorMsg += " bytes). Only read "; errorMsg += numRead; errorMsg += " bytes."; std::string errorString = errorMsg.c_str(); throw(GlfException(GlfStatus::FAIL_IO, errorString)); return(false); } // Read the ref length. byteLen = sizeof(uint32_t); numRead = ifread(filePtr, &myRefLen, byteLen); if(numRead != byteLen) { String errorMsg = "Failed to read the reference sequence length ("; errorMsg += byteLen; errorMsg += " bytes). Only read "; errorMsg += numRead; errorMsg += " bytes."; std::string errorString = errorMsg.c_str(); throw(GlfException(GlfStatus::FAIL_IO, errorString)); return(false); } // Successfully read, return success. return(true); }
// Read the header from the specified file. Assumes the file is in // the correct position for reading the header. bool GlfHeader::read(IFILE filePtr) { if((filePtr == NULL) || (filePtr->isOpen() == false)) { // File is not open, return failure. std::string errorString = "Failed to read the header since the file is not open."; throw(GlfException(GlfStatus::FAIL_ORDER, errorString)); return(false); } // Read the magic int numRead = 0; char magic[GLF_MAGIC_LEN]; numRead = ifread(filePtr, &magic, GLF_MAGIC_LEN); if(numRead != GLF_MAGIC_LEN) { String errorMsg = "Failed to read the magic number ("; errorMsg += GLF_MAGIC_LEN; errorMsg += " bytes). Only read "; errorMsg += numRead; errorMsg += " bytes."; std::string errorString = errorMsg.c_str(); throw(GlfException(GlfStatus::FAIL_IO, errorString)); return(false); } // Read the header length. int32_t headerLen = 0; int byteLen = sizeof(int32_t); numRead = ifread(filePtr, &headerLen, byteLen); if(numRead != byteLen) { String errorMsg = "Failed to read the length of the header text ("; errorMsg += byteLen; errorMsg += " bytes). Only read "; errorMsg += numRead; errorMsg += " bytes."; std::string errorString = errorMsg.c_str(); throw(GlfException(GlfStatus::FAIL_IO, errorString)); return(false); } // Read the header from the file. numRead = myText.readFromFile(filePtr, headerLen); if(numRead != headerLen) { String errorMsg = "Failed to read the header text ("; errorMsg += headerLen; errorMsg += " bytes). Only read "; errorMsg += numRead; errorMsg += " bytes."; std::string errorString = errorMsg.c_str(); throw(GlfException(GlfStatus::FAIL_IO, errorString)); return(false); } // Successfully read, return success. return(true); }
bool glfHandler::ReadHeader() { if (isStub) return true; if (handle == NULL) return false; char magicNumber[4]; if (ifread(handle, magicNumber, 4) != 4) { errorMsg = "unexpected end of file"; return false; } if (magicNumber[0] != 'G' || magicNumber[1] != 'L' || magicNumber[2] != 'F') { errorMsg = "invalid format"; return false; } if (magicNumber[3] != 3) { errorMsg = "unsupported version"; return false; } unsigned int headerLength = 0; if (ifread(handle, &headerLength, 4) != 4) { errorMsg = "unexpected end of file"; return false; } if (headerLength > 1024 * 1024) { errorMsg = "header too large -- bailing"; return false; } header.SetLength(headerLength + 1); header[headerLength] = 0; if (headerLength && ifread(handle, header.LockBuffer(headerLength + 1), headerLength) != headerLength) { errorMsg = "unexpected end of file"; return false; } return true; }
void yFile::GetDataByFile() { std::ifstream ifread(m_fileName); std::string szBuf; if (!ifread.is_open()) { return; } while (getline(ifread,szBuf)) { std::size_t pos = szBuf.find('='); if (std::string::npos == pos) { break; } else { m_data.insert(std::pair<std::string, std::string>( szBuf.substr(0, pos), szBuf.substr(pos + 1))); } szBuf.erase(); } ifread.close(); }
// Read & parse the specified index file. StatGenStatus::Status Tabix::readIndex(const char* filename) { // Reset the index from anything that may previously be set. resetIndex(); IFILE indexFile = ifopen(filename, "rb"); // Failed to open the index file. if(indexFile == NULL) { return(StatGenStatus::FAIL_IO); } // read the tabix index structure. // Read the magic string. char magic[4]; if(ifread(indexFile, magic, 4) != 4) { // Failed to read the magic return(StatGenStatus::FAIL_IO); } // If this is not an index file, set num references to 0. if (magic[0] != 'T' || magic[1] != 'B' || magic[2] != 'I' || magic[3] != 1) { // Not a Tabix Index file. return(StatGenStatus::FAIL_PARSE); } // It is a tabix index file. // Read the number of reference sequences. if(ifread(indexFile, &n_ref, 4) != 4) { // Failed to read. return(StatGenStatus::FAIL_IO); } // Size the references. myRefs.resize(n_ref); // Read the Format configuration. if(ifread(indexFile, &myFormat, sizeof(myFormat)) != sizeof(myFormat)) { // Failed to read. return(StatGenStatus::FAIL_IO); } // Read the length of the chromosome names. uint32_t l_nm; if(ifread(indexFile, &l_nm, sizeof(l_nm)) != sizeof(l_nm)) { // Failed to read. return(StatGenStatus::FAIL_IO); } // Read the chromosome names. myChromNamesBuffer = new char[l_nm]; if(ifread(indexFile, myChromNamesBuffer, l_nm) != l_nm) { return(StatGenStatus::FAIL_IO); } myChromNamesVector.resize(n_ref); // Parse out the chromosome names. bool prevNull = true; int chromIndex = 0; for(uint32_t i = 0; i < l_nm; i++) { if(chromIndex >= n_ref) { // already set the pointer for the last chromosome name, // so stop looping. break; } if(prevNull == true) { myChromNamesVector[chromIndex++] = myChromNamesBuffer + i; prevNull = false; } if(myChromNamesBuffer[i] == '\0') { prevNull = true; } } for(int refIndex = 0; refIndex < n_ref; refIndex++) { // Read each reference. Reference* ref = &(myRefs[refIndex]); // Resize the bins so they can be indexed by bin number. ref->bins.resize(MAX_NUM_BINS + 1); // Read the number of bins. if(ifread(indexFile, &(ref->n_bin), 4) != 4) { // Failed to read the number of bins. // Return failure. return(StatGenStatus::FAIL_PARSE); } // Read each bin. for(int binIndex = 0; binIndex < ref->n_bin; binIndex++) { uint32_t binNumber; // Read in the bin number. if(ifread(indexFile, &(binNumber), 4) != 4) { // Failed to read the bin number. // Return failure. return(StatGenStatus::FAIL_IO); } // Add the bin to the reference and get the // pointer back so the values can be set in it. Bin* binPtr = &(ref->bins[binNumber]); binPtr->bin = binNumber; // Read in the number of chunks. if(ifread(indexFile, &(binPtr->n_chunk), 4) != 4) { // Failed to read number of chunks. // Return failure. return(StatGenStatus::FAIL_IO); } // Read in the chunks. // Allocate space for the chunks. uint32_t sizeOfChunkList = binPtr->n_chunk * sizeof(Chunk); binPtr->chunks = (Chunk*)malloc(sizeOfChunkList); if(ifread(indexFile, binPtr->chunks, sizeOfChunkList) != sizeOfChunkList) { // Failed to read the chunks. // Return failure. return(StatGenStatus::FAIL_IO); } } // Read the number of intervals. if(ifread(indexFile, &(ref->n_intv), 4) != 4) { // Failed to read, set to 0. ref->n_intv = 0; // Return failure. return(StatGenStatus::FAIL_IO); } // Allocate space for the intervals and read them. uint32_t linearIndexSize = ref->n_intv * sizeof(uint64_t); ref->ioffsets = (uint64_t*)malloc(linearIndexSize); if(ifread(indexFile, ref->ioffsets, linearIndexSize) != linearIndexSize) { // Failed to read the linear index. // Return failure. return(StatGenStatus::FAIL_IO); } } // Successfully read teh bam index file. return(StatGenStatus::SUCCESS); }
EXTERN_C void sopen_abf_read(HDRTYPE* hdr) { /* this function will be called by the function SOPEN in "biosig.c" Input: char* Header // contains the file content Output: HDRTYPE *hdr // defines the HDR structure accoring to "biosig.h" */ if (VERBOSE_LEVEL>7) fprintf(stdout,"sopen_abf_read 101\n"); size_t count = hdr->HeadLen; hdr->VERSION = lef32p(hdr->AS.Header + offsetof(struct ABFFileHeader, fFileVersionNumber)); hdr->HeadLen = (hdr->VERSION < 1.6) ? ABF_OLDHEADERSIZE : ABF_HEADERSIZE; if (count < hdr->HeadLen) { hdr->AS.Header = (uint8_t*) realloc(hdr->AS.Header, hdr->HeadLen); count += ifread(hdr->AS.Header+count, 1, hdr->HeadLen-count, hdr); } hdr->HeadLen = count; assert(hdr->HeadLen == leu32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lHeaderSize))); { struct tm t; uint32_t u = leu32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lFileStartDate)); t.tm_year = u / 10000 - 1900; t.tm_mon = (u % 10000)/100 - 1; t.tm_mday = (u % 100); u = leu32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lFileStartTime)); t.tm_hour = u / 3600; t.tm_min = (u % 3600)/60; t.tm_sec = (u % 60); //u = leu16p(hdr->AS.Header + offsetof(struct ABFFileHeader, nFileStartMillisecs)); hdr->T0 = tm_time2gdf_time(&t); } uint16_t gdftyp = 3; switch (lei16p(hdr->AS.Header + offsetof(struct ABFFileHeader, nDataFormat))) { case 0: gdftyp = 3; break; case 1: gdftyp = 16; break; } size_t slen; slen = min(MAX_LENGTH_MANUF, sizeof(((struct ABFFileHeader*)(hdr->AS.Header))->sCreatorInfo)); slen = min(MAX_LENGTH_MANUF, ABF_CREATORINFOLEN); strncpy(hdr->ID.Manufacturer._field, (char*)hdr->AS.Header + offsetof(struct ABFFileHeader, sCreatorInfo), slen); hdr->ID.Manufacturer._field[slen] = 0; hdr->ID.Manufacturer.Name = hdr->ID.Manufacturer._field; slen = min(MAX_LENGTH_RID, sizeof(((struct ABFFileHeader*)(hdr->AS.Header))->sFileComment)); strncpy(hdr->ID.Recording,(char*)hdr->AS.Header + offsetof(struct ABFFileHeader, sFileComment), slen); hdr->ID.Recording[slen] = 0; if (VERBOSE_LEVEL>7) { fprintf(stdout,"sCreatorInfo:\t%s\n",hdr->AS.Header + offsetof(struct ABFFileHeader, sCreatorInfo)); fprintf(stdout,"_sFileComment:\t%s\n",hdr->AS.Header + offsetof(struct ABFFileHeader, _sFileComment)); fprintf(stdout,"sFileComment:\t%s\n",hdr->AS.Header + offsetof(struct ABFFileHeader, sFileComment)); fprintf(stdout,"sFileComment:\t%s\n",hdr->AS.Header + offsetof(struct ABFFileHeader, sFileComment)); fprintf(stdout,"\nlHeaderSize:\t%i\n",lei32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lHeaderSize))); fprintf(stdout,"lTagSectionPtr:\t%i\n",lei32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lTagSectionPtr))); fprintf(stdout,"lNumTagEntries:\t%i\n",lei32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lNumTagEntries))); fprintf(stdout,"lVoiceTagPtr:\t%i\n",lei32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lVoiceTagPtr))); fprintf(stdout,"lVoiceTagEntries:\t%i\n",lei32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lVoiceTagEntries))); fprintf(stdout,"lSynchArrayPtr:\t%i\n",lei32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lSynchArrayPtr))); fprintf(stdout,"lSynchArraySize:\t%i\n",lei32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lSynchArraySize))); fprintf(stdout,"\nlDataSectionPtr:\t%i\n",lei32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lDataSectionPtr))); fprintf(stdout,"lScopeConfigPtr:\t%i\n",lei32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lScopeConfigPtr))); fprintf(stdout,"lNumScopes:\t%i\n",lei32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lNumScopes))); fprintf(stdout,"_lDACFilePtr:\t%i\n",lei32p(hdr->AS.Header + offsetof(struct ABFFileHeader, _lDACFilePtr))); fprintf(stdout,"_lDACFileNumEpisodes:\t%i\n",lei32p(hdr->AS.Header + offsetof(struct ABFFileHeader, _lDACFileNumEpisodes))); fprintf(stdout,"lDeltaArrayPtr:\t%i\n",lei32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lDeltaArrayPtr))); fprintf(stdout,"lNumDeltas:\t%i\n",lei32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lNumDeltas))); fprintf(stdout,"nDataFormat:\t%i\n",lei16p(hdr->AS.Header + offsetof(struct ABFFileHeader, nDataFormat))); fprintf(stdout,"nSimultaneousScan:\t%i\n",lei16p(hdr->AS.Header + offsetof(struct ABFFileHeader, nSimultaneousScan))); fprintf(stdout,"lStatisticsConfigPtr:\t%i\n",lei32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lStatisticsConfigPtr))); fprintf(stdout,"lAnnotationSectionPtr:\t%i\n",lei32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lAnnotationSectionPtr))); fprintf(stdout,"lNumAnnotations:\t%i\n",lei32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lNumAnnotations))); fprintf(stdout,"\nlNumSamplesPerEpisode:\t%i\n",lei32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lNumSamplesPerEpisode))); fprintf(stdout,"lPreTriggerSamples:\t%i\n",lei32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lPreTriggerSamples))); fprintf(stdout,"lEpisodesPerRun:\t%i\n",lei32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lEpisodesPerRun))); fprintf(stdout,"lActualAcqLength:\t%i\n",lei32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lActualAcqLength))); fprintf(stdout,"lActualEpisodes:\t%i\n",lei32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lActualEpisodes))); fprintf(stdout,"lRunsPerTrial:\t%i\n",lei32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lRunsPerTrial))); fprintf(stdout,"lNumberOfTrials:\t%i\n",lei32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lNumberOfTrials))); fprintf(stdout,"fADCRange:\t%f\n",lef32p(hdr->AS.Header + offsetof(struct ABFFileHeader, fADCRange))); fprintf(stdout,"fDACRange:\t%f\n",lef32p(hdr->AS.Header + offsetof(struct ABFFileHeader, fDACRange))); fprintf(stdout,"lADCResolution:\t%i\n",lei32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lADCResolution))); fprintf(stdout,"lDACResolution:\t%i\n",lei32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lDACResolution))); fprintf(stdout,"\nchannel_count_acquired:\t%i\n",lei16p(hdr->AS.Header + offsetof(struct ABFFileHeader, channel_count_acquired))); fprintf(stdout,"nADCNumChannels:\t%i\n",lei16p(hdr->AS.Header + offsetof(struct ABFFileHeader, nADCNumChannels))); fprintf(stdout,"fADCSampleInterval:\t%f\n",lef32p(hdr->AS.Header + offsetof(struct ABFFileHeader, fADCSampleInterval))); fprintf(stdout,"nDigitalDACChannel:\t%i\n",lei16p(hdr->AS.Header + offsetof(struct ABFFileHeader, nDigitalDACChannel))); fprintf(stdout,"nOperationMode:\t%i\n",lei16p(hdr->AS.Header + offsetof(struct ABFFileHeader, nOperationMode))); fprintf(stdout,"nDigitalEnable:\t%i\n",lei16p(hdr->AS.Header + offsetof(struct ABFFileHeader, nDigitalEnable))); fprintf(stdout,"\nfFileVersionNumber:\t%f\n",lef32p(hdr->AS.Header + offsetof(struct ABFFileHeader, fFileVersionNumber))); fprintf(stdout,"fHeaderVersionNumber:\t%f\n",lef32p(hdr->AS.Header + offsetof(struct ABFFileHeader, fHeaderVersionNumber))); fprintf(stdout,"fADCSampleInterval:\t%f\n",lef32p(hdr->AS.Header + offsetof(struct ABFFileHeader, fADCSampleInterval))); fprintf(stdout,"fADCSecondSampleInterval:\t%f\n",lef32p(hdr->AS.Header + offsetof(struct ABFFileHeader, fADCSecondSampleInterval))); fprintf(stdout,"fSynchTimeUnit:\t%f\n",lef32p(hdr->AS.Header + offsetof(struct ABFFileHeader, fSynchTimeUnit))); fprintf(stdout,"fSecondsPerRun:\t%f\n",lef32p(hdr->AS.Header + offsetof(struct ABFFileHeader, fSecondsPerRun))); fprintf(stdout,"fTriggerThreshold:\t%f\n",lef32p(hdr->AS.Header + offsetof(struct ABFFileHeader, fTriggerThreshold))); fprintf(stdout,"\nfScopeOutputInterval:\t%f\n",lef32p(hdr->AS.Header + offsetof(struct ABFFileHeader, fScopeOutputInterval))); fprintf(stdout,"fEpisodeStartToStart:\t%f\n",lef32p(hdr->AS.Header + offsetof(struct ABFFileHeader, fEpisodeStartToStart))); fprintf(stdout,"fRunStartToStart:\t%f\n",lef32p(hdr->AS.Header + offsetof(struct ABFFileHeader, fRunStartToStart))); fprintf(stdout,"fTrialStartToStart:\t%f\n",lef32p(hdr->AS.Header + offsetof(struct ABFFileHeader, fTrialStartToStart))); fprintf(stdout,"fStatisticsPeriod:\t%f\n",lef32p(hdr->AS.Header + offsetof(struct ABFFileHeader, fStatisticsPeriod))); fprintf(stdout,"fADCRange:\t%f\n",lef32p(hdr->AS.Header + offsetof(struct ABFFileHeader, fADCRange))); fprintf(stdout,"fDACRange:\t%f\n",lef32p(hdr->AS.Header + offsetof(struct ABFFileHeader, fTriggerThreshold))); fprintf(stdout,"fTriggerThreshold:\t%f\n",lef32p(hdr->AS.Header + offsetof(struct ABFFileHeader, fDACRange))); fprintf(stdout,"dFileDuration:\t%g\n",lef64p(hdr->AS.Header + offsetof(struct ABFFileHeader, dFileDuration))); fprintf(stdout,"fTriggerThreshold:\t%f\n",lef32p(hdr->AS.Header + offsetof(struct ABFFileHeader, fTriggerThreshold))); }
// Open a sam/bam file for reading with the specified filename. bool SamFile::OpenForRead(const char * filename, SamFileHeader* header) { // Reset for any previously operated on files. resetFile(); int lastchar = 0; while (filename[lastchar] != 0) lastchar++; // If at least one character, check for '-'. if((lastchar >= 1) && (filename[0] == '-')) { // Read from stdin - determine type of file to read. // Determine if compressed bam. if(strcmp(filename, "-.bam") == 0) { // Compressed bam - open as bgzf. // -.bam is the filename, read compressed bam from stdin filename = "-"; myFilePtr = new InputFile; // support recover mode - this switches in a reader // capable of recovering from bad BGZF compression blocks. myFilePtr->setAttemptRecovery(myAttemptRecovery); myFilePtr->openFile(filename, "rb", InputFile::BGZF); myInterfacePtr = new BamInterface; // Read the magic string. char magic[4]; ifread(myFilePtr, magic, 4); } else if(strcmp(filename, "-.ubam") == 0) { // uncompressed BAM File. // -.ubam is the filename, read uncompressed bam from stdin. // uncompressed BAM is still compressed with BGZF, but using // compression level 0, so still open as BGZF since it has a // BGZF header. filename = "-"; // Uncompressed, so do not require the eof block. #ifdef __ZLIB_AVAILABLE__ BgzfFileType::setRequireEofBlock(false); #endif myFilePtr = ifopen(filename, "rb", InputFile::BGZF); myInterfacePtr = new BamInterface; // Read the magic string. char magic[4]; ifread(myFilePtr, magic, 4); } else if((strcmp(filename, "-") == 0) || (strcmp(filename, "-.sam") == 0)) { // SAM File. // read sam from stdin filename = "-"; myFilePtr = ifopen(filename, "rb", InputFile::UNCOMPRESSED); myInterfacePtr = new SamInterface; } else { std::string errorMessage = "Invalid SAM/BAM filename, "; errorMessage += filename; errorMessage += ". From stdin, can only be '-', '-.sam', '-.bam', or '-.ubam'"; myStatus.setStatus(SamStatus::FAIL_IO, errorMessage.c_str()); delete myFilePtr; myFilePtr = NULL; return(false); } } else { // Not from stdin. Read the file to determine the type. myFilePtr = new InputFile; // support recovery mode - this conditionally enables a reader // capable of recovering from bad BGZF compression blocks. myFilePtr->setAttemptRecovery(myAttemptRecovery); bool rc = myFilePtr->openFile(filename, "rb", InputFile::DEFAULT); if (rc == false) { std::string errorMessage = "Failed to Open "; errorMessage += filename; errorMessage += " for reading"; myStatus.setStatus(SamStatus::FAIL_IO, errorMessage.c_str()); delete myFilePtr; myFilePtr = NULL; return(false); } char magic[4]; ifread(myFilePtr, magic, 4); if (magic[0] == 'B' && magic[1] == 'A' && magic[2] == 'M' && magic[3] == 1) { myInterfacePtr = new BamInterface; // Set that it is a bam file open for reading. This is needed to // determine if an index file can be used. myIsBamOpenForRead = true; } else { // Not a bam, so rewind to the beginning of the file so it // can be read. ifrewind(myFilePtr); myInterfacePtr = new SamInterface; } } // File is open for reading. myIsOpenForRead = true; // Read the header if one was passed in. if(header != NULL) { return(ReadHeader(*header)); } // Successfully opened the file. myStatus = SamStatus::SUCCESS; return(true); }
bool glfHandler::NextEntry() { if (isStub) return false; // Read record type if (endOfSection || (ifread(handle, &data, 1) != 1)) { endOfSection = true; data.recordType = 0; position = maxPosition + 1; return false; } // printf("%d/%d\n", data.recordType, data.refBase); if (position > maxPosition) return true; switch (data.recordType) { case 0 : endOfSection = true; position = maxPosition + 1; return true; case 1 : if (ifread(handle,((char *) &data) + 1, sizeof(data) - 1) == sizeof(data) - 1) { data.refBase = translateBase[data.refBase]; for (int i = 0; i < 10; i++) likelihoods[i] = bQualityConvertor.toDouble(data.lk[i]); position = position + data.offset; return true; } // Premature end of file data.recordType = 0; position = maxPosition + 1; return false; case 2 : while (ifread(handle, ((char *) &data) + 1, sizeof(data) - 4) == sizeof(data) - 4) { data.refBase = translateBase[data.refBase]; for (int i = 0; i < 3; i++) likelihoods[i] = bQualityConvertor.toDouble(data.indel.lk[i]); position = position + data.offset; indelSequence[0].SetLength(abs(data.indel.length[0]) + 1); indelSequence[0][abs(data.indel.length[0])] = 0; if (ifread(handle, indelSequence[0].LockBuffer(), abs(data.indel.length[0])) != (unsigned int) abs(data.indel.length[0])) break; indelSequence[1].SetLength(abs(data.indel.length[1]) + 1); indelSequence[1][abs(data.indel.length[1])] = 0; if (ifread(handle, indelSequence[1].LockBuffer(), abs(data.indel.length[1])) != (unsigned int) abs(data.indel.length[1])) break; return true; } // Premature end of file data.recordType = 0; position = maxPosition + 1; return false; } return false; }
EXTERN_C void sopen_alpha_read(HDRTYPE* hdr) { /* this function will be called by the function SOPEN in "biosig.c" Input: char* Header // contains the file content Output: HDRTYPE *hdr // defines the HDR structure accoring to "biosig.h" */ size_t count; unsigned int k; const char *FileName = hdr->FileName; fprintf(stdout,"Warning: support for alpha format is just experimental.\n"); char* fn = (char*)malloc(strlen(hdr->FileName)+15); strcpy(fn,hdr->FileName); // Flawfinder: ignore const size_t bufsiz = 4096; char buf[bufsiz]; // alpha.alp cal_res digin digvidtc eog marker measure mkdef montage rawdata rawhead report.txt r_info sleep const char *f2 = "alpha.alp"; char *tmpstr = strrchr(fn,FILESEP); if (tmpstr) strcpy(tmpstr+1,f2); // Flawfinder: ignore else strcpy(fn,f2); // Flawfinder: ignore FILE *fid = fopen(fn,"r"); count = fread(buf,1,bufsiz-1,fid); fclose(fid); buf[count]=0; // terminating 0 character char *t = strtok(buf,"\xA\xD"); while (t) { if (VERBOSE_LEVEL>7) fprintf(stdout,"0: %s \n",t); if (!strncmp(t,"Version = ",9)) hdr->VERSION = atof(t+9); else if (!strncmp(t,"Id = ",4)) { strncpy(hdr->ID.Manufacturer._field,t+5,MAX_LENGTH_MANUF); hdr->ID.Manufacturer.Name = hdr->ID.Manufacturer._field; } t = strtok(NULL,"\xA\xD"); } f2 = "rawhead"; if (tmpstr) strcpy(tmpstr+1,f2); // Flawfinder: ignore else strcpy(fn,f2); // Flawfinder: ignore int Notch = 0; int Bits = 0; double DigMax=0, DigMin=0; uint16_t gdftyp = 0; int ns = 0; fid = fopen(fn,"r"); count = fread(buf,1,bufsiz-1,fid); fclose(fid); buf[count]=0; // terminating 0 character t = strtok(buf,"\xA\xD"); char STATUS = 1; uint32_t *ChanOrder=NULL; char **ChanType = NULL; while ((t!=NULL) && (STATUS<9)) { char *t1 = strchr(t,'='); if (VERBOSE_LEVEL>7) fprintf(stdout,"<%6.2f> %i- %s | %s\n",hdr->VERSION, STATUS,t,t1); if (t1) { t1[-1] = 0; t1++; if (STATUS == 1) { if (!strcmp(t,"Version")) hdr->VERSION = atof(t1); else if (!strcmp(t,"BitsPerValue")) { Bits = atoi(t1); switch (Bits) { case 12: gdftyp = 255+12; // hdr->FILE.LittleEndian = 0; DigMax = (1<<(Bits-1))-1; DigMin = -(1<<(Bits-1)); break; case 16: gdftyp = 3; DigMax = 32752.0; //!!! that's the maximum value found in alpha-trace files DigMin = -32736.0; //!!! that's the minimum value found in alpha-trace files break; case 32: gdftyp = 5; break; DigMax = (1<<(Bits-1))-1; DigMin = -(1<<(Bits-1)); } } else if (!strcmp(t,"ChanCount")) { hdr->NS = atoi(t1); hdr->CHANNEL = (CHANNEL_TYPE*)realloc(hdr->CHANNEL, hdr->NS*sizeof(CHANNEL_TYPE)); ChanOrder = (uint32_t*)calloc(hdr->NS,sizeof(uint32_t)*2); ChanType = (char**)calloc(hdr->NS,sizeof(char*)); } else if (!strcmp(t,"SampleFreq")) hdr->SampleRate = atof(t1); else if (!strcmp(t,"SampleCount")) { hdr->NRec = atoi(t1); hdr->SPR = 1; } else if (!strcmp(t,"NotchFreq")) Notch = atof(t1); else if (!strcmp(t,"DispFlags") && (hdr->VERSION < 411.89)) STATUS = 2; else if (!strcmp(t,"Sec2Marker") && (hdr->VERSION > 411.89)) STATUS = 2; } else if (STATUS == 2) { if (ns>=hdr->NS) { ns = 0; STATUS = 3; } else { CHANNEL_TYPE *hc = hdr->CHANNEL+ns; hc->GDFTYP = gdftyp; hc->Notch = Notch; hc->LeadIdCode = 0; hc->SPR = hdr->SPR; //hc->bi8 = GDFTYP_BITS[gdftyp]*ns; hc->DigMax = DigMax; hc->DigMin = DigMin; hc->OnOff = 1; hc->Cal = 1.0; hc->Off = 0.0; hc->PhysMax = hc->DigMax; hc->PhysMin = hc->DigMin; strncpy(hc->Label, t, MAX_LENGTH_LABEL+1); char* t2= strchr(t1,','); t2[0] = 0; while (isspace((++t2)[0])); char* t3= strchr(t2,','); t3[0] = 0; while (isspace((++t3)[0])); char* t4= strchr(t3,','); t4[0] = 0; while (isspace((++t4)[0])); ChanOrder[ns*2] = atoi(t2); ChanOrder[ns*2+1] = ns; ChanType[ns] = t3; ns++; } } else if (STATUS == 3) { // decode information (filters, PhysDim, etc.) and assign to corresponding channels. char *pd = NULL; float tmp1, tmp2, HighPass, LowPass; #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L sscanf(t1, "%f, %f, %f, %f, %as", &HighPass,&LowPass, &tmp1,&tmp2, &pd); #else sscanf(t1, "%f, %f, %f, %f, %ms", &HighPass,&LowPass, &tmp1,&tmp2, &pd); #endif strrchr(pd,',')[0]=0; if (!strcmp(pd,"%%")) pd[1]=0; uint16_t pdc = PhysDimCode(pd); if (pd) free(pd); char flag = 0; for (k=0; k < hdr->NS; k++) { if ((ChanType[k]!=NULL) && !strcmp(t,ChanType[k])) { CHANNEL_TYPE *hc = hdr->CHANNEL+k; hc->PhysDimCode = pdc; //strcpy(hc->PhysDim,pd); hc->LowPass = LowPass; hc->HighPass = HighPass; ChanType[k] = NULL; } if (ChanType[k] != NULL) flag = 1; // not done yet } if (!flag) STATUS = 99; // done with channel definition } } t = strtok(NULL,"\xA\xD"); } hdr->AS.bpb8 = (GDFTYP_BITS[gdftyp]*hdr->NS); // hdr->AS.bpb = (GDFTYP_BITS[gdftyp]*hdr->NS)>>3; // do not rely on this, because some bits can get lost // sort channels qsort(ChanOrder,hdr->NS,2*sizeof(uint32_t),&u32cmp); for (k=0; k<hdr->NS; k++) { hdr->CHANNEL[ChanOrder[2*k+1]].bi8 = GDFTYP_BITS[gdftyp]*k; hdr->CHANNEL[ChanOrder[2*k+1]].bi = (GDFTYP_BITS[gdftyp]*k)>>3; } free(ChanOrder); free(ChanType); f2 = "cal_res"; if (tmpstr) strcpy(tmpstr+1,f2); // Flawfinder: ignore else strcpy(fn,f2); // Flawfinder: ignore fid = fopen(fn,"r"); if (fid!=NULL) { if (VERBOSE_LEVEL>7) fprintf(stdout,"cal_res: \n"); count = fread(buf,1,bufsiz-1,fid); fclose(fid); buf[count]=0; // terminating 0 character t = strtok(buf,"\xA\xD"); t = strtok(NULL,"\xA\xD"); // skip lines 1 and 2 /* char label[MAX_LENGTH_LABEL+1]; char flag[MAX_LENGTH_LABEL+1]; double cal,off; */ char *t0,*t1,*t2,*t3; unsigned n=0; // for (k=0; max(k,n)<hdr->NS; k++) { t = strtok(NULL,"\xA\xD"); if (t==NULL) { fprintf(stderr,"Warning SOPEN(alpha): scaling coefficients not defined for all channels\n"); break; } // strncpy(hc->Label,t,min(strcspn(t," =,"),MAX_LENGTH_LABEL)); t0 = strchr(t,'=');t0[0]=0;t0++; int ix = strlen(t)-1; while ((ix>0) && isspace(t[ix])) t[ix--] = 0; // remove trailing spaces t1 = strchr(t0,',');t1[0]=0;t1++; t2 = strchr(t1,',');t2[0]=0;t2++; t3 = strchr(t2,',');t3[0]=0;t3++; n = atoi(t); // n==0 if label is provided, n>0 if channel number is provided /* does not work because ambigous labels are used in rawhead and cal_res (e.g. T3 and T7) if (!n) for (n=0; n<hdr->NS; n++) { if (!strcmp(hdr->CHANNEL[n].Label,t)) { n++; break; } } */ if (VERBOSE_LEVEL>7) fprintf(stdout,"cal_res: %i %i <%s> %s %s %s\n",k,n,t,t1,t2,t3); CHANNEL_TYPE *hc = hdr->CHANNEL + (n>0 ? n-1 : k); // channel can be denoted by label or number hc->Cal = atof(t1); hc->Off = 0; if (VERBOSE_LEVEL>7) fprintf(stdout," <%s> %s = ###, %f, %f\n", t1,hc->Label,hc->Cal,hc->Off); hc->PhysMax = (hc->DigMax - hc->Off) * hc->Cal; hc->PhysMin = (hc->DigMin - hc->Off) * hc->Cal; hc->XYZ[0]=0; hc->XYZ[1]=0; hc->XYZ[2]=0; } } f2 = "r_info"; if (tmpstr) strcpy(tmpstr+1,f2); // Flawfinder: ignore else strcpy(fn,f2); // Flawfinder: ignore fid = fopen(fn,"r"); if (fid!=NULL) { if (VERBOSE_LEVEL>7) fprintf(stdout,"r_info: \n"); count = fread(buf,1,bufsiz-1,fid); fclose(fid); buf[count]=0; // terminating 0 character struct tm T; t = strtok(buf,"\xA\xD"); t = strtok(NULL,"\xA\xD"); // skip line 1 while (t!=NULL) { char *t1 = strchr(t,'='); t1[0] = 0; while (isspace((++t1)[0])); for (k=strlen(t); (k>0) && isspace(t[--k]); t[k]=0); for (k=strlen(t1); (k>0) && isspace(t1[--k]); t1[k]=0); if (VERBOSE_LEVEL>7) fprintf(stdout,"r_info: %s = %s\n",t,t1); if (0) {} else if (!strcmp(t,"RecId")) strncpy(hdr->ID.Recording,t1,MAX_LENGTH_RID); else if (!strcmp(t,"RecDate")) { sscanf(t1,"%02d.%02d.%04d",&T.tm_mday,&T.tm_mon,&T.tm_year); T.tm_year -=1900; T.tm_mon -=1; } else if (!strcmp(t,"RecTime")) sscanf(t1,"%02d.%02d.%02d",&T.tm_hour,&T.tm_min,&T.tm_sec); else if (!strcmp(t,"TechSal")) { if (hdr->ID.Technician) free(hdr->ID.Technician); hdr->ID.Technician = strdup(t1); } else if (!strcmp(t,"TechTitle") || !strcmp(t,"TechLast") || !strcmp(t,"TechFirst")) { size_t l0 = strlen(hdr->ID.Technician); size_t l1 = strlen(t1); hdr->ID.Technician = (char*)realloc(hdr->ID.Technician,l0+l1+2); hdr->ID.Technician[l0] = ' '; strcpy(hdr->ID.Technician+l0+1, t1); // Flawfinder: ignore } t = strtok(NULL,"\xA\xD"); } hdr->T0 = tm_time2gdf_time(&T); } f2 = "marker"; if (tmpstr) strcpy(tmpstr+1,f2); // Flawfinder: ignore else strcpy(fn,f2); // Flawfinder: ignore fid = fopen(fn,"r"); if (fid != NULL) { size_t n,N; N=0; n=0; while (!feof(fid)) { hdr->AS.auxBUF = (uint8_t*) realloc(hdr->AS.auxBUF,N+bufsiz+1); N += fread(hdr->AS.auxBUF+N, 1, bufsiz, fid); } fclose(fid); hdr->AS.auxBUF[N] = 0; // terminating 0 character N = 0; t = (char*)hdr->AS.auxBUF+strcspn((char*)hdr->AS.auxBUF,"\xA\xD"); t = t+strspn(t,"\xA\xD"); // skip lines 1 and 2 while (t[0]) { char* t1 = t; size_t l1 = strcspn(t1,"="); size_t p2 = strspn(t1+l1,"= ")+l1; char* t2 = t+p2; size_t l2 = strcspn(t2," ,"); size_t p3 = strspn(t2+l2," ,")+l2; char* t3 = t2+p3; size_t l3 = strcspn(t3," ,"); size_t p4 = strspn(t3+l3," ,")+l3; char* t4 = t3+p4; size_t l4 = strcspn(t4,"\xA\xD"); size_t p5 = strspn(t4+l4,"\xA\xD")+l4; t1[l1] = 0; while (isspace(t1[--l1])) t1[l1]=0; t2[l2] = 0; t3[l3] = 0; t4[l4] = 0; t = t4 + p5; if (n+1 >= N) { const size_t sz = 100; hdr->EVENT.TYP = (typeof(hdr->EVENT.TYP)) realloc(hdr->EVENT.TYP,(N+sz)*sizeof(*hdr->EVENT.TYP)); hdr->EVENT.POS = (typeof(hdr->EVENT.POS)) realloc(hdr->EVENT.POS,(N+sz)*sizeof(*hdr->EVENT.POS)); N += sz; } hdr->EVENT.POS[n] = atol(t3); if (!strcmp(t1,"REC")) hdr->EVENT.TYP[n] = 0x7ffe; else if (!strcmp(t1,"MON")) hdr->EVENT.TYP[n] = 0; else if (!strcmp(t1,"TXT")) FreeTextEvent(hdr, n, t4); else FreeTextEvent(hdr, n, t1); if (!strcmp(t2,"off")) hdr->EVENT.TYP[n] |= 0x8000; //fprintf(stdout,"#%u, 0x%04x,%u | t1=<%s> = t2=<%s>, t3=<%s>, t4=<%s>\n",n,hdr->EVENT.TYP[n],hdr->EVENT.POS[n],t1,t2,t3,t4); n++; // t = strtok(NULL,"\xA\xD"); //fprintf(stdout," <%s>\n",t1); } hdr->EVENT.N = n; hdr->EVENT.SampleRate = hdr->SampleRate; // convert2to4_eventtable(hdr); } tmpstr = strrchr(fn,FILESEP); tmpstr[0] = 0; tmpstr = strrchr(fn,FILESEP); f2 = "s_info"; if (tmpstr) strcpy(tmpstr+1,f2); // Flawfinder: ignore else strcpy(fn,f2); // Flawfinder: ignore fid = fopen(fn,"r"); if (fid!=NULL) { count = fread(buf,1,bufsiz-1,fid); fclose(fid); buf[count]=0; // terminating 0 character char *Lastname = NULL; char *Firstname = NULL; struct tm T; t = strtok(buf,"\xA\xD"); t = strtok(NULL,"\xA\xD"); // skip line 1 while (t!=NULL) { char *t1 = strchr(t,'='); t1[0] = 0; while (isspace((++t1)[0])); for (k=strlen(t); (k>0) && isspace(t[--k]); t[k]=0); for (k=strlen(t1); (k>0) && isspace(t1[--k]); t1[k]=0); if (VERBOSE_LEVEL>7) fprintf(stdout,"s_info: <%s> = <%s>\n",t,t1); if (0) {} else if (!strcmp(t,"SubjId")) strncpy(hdr->Patient.Id,t1,MAX_LENGTH_PID); else if (!strcmp(t,"Gender")) switch (t1[0]) { case 'm': case 'M': hdr->Patient.Sex = 1; break; case 'w': case 'W': case 'f': case 'F': hdr->Patient.Sex = 2; break; default: hdr->Patient.Sex = 0; break; } else if (!strcmp(t,"Handedness")) switch (t1[0]) { case 'r': case 'R': hdr->Patient.Handedness = 1; break; case 'l': case 'L': hdr->Patient.Handedness = 2; break; default: hdr->Patient.Handedness = 0; break; } else if (!strcmp(t,"Size")) hdr->Patient.Height = atof(t1); else if (!strcmp(t,"Weight")) hdr->Patient.Weight = atof(t1); else if (!strcmp(t,"FirstName")) { Firstname = t1; } else if (!strcmp(t,"LastName")) { Lastname = t1; } else if (!strcmp(t,"BirthDay")) { int c = sscanf(t1,"%02d.%02d.%04d",&T.tm_mday,&T.tm_mon,&T.tm_year); T.tm_year -=1900; T.tm_mon -=1; T.tm_hour =12; T.tm_min =0; T.tm_sec =0; if (c > 2) hdr->Patient.Birthday = tm_time2gdf_time(&T); } t = strtok(NULL,"\xA\xD"); } size_t l0 = strlen(Firstname); size_t l1 = strlen(Lastname); if (l0+l1+1 <= MAX_LENGTH_NAME) { strcpy(hdr->Patient.Name, Firstname); // Flawfinder: ignore hdr->Patient.Name[l0] = ' '; strcpy(hdr->Patient.Name + l0 + 1, Lastname); // Flawfinder: ignore } else strncpy(hdr->Patient.Name, Lastname, MAX_LENGTH_NAME+1); // Flawfinder: ignore } strcpy(fn,hdr->FileName); // Flawfinder: ignore tmpstr = strrchr(fn,FILESEP); f2 = "rawdata"; if (tmpstr) strcpy(tmpstr+1,f2); // Flawfinder: ignore else strcpy(fn,f2); // Flawfinder: ignore if (VERBOSE_LEVEL>7) fprintf(stdout,"rawdata11: %s \n",f2); hdr->FileName = fn; ifopen(hdr,"r"); if (VERBOSE_LEVEL>7) fprintf(stdout,"rawdata22: %s open=%i\n",f2,hdr->FILE.OPEN); if (hdr->FILE.OPEN) { int16_t a[3]; ifread(a, 2, 3, hdr); hdr->VERSION = a[0]; hdr->HeadLen = 6; switch (a[2]) { case 12: gdftyp = 255+12; break; case 16: gdftyp = 3; break; case 32: gdftyp = 5; break; } for (k=a[1]; k<hdr->NS; k++) hdr->CHANNEL[k].OnOff = 0; for (k=0; k<hdr->NS; k++) { hdr->CHANNEL[k].GDFTYP = gdftyp; } hdr->AS.bpb = (GDFTYP_BITS[gdftyp]*a[1])>>3; hdr->FILE.POS = 0; size_t len = (GDFTYP_BITS[gdftyp]*a[1]*hdr->NRec*hdr->SPR)>>3; if ((GDFTYP_BITS[gdftyp]*a[1]) & 0x07) { /* hack: if SPR*NS*bits are not a multiple of bytes, hdr->AS.bpb would be non-integer causing some problems in SREAD reading the correct number of bytes. This hack makes sure that all data is loaded. */ len++; } hdr->AS.rawdata = (uint8_t*) realloc(hdr->AS.rawdata, len); size_t count = ifread(hdr->AS.rawdata,1,len,hdr); hdr->AS.first = 0; hdr->AS.length = (count<<3)/(GDFTYP_BITS[gdftyp]*a[1]); }
// Read & parse the specified index file. SamStatus::Status BamIndex::readIndex(const char* filename) { // Reset the index from anything that may previously be set. resetIndex(); IFILE indexFile = ifopen(filename, "rb"); // Failed to open the index file. if(indexFile == NULL) { return(SamStatus::FAIL_IO); } // generate the bam index structure. // Read the magic string. char magic[4]; if(ifread(indexFile, magic, 4) != 4) { // Failed to read the magic ifclose(indexFile); return(SamStatus::FAIL_IO); } // If this is not an index file, set num references to 0. if (magic[0] != 'B' || magic[1] != 'A' || magic[2] != 'I' || magic[3] != 1) { // Not a BAM Index file. ifclose(indexFile); return(SamStatus::FAIL_PARSE); } // It is a bam index file. // Read the number of reference sequences. if(ifread(indexFile, &n_ref, 4) != 4) { // Failed to read. ifclose(indexFile); return(SamStatus::FAIL_IO); } // Size the references. myRefs.resize(n_ref); for(int refIndex = 0; refIndex < n_ref; refIndex++) { // Read each reference. Reference* ref = &(myRefs[refIndex]); // Read the number of bins. if(ifread(indexFile, &(ref->n_bin), 4) != 4) { // Failed to read the number of bins. // Return failure. ifclose(indexFile); return(SamStatus::FAIL_PARSE); } // If there are no bins, then there are no // mapped/unmapped reads. if(ref->n_bin == 0) { ref->n_mapped = 0; ref->n_unmapped = 0; } // Resize the bins so they can be indexed by bin number. ref->bins.resize(ref->n_bin + 1); // Read each bin. for(int binIndex = 0; binIndex < ref->n_bin; binIndex++) { uint32_t binNumber; // Read in the bin number. if(ifread(indexFile, &(binNumber), 4) != 4) { // Failed to read the bin number. // Return failure. ifclose(indexFile); return(SamStatus::FAIL_IO); } // Add the bin to the reference and get the // pointer back so the values can be set in it. Bin* binPtr = &(ref->bins[binIndex]); binPtr->bin = binNumber; // Read in the number of chunks. if(ifread(indexFile, &(binPtr->n_chunk), 4) != 4) { // Failed to read number of chunks. // Return failure. ifclose(indexFile); return(SamStatus::FAIL_IO); } // Read in the chunks. // Allocate space for the chunks. uint32_t sizeOfChunkList = binPtr->n_chunk * sizeof(Chunk); binPtr->chunks = (Chunk*)malloc(sizeOfChunkList); if(ifread(indexFile, binPtr->chunks, sizeOfChunkList) != sizeOfChunkList) { // Failed to read the chunks. // Return failure. ifclose(indexFile); return(SamStatus::FAIL_IO); } // Determine the min/max for this bin if it is not the max bin. if(binPtr->bin != MAX_NUM_BINS) { for(int i = 0; i < binPtr->n_chunk; i++) { if(binPtr->chunks[i].chunk_beg < ref->minChunkOffset) { ref->minChunkOffset = binPtr->chunks[i].chunk_beg; } if(binPtr->chunks[i].chunk_end > ref->maxChunkOffset) { ref->maxChunkOffset = binPtr->chunks[i].chunk_end; } if(binPtr->chunks[i].chunk_end > maxOverallOffset) { maxOverallOffset = binPtr->chunks[i].chunk_end; } } } else { // Mapped/unmapped are the last chunk of the // MAX BIN ref->n_mapped = binPtr->chunks[binPtr->n_chunk - 1].chunk_beg; ref->n_unmapped = binPtr->chunks[binPtr->n_chunk - 1].chunk_end; } } // Read the number of intervals. if(ifread(indexFile, &(ref->n_intv), 4) != 4) { // Failed to read, set to 0. ref->n_intv = 0; // Return failure. ifclose(indexFile); return(SamStatus::FAIL_IO); } // Allocate space for the intervals and read them. uint32_t linearIndexSize = ref->n_intv * sizeof(uint64_t); ref->ioffsets = (uint64_t*)malloc(linearIndexSize); if(ifread(indexFile, ref->ioffsets, linearIndexSize) != linearIndexSize) { // Failed to read the linear index. // Return failure. ifclose(indexFile); return(SamStatus::FAIL_IO); } } int32_t numUnmapped = 0; if(ifread(indexFile, &numUnmapped, sizeof(int32_t)) == sizeof(int32_t)) { myUnMappedNumReads = numUnmapped; } // Successfully read the bam index file. ifclose(indexFile); return(SamStatus::SUCCESS); }
void BedFile::openForRead(const char* bedFile, const char* bimFile, const char* famFile, const char* refFile, int nbuf) { StringArray tokens; reset(); iFile = ifopen(bedFile,"rb"); if ( iFile == NULL ) { throw VcfFileException("Failed opening file %s - %s",bedFile,strerror(errno)); } // read magic numbers char magicNumbers[3] = {0x6c,0x1b,0x01}; char firstThreeBytes[3]; ifread( iFile, firstThreeBytes, 3 ); for(int i=0; i < 3; ++i) { if ( firstThreeBytes[i] != magicNumbers[i] ) { throw VcfFileException("The magic numbers do not match in BED file %s",bedFile); } } iBimFile = ifopen(bimFile,"rb"); iFamFile = ifopen(famFile,"rb"); sRefFile = refFile; while( 1 ) { int ret = line.ReadLine(iFamFile); if ( ret <= 0 ) break; tokens.ReplaceTokens(line, " \t\r\n"); if ( tokens.Length() < 5 ) { throw VcfFileException("Less then 5 columns are observed in FAM file"); } VcfInd* p = new VcfInd(tokens[1],tokens[0],tokens[2],tokens[3],tokens[4]); vpVcfInds.push_back(p); } //Logger::gLogger->writeLog("Finished loading %d individuals from FAM file",(int)vpVcfInds.size()); nBytes = (vpVcfInds.size()+3)/4; if ( pBedBuffer != NULL ) { delete[] pBedBuffer; } pBedBuffer = new char[nBytes]; nBuffers = nbuf; nNumMarkers = 0; nHead = 0; bParseGenotypes = true; bParseDosages = false; bParseValues = false; if ( nBuffers == 0 ) { // infinite buffer size // do not set size of markers } else { vpVcfMarkers.resize( nBuffers ); for(int i=0; i < nBuffers; ++i) { VcfMarker* p = new VcfMarker; vpVcfMarkers[i] = p; } } genomeSequence.setReferenceName(sRefFile.c_str()); genomeSequence.useMemoryMap(true); //Logger::gLogger->writeLog("Loading reference file %s",sRefFile.c_str()); if ( genomeSequence.open() ) { // write a message that new index file is being created if ( genomeSequence.create(false) ) { throw VcfFileException("Failed creating index file of the reference. Please check the file permission"); } if ( genomeSequence.open() ) { throw VcfFileException("Failed opening index file of the reference."); } } }
// Read a BAM file's header. bool BamInterface::readHeader(IFILE filePtr, SamFileHeader& header, SamStatus& status) { if(filePtr == NULL) { // File is not open, return false. status.setStatus(SamStatus::FAIL_ORDER, "Cannot read header since the file pointer is null"); return(false); } if(filePtr->isOpen() == false) { status.setStatus(SamStatus::FAIL_ORDER, "Cannot read header since the file is not open"); return(false); } // Clear the passed in header. header.resetHeader(); int32_t headerLength; int readSize = ifread(filePtr, &headerLength, sizeof(headerLength)); if(readSize != sizeof(headerLength)) { String errMsg = "Failed to read the BAM header length, read "; errMsg += readSize; errMsg += " bytes instead of "; errMsg += (unsigned int)sizeof(headerLength); status.setStatus(SamStatus::FAIL_IO, errMsg.c_str()); return(false); } String headerStr; if(headerLength > 0) { // Read the header. readSize = ifread(filePtr, headerStr.LockBuffer(headerLength + 1), headerLength); headerStr[headerLength] = 0; headerStr.UnlockBuffer(); if(readSize != headerLength) { // Failed to read the header. status.setStatus(SamStatus::FAIL_IO, "Failed to read the BAM header."); return(false); } } // Parse the header that was read. if(!header.addHeader(headerStr)) { // Status is set in the method on failure. status.setStatus(SamStatus::FAIL_PARSE, header.getErrorMessage()); return(false); } int referenceCount; // Read the number of references sequences. ifread(filePtr, &referenceCount, sizeof(int)); // Get and clear the reference info so it can be set // from the bam reference table. SamReferenceInfo& refInfo = header.getReferenceInfoForBamInterface(); refInfo.clear(); CharBuffer refName; // Read each reference sequence for (int i = 0; i < referenceCount; i++) { int nameLength; int rc; // Read the length of the reference name. rc = ifread(filePtr, &nameLength, sizeof(int)); if(rc != sizeof(int)) { status.setStatus(SamStatus::FAIL_IO, "Failed to read the BAM reference dictionary."); return(false); } // Read the name. refName.readFromFile(filePtr, nameLength); // Read the length of the reference sequence. int32_t refLen; rc = ifread(filePtr, &refLen, sizeof(int)); if(rc != sizeof(int)) { status.setStatus(SamStatus::FAIL_IO, "Failed to read the BAM reference dictionary."); return(false); } refInfo.add(refName.c_str(), refLen); } // Successfully read the file. return(true); }
bool BedFile::iterateMarker() { // read a marker information from BIM file if ( line.ReadLine(iBimFile) > 0 ) { ++nNumLines; } else { return false; } lineTokens.ReplaceTokens(line, " \t\r\n"); VcfMarker* pMarker; if ( nBuffers == 0 ) { pMarker = new VcfMarker; vpVcfMarkers.push_back(pMarker); ++nNumMarkers; ++nHead; } else { // make a circular list with constant size nBuffer pMarker = vpVcfMarkers[nHead]; nHead = (nHead+1) % nBuffers; ++nNumMarkers; } if ( lineTokens.Length() < 6 ) { throw VcfFileException("BIM file has only %d columns - %s",lineTokens.Length(),lineTokens[0].c_str()); } try { String strChr = lineTokens[0]; if ( strChr.Compare("23") == 0 ) { strChr = "X"; } else if ( strChr.Compare("24") == 0 ) { strChr = "Y"; } else if ( strChr.Compare("25") == 0 ) { strChr = "XY"; } else if ( strChr.Compare("26") == 0 ) { strChr = "MT"; } // try to resolve different conventions for chromosome names by using // (1) original chr // (2) strChr : 23 -> "X", 24 -> "Y", 25 -> "XY", 26 -> "MT" // (3) "chr"+ chr // (4) "chr"+ strChr pMarker->setPos(lineTokens[3]); genomeIndex_t markerIndex = genomeSequence.getGenomePosition( lineTokens[0].c_str(), pMarker->nPos ); if ( markerIndex == INVALID_GENOME_INDEX ) { // routines specific to BED file format markerIndex = genomeSequence.getGenomePosition( strChr.c_str(), pMarker->nPos ); if ( markerIndex == INVALID_GENOME_INDEX ) { strChr = String("chr") + strChr; markerIndex = genomeSequence.getGenomePosition( strChr.c_str(), pMarker->nPos ); if ( markerIndex == INVALID_GENOME_INDEX ) { throw VcfFileException("Cannot parse chromosome name "+lineTokens[0]+" in BIM file"); } } } pMarker->setChrom(strChr); pMarker->setID(lineTokens[1]); // determine refBase/altBase // if refBase matches a1 or a2, use it // if none matches and either is zero // do not allow for triallelic sites char refBase = genomeSequence[markerIndex]; char a1 = lineTokens[4][0]; char a2 = lineTokens[5][0]; char altBase = determineAltBase(refBase, a1,a2); pMarker->setRef(String(refBase)); pMarker->setAlts(String(altBase)); // read genotypes ifread(iFile, pBedBuffer, nBytes); pMarker->setSampleSize((int)vpVcfInds.size(),bParseGenotypes,bParseDosages,bParseValues); int AC = 0, AN = 0, NS = 0; for(int i=0; i < (int)vpVcfInds.size(); ++i) { char g = (pBedBuffer[i/4] >> ((i % 4)*2)) & 0x03; //Logger::gLogger->writeLog("i = %d, g = %d",i,(int)g); switch(g) { case 0: // 0/0 -> 0x00 if ( bRefIsAllele1 ) { pMarker->setGenotype(i,0x0000); // 0/0 } else { pMarker->setGenotype(i,0x0101); // 0/0 AC += 2; } AN += 2; ++NS; break; case 1: pMarker->setGenotype(i,0xffff); // missing break; case 2: // 0/1 pMarker->setGenotype(i,0x0001); // 0/1 ++AC; AN += 2; ++NS; break; case 3: if ( bRefIsAllele1 ) { pMarker->setGenotype(i,0x0101); // 1/1 AC += 2; } else { pMarker->setGenotype(i,0x0000); // 0/0 } AN += 2; ++NS; break; default: throw VcfFileException("Error in parsing genotypes"); } } pMarker->setQual("."); pMarker->setFilters("."); String info; if ( AN > 0 ) { info.printf("NS=%d;AC=%d;AN=%d;AF=%.6lf",NS,AC,AN,(double)AC/(double)AN); } else { info.printf("NS=%d;AC=%d;AN=%d",NS,AC,AN); } pMarker->setInfo(info, false); return true; } catch (VcfFileException exc) { // add the line number to the error message throw VcfFileException(exc.msg + " See line " + nNumLines + "."); } }
/**************************************************************************** sopen_heka reads heka format if itx is not null, the file is converted into an ITX formated file and streamed to itx, too. ****************************************************************************/ void sopen_heka(HDRTYPE* hdr, FILE *itx) { size_t count = hdr->HeadLen; if (hdr->TYPE==HEKA && hdr->VERSION > 1) { int32_t Levels=0; uint16_t k; //int32_t *Sizes=NULL; int32_t Counts[5], counts[5]; //, Sizes[5]; memset(Counts,0,20); memset(counts,0,20); //memset(Sizes,0,20); uint32_t StartOfData=0,StartOfPulse=0; union { struct { int32_t Root; int32_t Group; int32_t Series; int32_t Sweep; int32_t Trace; } Rec; int32_t all[5]; } Sizes; // HEKA PatchMaster file format count = hdr->HeadLen; struct stat FileBuf; stat(hdr->FileName,&FileBuf); hdr->AS.Header = (uint8_t*)realloc(hdr->AS.Header, FileBuf.st_size); count += ifread(hdr->AS.Header+count, 1, 1024-count, hdr); hdr->HeadLen = count; hdr->FILE.LittleEndian = *(uint8_t*)(hdr->AS.Header+52) > 0; char SWAP = ( hdr->FILE.LittleEndian && (__BYTE_ORDER == __BIG_ENDIAN)) \ || (!hdr->FILE.LittleEndian && (__BYTE_ORDER == __LITTLE_ENDIAN)); if (SWAP) { biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "Heka/Patchmaster format requires data swapping - this is not supported yet."); return; } SWAP = 0; // might be useful for compile time optimization /* get file size and read whole file */ count += ifread(hdr->AS.Header+count, 1, FileBuf.st_size - count, hdr); if (VERBOSE_LEVEL>7) fprintf(stdout,"%s (line %i) %s(...): %i bytes read\n",__FILE__,__LINE__,__func__, count); // double oTime; uint32_t nItems; if (hdr->FILE.LittleEndian) { // oTime = lef64p(hdr->AS.Header+40); // not used nItems = leu32p(hdr->AS.Header+48); } else { // oTime = bef64p(hdr->AS.Header+40); // not used nItems = beu32p(hdr->AS.Header+48); } if (VERBOSE_LEVEL>7) fprintf(stdout,"%s (line %i) %s(...): nItems=%i\n",__FILE__,__LINE__,__func__, nItems); if (hdr->VERSION == 1) { Sizes.Rec.Root = 544; Sizes.Rec.Group = 128; Sizes.Rec.Series = 1120; Sizes.Rec.Sweep = 160; Sizes.Rec.Trace = 296; } else if (hdr->VERSION == 2) for (k=0; k < min(12,nItems); k++) { if (VERBOSE_LEVEL>7) fprintf(stdout,"%s (line %i): HEKA nItems=%i\n",__func__,__LINE__, k); uint32_t start = *(uint32_t*)(hdr->AS.Header+k*16+64); uint32_t length = *(uint32_t*)(hdr->AS.Header+k*16+64+4); if (SWAP) { start = bswap_32(start); length = bswap_32(length); } uint8_t *ext = hdr->AS.Header + k*16 + 64 + 8; if (VERBOSE_LEVEL>7) fprintf(stdout,"%s (line %i): HEKA #%i: <%s> [%i:+%i]\n",__func__,__LINE__,k,ext,start,length); if (!start) break; if ((start+8) > count) { biosigERROR(hdr, B4C_INCOMPLETE_FILE, "Heka/Patchmaster: file is corrupted - segment with pulse data is not available!"); return; } if (!memcmp(ext,".pul\0\0\0\0",8)) { // find pulse data ifseek(hdr, start, SEEK_SET); //magic = *(int32_t*)(hdr->AS.Header+start); Levels = *(int32_t*)(hdr->AS.Header+start+4); if (SWAP) Levels = bswap_32(Levels); if (Levels>5) { biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "Heka/Patchmaster format with more than 5 levels not supported"); return; } if (VERBOSE_LEVEL>7) fprintf(stdout,"%s (line %i): HEKA #%i Levels=%i\n",__func__,__LINE__,k,Levels); memcpy(Sizes.all,hdr->AS.Header+start+8,sizeof(int32_t)*Levels); if (SWAP) { int l; for (l=0; l < Levels; l++) Sizes.all[l] = bswap_32(Sizes.all[l]); } if (VERBOSE_LEVEL>7) {int l; for (l=0; l < Levels; l++) fprintf(stdout,"%s (line %i): HEKA #%i %i\n",__func__,__LINE__,l, Sizes.all[l]); } StartOfPulse = start + 8 + 4 * Levels; } else if (!memcmp(ext,".dat\0\0\0\0",8)) { StartOfData = start; } } if (VERBOSE_LEVEL>7) fprintf(stdout,"%s (line %i) %s(...): \n",__FILE__,__LINE__,__func__); // if (!Sizes) free(Sizes); Sizes=NULL; /* DONE: HEKA, check channel number and label pass 1: + get number of sweeps + get number of channels + check whether all traces of a single sweep have the same SPR, and Fs + check whether channelnumber (TrAdcChannel), scaling (DataScaler) and Label fit among all sweeps + extract the total number of samples + physical units + level 4 may have no children + count event descriptions Level2/SeLabel pass 2: + initialize data to NAN + skip sweeps if selected channel is not in it + Y scale, physical scale + Event.CodeDescription, Events, resampling */ uint32_t k1=0, k2=0, k3=0, k4=0; uint32_t K1=0, K2=0, K3=0, K4=0, K5=0; double t; size_t pos; // read K1 if (SWAP) { K1 = bswap_32(*(uint32_t*)(hdr->AS.Header + StartOfPulse + Sizes.Rec.Root)); hdr->VERSION = bswap_32(*(uint32_t*)(hdr->AS.Header + StartOfPulse)); union { double f64; uint64_t u64; } c; c.u64 = bswap_64(*(uint64_t*)(hdr->AS.Header + StartOfPulse + 520)); t = c.f64; } else { K1 = (*(uint32_t*)(hdr->AS.Header + StartOfPulse + Sizes.Rec.Root)); hdr->VERSION = (*(uint32_t*)(hdr->AS.Header + StartOfPulse)); t = (*(double*)(hdr->AS.Header + StartOfPulse + 520)); } if (VERBOSE_LEVEL>7) fprintf(stdout,"%s (line %i) %s(...): \n",__FILE__,__LINE__,__func__); hdr->T0 = heka2gdftime(t); // this is when when heka was started, data is recorded later. hdr->SampleRate = 0.0; double *DT = NULL; // list of sampling intervals per channel hdr->SPR = 0; if (VERBOSE_LEVEL>7) fprintf(stdout,"%s (line %i) %s(...): %p\n",__FILE__,__LINE__,__func__,hdr->EVENT.CodeDesc); /******************************************************************************************************* HEKA: read structural information *******************************************************************************************************/ pos = StartOfPulse + Sizes.Rec.Root + 4; size_t EventN=0; for (k1=0; k1<K1; k1++) { // read group if (VERBOSE_LEVEL>7) fprintf(stdout,"HEKA L1 @%i=\t%i/%i \n",(int)(pos+StartOfData),k1,K1); pos += Sizes.Rec.Group+4; // read number of children K2 = (*(uint32_t*)(hdr->AS.Header+pos-4)); hdr->AS.auxBUF = (uint8_t*)realloc(hdr->AS.auxBUF,K2*33); // used to store name of series for (k2=0; k2<K2; k2++) { // read series union { double f64; uint64_t u64; } Delay; char *SeLabel = (char*)(hdr->AS.Header+pos+4); // max 32 bytes strncpy((char*)hdr->AS.auxBUF + 33*k2, (char*)hdr->AS.Header+pos+4, 32); hdr->AS.auxBUF[33*k2+32] = 0; SeLabel = (char*)hdr->AS.auxBUF + 33*k2; double tt = *(double*)(hdr->AS.Header+pos+136); // time of series. TODO: this time should be taken into account Delay.u64 = bswap_64(*(uint64_t*)(hdr->AS.Header+pos+472+176)); gdf_time t = heka2gdftime(tt); struct tm tm; gdf_time2tm_time_r(t,&tm); if (VERBOSE_LEVEL>7) fprintf(stdout,"HEKA L2 @%i=%s %f\t%i/%i %i/%i t=%.17g %s\n",(int)(pos+StartOfData),SeLabel,Delay.f64,k1,K1,k2,K2,ldexp(t,-32),asctime(&tm)); pos += Sizes.Rec.Series + 4; // read number of children K3 = (*(uint32_t*)(hdr->AS.Header+pos-4)); if (EventN <= hdr->EVENT.N + K3 + 2) { EventN = max(max(16,EventN),hdr->EVENT.N+K3+2) * 2; if (reallocEventTable(hdr, EventN) == SIZE_MAX) { biosigERROR(hdr, B4C_MEMORY_ALLOCATION_FAILED, "Allocating memory for event table failed."); return; }; } if (!hdr->AS.SegSel[0] && !hdr->AS.SegSel[1] && !hdr->AS.SegSel[2]) { // in case of reading the whole file (no sweep selection), include marker for start of series FreeTextEvent(hdr, hdr->EVENT.N, SeLabel); hdr->EVENT.POS[hdr->EVENT.N] = hdr->SPR; // within reading the structure, hdr->SPR is used as a intermediate variable counting the number of samples #if (BIOSIG_VERSION >= 10500) hdr->EVENT.TimeStamp[hdr->EVENT.N] = t; #endif hdr->EVENT.N++; } for (k3=0; k3<K3; k3++) { // read sweep hdr->NRec++; // increase number of sweeps size_t SPR = 0, spr = 0; gdf_time t = heka2gdftime(*(double*)(hdr->AS.Header+pos+48)); // time of sweep. TODO: this should be taken into account gdf_time2tm_time_r(t,&tm); if (VERBOSE_LEVEL>7) fprintf(stdout,"HEKA L3 @%i= %fHz\t%i/%i %i/%i %i/%i %s\n",(int)(pos+StartOfData),hdr->SampleRate,k1,K1,k2,K2,k3,K3,asctime(&tm)); char flagSweepSelected = (hdr->AS.SegSel[0]==0 || k1+1==hdr->AS.SegSel[0]) && (hdr->AS.SegSel[1]==0 || k2+1==hdr->AS.SegSel[1]) && (hdr->AS.SegSel[2]==0 || k3+1==hdr->AS.SegSel[2]); // hdr->SPR if (hdr->SPR==0) hdr->T0 = t; // start time of first recording determines the start time of the recording else if (flagSweepSelected && hdr->SPR > 0) { // marker for start of sweep hdr->EVENT.POS[hdr->EVENT.N] = hdr->SPR; // within reading the structure, hdr->SPR is used as a intermediate variable counting the number of samples hdr->EVENT.TYP[hdr->EVENT.N] = 0x7ffe; #if (BIOSIG_VERSION >= 10500) hdr->EVENT.TimeStamp[hdr->EVENT.N] = t; #endif hdr->EVENT.N++; } pos += Sizes.Rec.Sweep + 4; // read number of children K4 = (*(uint32_t*)(hdr->AS.Header+pos-4)); for (k4=0; k4<K4; k4++) { // read trace double DigMin, DigMax; uint16_t gdftyp = 0; uint32_t ns = (*(uint32_t*)(hdr->AS.Header+pos+36)); uint32_t DataPos = (*(uint32_t*)(hdr->AS.Header+pos+40)); spr = (*(uint32_t*)(hdr->AS.Header+pos+44)); double DataScaler= (*(double*)(hdr->AS.Header+pos+72)); double Toffset = (*(double*)(hdr->AS.Header+pos+80)); // time offset of uint16_t pdc = PhysDimCode((char*)(hdr->AS.Header + pos + 96)); double dT = (*(double*)(hdr->AS.Header+pos+104)); //double XStart = (*(double*)(hdr->AS.Header+pos+112)); uint16_t XUnits = PhysDimCode((char*)(hdr->AS.Header+pos+120)); double YRange = (*(double*)(hdr->AS.Header+pos+128)); double YOffset = (*(double*)(hdr->AS.Header+pos+136)); double Bandwidth = (*(double*)(hdr->AS.Header+pos+144)); //double PipetteResistance = (*(double*)(hdr->AS.Header+pos+152)); double RsValue = (*(double*)(hdr->AS.Header+pos+192)); uint8_t ValidYRange = hdr->AS.Header[pos+220]; uint16_t AdcChan = (*(uint16_t*)(hdr->AS.Header+pos+222)); /* obsolete: range is defined by DigMin/DigMax * DataScaler + YOffset double PhysMin = (*(double*)(hdr->AS.Header+pos+224)); double PhysMax = (*(double*)(hdr->AS.Header+pos+232)); */ if (VERBOSE_LEVEL>7) fprintf(stdout, "%s (line %i): %i %i %i %i %i %g %g 0x%x xUnits=%i %g %g %g %g %i %i\n", __FILE__,__LINE__, k1, k2, k3, k4, ns, DataScaler, Toffset, pdc, XUnits, YRange, YOffset, Bandwidth, RsValue, ValidYRange, AdcChan); switch (hdr->AS.Header[pos+70]) { case 0: gdftyp = 3; //int16 /* It seems that the range is 1.024*(2^15-1)/2^15 nA or V and symetric around zero. i.e. YOffset is zero */ DigMax = ldexp(1.0,15) - 1.0; DigMin = -DigMax; break; case 1: gdftyp = 5; //int32 DigMax = ldexp(1.0, 31) - 1.0; DigMin = -DigMax; break; case 2: gdftyp = 16; //float32 DigMax = 1e9; DigMin = -1e9; break; case 3: gdftyp = 17; //float64 DigMax = 1e9; DigMin = -1e9; break; default: DigMax = NAN; DigMin = NAN; biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "Heka/Patchmaster: data type not supported"); }; if (SWAP) { AdcChan = bswap_16(AdcChan); ns = bswap_32(ns); DataPos = bswap_32(DataPos); spr = bswap_32(spr); // avoid breaking strict-aliasing rules union { double f64; uint64_t u64; } c; c.f64 = dT; c.u64 = bswap_64(c.u64); dT = c.f64; c.f64 = YRange; c.u64 = bswap_64(c.u64); YRange = c.f64; c.f64 = YOffset; c.u64 = bswap_64(c.u64); YOffset = c.f64; //c.f64 = PhysMax; c.u64 = bswap_64(c.u64); PhysMax = c.f64; //c.f64 = PhysMin; c.u64 = bswap_64(c.u64); PhysMin = c.f64; c.f64 = Toffset; c.u64 = bswap_64(c.u64); Toffset = c.f64; } if (YOffset != 0.0) fprintf(stderr,"!!! WARNING !!! HEKA: the offset is not zero - " "this case is not tested and might result in incorrect scaling of " "the data,\n!!! YOU ARE WARNED !!!\n"); // scale to standard units - no prefix double Cal = DataScaler * PhysDimScale(pdc); double Off = YOffset * PhysDimScale(pdc); pdc &= 0xffe0; float Fs = 1.0 / ( dT * PhysDimScale(XUnits) ) ; // float is used to avoid spurios accuracy, round to single precision accuracy if (flagSweepSelected) { if (hdr->SampleRate <= 0.0) hdr->SampleRate = Fs; if (fabs(hdr->SampleRate - Fs) > 1e-9*Fs) { long DIV1 = 1, DIV2 = 1; rational(hdr->SampleRate*dT*PhysDimScale(XUnits), 1e-6, &DIV2, &DIV1); if (DIV1 > 1) { if ( ((size_t)DIV1 * hdr->SPR) > 0xffffffffffffffff) { fprintf(stderr,"!!! WARNING sopen_heka(%s) !!! due to resampling, the data will have more then 2^31 samples !!!\n", hdr->FileName); biosigERROR(hdr,B4C_FORMAT_UNSUPPORTED,"HEKA file has more than 2^32 samples - this is not supported yet"); } hdr->SPR *= DIV1; hdr->SampleRate *= DIV1; hdr->EVENT.SampleRate = hdr->SampleRate; size_t n = 0; while (n < hdr->EVENT.N) hdr->EVENT.POS[n++] *= DIV1; } if (DIV2 > 1) spr *= DIV2; } // samples per sweep if (k4==0) SPR = spr; else if (SPR != spr) { biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "Heka/Patchmaster: number of samples among channels within a single sweep do not match."); return; } } char *Label = (char*)hdr->AS.Header+pos+4; for (ns=0; ns < hdr->NS; ns++) { if (!strcmp(hdr->CHANNEL[ns].Label,Label)) break; } if (VERBOSE_LEVEL>7) fprintf(stdout,"HEKA L4 @%i= #%i,%i, %s %f %fHz\t%i/%i %i/%i %i/%i %i/%i \n",(int)(pos+StartOfData),ns,AdcChan,Label,hdr->SampleRate,Fs,k1,K1,k2,K2,k3,K3,k4,K4); CHANNEL_TYPE *hc; if (ns >= hdr->NS) { hdr->NS = ns + 1; #ifdef WITH_TIMESTAMPCHANNEL // allocate memory for an extra time stamp channel, which is define only after the end of the channel loop - see below hdr->CHANNEL = (CHANNEL_TYPE*) realloc(hdr->CHANNEL, (hdr->NS + 1) * sizeof(CHANNEL_TYPE)); #else hdr->CHANNEL = (CHANNEL_TYPE*) realloc(hdr->CHANNEL, hdr->NS * sizeof(CHANNEL_TYPE)); #endif hc = hdr->CHANNEL + ns; strncpy(hc->Label, Label, max(32, MAX_LENGTH_LABEL)); hc->Label[max(32,MAX_LENGTH_LABEL)] = 0; hc->Transducer[0] = 0; hc->SPR = 1; hc->PhysDimCode = pdc; hc->OnOff = 1; hc->GDFTYP = gdftyp; hc->LeadIdCode = 0; hc->DigMin = DigMin; hc->DigMax = DigMax; // TODO: case of non-zero YOffset is not tested // hc->PhysMax = DigMax * Cal + Off; hc->PhysMin = DigMin * Cal + Off; hc->Cal = Cal; hc->Off = Off; hc->TOffset = Toffset; #ifndef NDEBUG double Cal2 = (hc->PhysMax - hc->PhysMin) / (hc->DigMax - hc->DigMin); double Off2 = hc->PhysMin - Cal2 * hc->DigMin; double Off3 = hc->PhysMax - Cal2 * hc->DigMax; if (VERBOSE_LEVEL>6) fprintf(stdout,"HEKA L5 @%i= #%i,%i, %s %g/%g %g/%g \n",(int)(pos+StartOfData),ns,AdcChan,Label,Cal,Cal2,Off,Off2); assert(Cal==Cal2); assert(Off==Off2); assert(Off==Off3); #endif /* TODO: fix remaining channel header */ /* LowPass, HighPass, Notch, Impedance, */ hc->HighPass = NAN; hc->LowPass = (Bandwidth > 0) ? Bandwidth : NAN; hc->Notch = NAN; hc->Impedance = (RsValue > 0) ? RsValue : NAN; DT = (double*) realloc(DT, hdr->NS*sizeof(double)); DT[ns] = dT; } else { /* channel has been already defined in earlier sweep. check compatibility and adapt internal format when needed */ hc = hdr->CHANNEL + ns; double PhysMax = DigMax * Cal + Off; double PhysMin = DigMin * Cal + Off; // get max value to avoid false positive saturation detection when scaling changes if (hc->PhysMax < PhysMax) hc->PhysMax = PhysMax; if (hc->PhysMin > PhysMin) hc->PhysMin = PhysMin; if (hc->GDFTYP < gdftyp) { /* when data type changes, use the largest data type */ if (4 < hc->GDFTYP && hc->GDFTYP < 9 && gdftyp==16) /* (U)INT32, (U)INT64 + FLOAT32 -> DOUBLE */ hc->GDFTYP = 17; else hc->GDFTYP = gdftyp; } else if (hc->GDFTYP > gdftyp) { /* when data type changes, use the largest data type */ if (4 < gdftyp && gdftyp < 9 && hc->GDFTYP==16) /* (U)INT32, (U)INT64 + FLOAT32 -> DOUBLE */ hc->GDFTYP = 17; } if (fabs(hc->Cal - Cal) > 1e-9*Cal) { /* when scaling changes from sweep to sweep, use floating point numbers internally. */ if (hc->GDFTYP < 5) // int16 or smaller hc->GDFTYP = 16; else if (hc->GDFTYP < 9) // int32, int64 -> double hc->GDFTYP = 17; } if ((pdc & 0xFFE0) != (hc->PhysDimCode & 0xFFE0)) { fprintf(stdout, "ERROR: [%i,%i,%i,%i] Yunits in %s do not match %04x(%s) ! %04x(%s)\n",k1,k2,k3,k4, Label, pdc, PhysDim3(pdc), hc->PhysDimCode, PhysDim3(hc->PhysDimCode)); biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "Heka/Patchmaster: Yunits do not match"); } if ( ( VERBOSE_LEVEL > 7 ) && ( fabs( DT[ns] - dT) > 1e-9 * dT) ) { fprintf(stdout, "%s (line %i) different sampling rates [%i,%i,%i,%i]#%i,%f/%f \n",__FILE__,__LINE__,(int)k1,(int)k2,(int)k3,(int)k4,(int)ns, 1.0/DT[ns],1.0/dT); } } if (YOffset) { biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "Heka/Patchmaster: YOffset is not zero"); } if (hdr->AS.Header[pos+220] != 1) { fprintf(stderr,"WARNING Heka/Patchmaster: ValidYRange not set to 1 but %i in sweep [%i,%i,%i,%i]\n", hdr->AS.Header[pos+220],k1+1,k2+1,k3+1,k4+1); } if (VERBOSE_LEVEL>7) fprintf(stdout,"HEKA L6 @%i= #%i,%i, %s %f-%fHz\t%i/%i %i/%i %i/%i %i/%i \n",(int)(pos+StartOfData),ns,AdcChan,Label,hdr->SampleRate,Fs,k1,K1,k2,K2,k3,K3,k4,K4); pos += Sizes.Rec.Trace+4; // read number of children -- this should be 0 - ALWAYS; K5 = (*(uint32_t*)(hdr->AS.Header+pos-4)); if (K5) { biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "Heka/Patchmaster: Level 4 has some children"); } } // end loop k4 // if sweep is selected, add number of samples to counter if (flagSweepSelected) { if ( hdr->SPR > 0xffffffffffffffffu-SPR) { biosigERROR(hdr,B4C_FORMAT_UNSUPPORTED,"HEKA file has more than 2^32 samples - this is not supported yet"); } hdr->SPR += SPR; } } // end loop k3 } // end loop k2 } // end loop k1 #ifndef NO_BI if (DT) free(DT); #else size_t *BI = (size_t*) DT; // DT is not used anymore, use space for BI #endif DT = NULL; #ifdef WITH_TIMESTAMPCHANNEL { /* define time stamp channel, memory is already allocated above */ CHANNEL_TYPE *hc = hdr->CHANNEL + hdr->NS; hc->GDFTYP = 7; // corresponds to int64_t, gdf_time strcpy(hc->Label,"Timestamp"); hc->Transducer[0]=0; hc->PhysDimCode = 2272; // units: days [d] hc->LeadIdCode = 0; hc->SPR = 1; hc->Cal = ldexp(1.0, -32); hc->Off = 0.0; hc->OnOff = 1; hc->DigMax = ldexp( 1.0, 61); hc->DigMin = 0; hc->PhysMax = hc->DigMax * hc->Cal; hc->PhysMin = hc->DigMin * hc->Cal; hc->TOffset = 0.0; hc->Impedance = NAN; hc->HighPass = NAN; hc->LowPass = NAN; hc->Notch = NAN; hc->XYZ[0] = 0.0; hc->XYZ[1] = 0.0; hc->XYZ[2] = 0.0; hdr->NS++; } #endif hdr->NRec = 1; hdr->AS.bpb = 0; for (k = 0; k < hdr->NS; k++) { CHANNEL_TYPE *hc = hdr->CHANNEL + k; hc->Cal = (hc->PhysMax - hc->PhysMin) / (hc->DigMax - hc->DigMin); hc->Off = hc->PhysMin - hc->DigMin * hc->Cal; #ifndef NO_BI hc->bi = hdr->AS.bpb; #else BI[k] = hdr->AS.bpb; #endif hc->SPR = hdr->SPR; hdr->AS.bpb += hc->SPR * (GDFTYP_BITS[hc->GDFTYP]>>3); // multiplation must not exceed 32 bit limit } if (hdr->AS.B4C_ERRNUM) { #ifdef NO_BI if (BI) free(BI); #endif return; } hdr->ID.Manufacturer.Name = "HEKA/Patchmaster"; /****************************************************************************** SREAD_HEKA void sread_heka(HDRTYPE* hdr, FILE *itx, ... ) { ******************************************************************************/ if (VERBOSE_LEVEL > 7) fprintf(stdout,"HEKA: 400: %"PRIi64" %"PRIi32" %"PRIi64"\n",hdr->NRec, hdr->AS.bpb, hdr->NRec * (size_t)hdr->AS.bpb); size_t sz = hdr->NRec * (size_t)hdr->AS.bpb; if (sz/hdr->NRec < hdr->AS.bpb) { biosigERROR(hdr, B4C_MEMORY_ALLOCATION_FAILED, "memory allocation failed - more than 2GB required but platform supports only 32 bit!"); return; } void* tmpptr = realloc(hdr->AS.rawdata, sz); if (tmpptr!=NULL) hdr->AS.rawdata = (uint8_t*) tmpptr; else { biosigERROR(hdr, B4C_MEMORY_ALLOCATION_FAILED, "memory allocation failed - not enough memory!"); return; } assert(hdr->NRec >= 0); memset(hdr->AS.rawdata, 0xff, hdr->NRec * (size_t)hdr->AS.bpb); // initialize with NAN's #ifdef NO_BI #define _BI (BI[k]) #else #define _BI (hc->bi) #endif /* initialize with NAN's */ for (k=0; k<hdr->NS; k++) { size_t k1; CHANNEL_TYPE *hc = hdr->CHANNEL+k; switch (hc->GDFTYP) { case 3: for (k1=0; k1<hc->SPR; k1++) { *(uint16_t*)(hdr->AS.rawdata + _BI + k1 * 2) = 0x8000; } break; case 5: for (k1=0; k1<hc->SPR; k1++) *(uint32_t*)(hdr->AS.rawdata + _BI + k1 * 4) = 0x80000000; break; case 7: for (k1=0; k1<hc->SPR; k1++) *(int64_t*)(hdr->AS.rawdata + _BI + k1 * 4) = 0x8000000000000000LL; break; case 16: for (k1=0; k1<hc->SPR; k1++) *(float*)(hdr->AS.rawdata + _BI + k1 * 4) = NAN; break; case 17: for (k1=0; k1<hc->SPR; k1++) *(double*)(hdr->AS.rawdata + _BI + k1 * 8) = NAN; break; } } #undef _BI char *WAVENAME = NULL; if (itx) { fprintf(itx, "IGOR\r\nX Silent 1\r\n"); const char *fn = strrchr(hdr->FileName,'\\'); if (fn) fn++; else fn = strrchr(hdr->FileName,'/'); if (fn) fn++; else fn = hdr->FileName; size_t len = strspn(fn,"."); WAVENAME = (char*)malloc(strlen(hdr->FileName)+7); if (len) strncpy(WAVENAME, fn, len); else strcpy(WAVENAME, fn); // Flawfinder: ignore } if (VERBOSE_LEVEL>7) hdr2ascii(hdr,stdout,4); /******************************************************************************************************* HEKA: read data blocks *******************************************************************************************************/ uint32_t SPR = 0; pos = StartOfPulse + Sizes.Rec.Root + 4; for (k1=0; k1<K1; k1++) { // read group if (VERBOSE_LEVEL>7) fprintf(stdout,"HEKA+L1 @%i=\t%i/%i \n",(int)(pos+StartOfData),k1,K1); pos += Sizes.Rec.Group+4; // read number of children K2 = (*(uint32_t*)(hdr->AS.Header+pos-4)); for (k2=0; k2<K2; k2++) { // read series union { double f64; uint64_t u64; } Delay; uint32_t spr = 0; char *SeLabel = (char*)(hdr->AS.Header+pos+4); // max 32 bytes Delay.u64 = bswap_64(*(uint64_t*)(hdr->AS.Header+pos+472+176)); if (VERBOSE_LEVEL>7) fprintf(stdout,"HEKA+L2 @%i=%s %f\t%i/%i %i/%i \n",(int)(pos+StartOfData),SeLabel,Delay.f64,k1,K1,k2,K2); /* move to reading of data */ pos += Sizes.Rec.Series+4; // read number of children K3 = (*(uint32_t*)(hdr->AS.Header+pos-4)); for (k3=0; k3<K3; k3++) { #if defined(WITH_TIMESTAMPCHANNEL) #ifdef NO_BI #define _BI (BI[hdr->NS-1]) #else #define _BI (hdr->CHANNEL[hdr->NS-1].bi) #endif gdf_time t = heka2gdftime(*(double*)(hdr->AS.Header+pos+48)); // time of sweep. TODO: this should be taken into account *(int64_t*)(hdr->AS.rawdata + _BI + SPR * 8) = t; #undef _BI #endif // WITH_TIMESTAMPCHANNEL // read sweep char flagSweepSelected = (hdr->AS.SegSel[0]==0 || k1+1==hdr->AS.SegSel[0]) && (hdr->AS.SegSel[1]==0 || k2+1==hdr->AS.SegSel[1]) && (hdr->AS.SegSel[2]==0 || k3+1==hdr->AS.SegSel[2]); if (VERBOSE_LEVEL>7) fprintf(stdout,"HEKA+L3 @%i=\t%i/%i %i/%i %i/%i sel=%i\n",(int)(pos+StartOfData),k1,K1,k2,K2,k3,K3,flagSweepSelected); pos += Sizes.Rec.Sweep + 4; // read number of children K4 = (*(uint32_t*)(hdr->AS.Header+pos-4)); size_t DIV=1; for (k4=0; k4<K4; k4++) { if (!flagSweepSelected) { pos += Sizes.Rec.Trace+4; continue; } // read trace uint16_t gdftyp = 0; uint32_t ns = (*(uint32_t*)(hdr->AS.Header+pos+36)); uint32_t DataPos = (*(uint32_t*)(hdr->AS.Header+pos+40)); spr = (*(uint32_t*)(hdr->AS.Header+pos+44)); double DataScaler= (*(double*)(hdr->AS.Header+pos+72)); double Toffset = (*(double*)(hdr->AS.Header+pos+80)); // time offset of uint16_t pdc = PhysDimCode((char*)(hdr->AS.Header + pos + 96)); char *physdim = (char*)(hdr->AS.Header + pos + 96); double dT = (*(double*)(hdr->AS.Header+pos+104)); // double XStart = (*(double*)(hdr->AS.Header+pos+112)); // uint16_t XUnits = PhysDimCode((char*)(hdr->AS.Header+pos+120)); double YRange = (*(double*)(hdr->AS.Header+pos+128)); double YOffset = (*(double*)(hdr->AS.Header+pos+136)); // double Bandwidth = (*(double*)(hdr->AS.Header+pos+144)); uint16_t AdcChan = (*(uint16_t*)(hdr->AS.Header+pos+222)); /* double PhysMin = (*(double*)(hdr->AS.Header+pos+224)); double PhysMax = (*(double*)(hdr->AS.Header+pos+232)); */ switch (hdr->AS.Header[pos+70]) { case 0: gdftyp = 3; break; // int16 case 1: gdftyp = 5; break; // int32 case 2: gdftyp = 16; break; // float32 case 3: gdftyp = 17; break; // float64 default: biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "Heka/Patchmaster unknown data type is used"); }; if (SWAP) { AdcChan = bswap_16(AdcChan); ns = bswap_32(ns); DataPos = bswap_32(DataPos); spr = bswap_32(spr); // avoid breaking strict-aliasing rules union { double f64; uint64_t u64; } c; c.f64 = dT; c.u64 = bswap_64(c.u64); dT = c.f64; c.f64 = YRange; c.u64 = bswap_64(c.u64); YRange = c.f64; c.f64 = YOffset; c.u64 = bswap_64(c.u64); YOffset = c.f64; /* c.f64 = PhysMax; c.u64 = bswap_64(c.u64); PhysMax = c.f64; c.f64 = PhysMin; c.u64 = bswap_64(c.u64); PhysMin = c.f64; */ c.f64 = Toffset; c.u64 = bswap_64(c.u64); Toffset = c.f64; } double Fs = round(1.0 / dT); DIV = round(hdr->SampleRate / Fs); char *Label = (char*)(hdr->AS.Header+pos+4); for (ns=0; ns < hdr->NS; ns++) { if (!strcmp(hdr->CHANNEL[ns].Label, Label)) break; } CHANNEL_TYPE *hc = hdr->CHANNEL+ns; if (VERBOSE_LEVEL>7) fprintf(stdout,"HEKA+L4 @%i= #%i,%i,%i/%i %s\t%i/%i %i/%i %i/%i %i/%i DIV=%i,%i,%i\n",(int)(pos+StartOfData),ns,AdcChan,spr,SPR,Label,k1,K1,k2,K2,k3,K3,k4,K4,(int)DIV,gdftyp,hc->GDFTYP); if (itx) { uint32_t k5; double Cal = DataScaler; assert(hdr->CHANNEL[ns].Off==0.0); double Off = 0.0; fprintf(itx, "\r\nWAVES %s_%i_%i_%i_%i\r\nBEGIN\r\n", WAVENAME,k1+1,k2+1,k3+1,k4+1); switch (hc->GDFTYP) { case 3: for (k5 = 0; k5 < spr; ++k5) fprintf(itx,"% e\n", (double)*(int16_t*)(hdr->AS.Header + DataPos + k5 * 2) * Cal + Off); break; case 5: for (k5 = 0; k5 < spr; ++k5) fprintf(itx,"% e\n", (double)*(int32_t*)(hdr->AS.Header + DataPos + k5 * 4) * Cal + Off); break; case 16: for (k5 = 0; k5 < spr; ++k5) fprintf(itx,"% e\n", (double)*(float*)(hdr->AS.Header + DataPos + k5 * 4) * Cal + Off); break; case 17: for (k5 = 0; k5 < spr; ++k5) fprintf(itx,"% e\n", *(double*)(hdr->AS.Header + DataPos + k5 * 8) * Cal + Off); break; } fprintf(itx, "END\r\nX SetScale/P x, %g, %g, \"s\", %s_%i_%i_%i_%i\r\n", Toffset, dT, WAVENAME, k1+1,k2+1,k3+1,k4+1); fprintf(itx, "X SetScale y,0,0,\"%s\", %s_%i_%i_%i_%i\n", physdim, WAVENAME, k1+1,k2+1,k3+1,k4+1); } #ifdef NO_BI #define _BI (BI[ns]) #else #define _BI (hc->bi) #endif // no need to check byte order because File.Endian is set and endian conversion is done in sread if ((DIV==1) && (gdftyp == hc->GDFTYP)) { uint16_t sz = GDFTYP_BITS[hc->GDFTYP]>>3; memcpy(hdr->AS.rawdata + _BI + SPR * sz, hdr->AS.Header + DataPos, spr * sz); } else if (1) { double Cal = DataScaler * PhysDimScale(pdc) / hdr->CHANNEL[ns].Cal; assert(Cal==1.0 || hc->GDFTYP > 15); // when scaling changes, target data type is always float/double -> see above uint32_t k5,k6; switch (gdftyp) { case 3: switch (hc->GDFTYP) { case 3: for (k5 = 0; k5 < spr; ++k5) { int16_t ival = *(int16_t*)(hdr->AS.Header + DataPos + k5 * 2); for (k6 = 0; k6 < DIV; ++k6) *(int16_t*)(hdr->AS.rawdata + _BI + (SPR + k5*DIV + k6) * 2) = ival; } break; case 5: for (k5 = 0; k5 < spr; ++k5) { int16_t ival = *(int16_t*)(hdr->AS.Header + DataPos + k5 * 2); for (k6 = 0; k6 < DIV; ++k6) *(int32_t*)(hdr->AS.rawdata + _BI + (SPR + k5*DIV + k6) * 4) = (int32_t)ival; } break; case 16: for (k5 = 0; k5 < spr; ++k5) { int16_t ival = *(int16_t*)(hdr->AS.Header + DataPos + k5 * 2); for (k6 = 0; k6 < DIV; ++k6) *(float*)(hdr->AS.rawdata + _BI + (SPR + k5*DIV + k6) * 4) = (float)ival * Cal; } break; case 17: for (k5 = 0; k5 < spr; ++k5) { int16_t ival = *(int16_t*)(hdr->AS.Header + DataPos + k5 * 2); for (k6 = 0; k6 < DIV; ++k6) *(double*)(hdr->AS.rawdata + _BI + (SPR + k5*DIV + k6) * 8) = (double)ival * Cal; } break; } break; case 5: switch (hc->GDFTYP) { case 5: for (k5 = 0; k5 < spr; ++k5) { int32_t ival = *(int32_t*)(hdr->AS.Header + DataPos + k5 * 4); for (k6 = 0; k6 < DIV; ++k6) *(int32_t*)(hdr->AS.rawdata + _BI + (SPR + k5*DIV + k6) * 4) = ival; } break; case 16: for (k5 = 0; k5 < spr; ++k5) { int32_t ival = *(int32_t*)(hdr->AS.Header + DataPos + k5 * 4); for (k6 = 0; k6 < DIV; ++k6) *(float*)(hdr->AS.rawdata + _BI + (SPR + k5*DIV + k6) * 4) = (float)ival * Cal; } break; case 17: for (k5 = 0; k5 < spr; ++k5) { int32_t ival = *(int32_t*)(hdr->AS.Header + DataPos + k5 * 4); for (k6 = 0; k6 < DIV; ++k6) *(double*)(hdr->AS.rawdata + _BI + (SPR + k5*DIV + k6) * 8) = (double)ival * Cal; } break; } break; case 16: switch (hc->GDFTYP) { case 16: for (k5 = 0; k5 < spr; ++k5) { float ival = *(float*)(hdr->AS.Header + DataPos + k5 * 4); for (k6 = 0; k6 < DIV; ++k6) *(float*)(hdr->AS.rawdata + _BI + (SPR + k5*DIV + k6) * 4) = ival * Cal; } break; case 17: for (k5 = 0; k5 < spr; ++k5) { float ival = *(float*)(hdr->AS.Header + DataPos + k5 * 4); for (k6 = 0; k6 < DIV; ++k6) *(double*)(hdr->AS.rawdata + _BI + (SPR + k5*DIV + k6) * 8) = (double)ival * Cal; } break; } break; case 17: switch (hc->GDFTYP) { case 17: for (k5 = 0; k5 < spr; ++k5) { double ival = *(double*)(hdr->AS.Header + DataPos + k5 * 8); for (k6 = 0; k6 < DIV; ++k6) *(double*)(hdr->AS.rawdata + _BI + (SPR + k5*DIV + k6) * 8) = ival * Cal; } break; } break; } } #undef _BI pos += Sizes.Rec.Trace+4; } if (flagSweepSelected) SPR += spr * DIV; } }