void wells_data_print(FILE *fp, wells_header_t *header, wells_data_t *data, int32_t nonzero) { int32_t i, output; output = 1; if(1 == nonzero) { output = 0; for(i=0;i<header->num_flows;i++) { if(0 < data->flow_values[i]) { output = 1; break; } } } if(1 == output) { if(fprintf(fp, "%d,%d,%d", data->rank, data->x, data->y) < 0) { ion_error(__func__, "fprintf", Exit, WriteFileError); } for(i=0;i<header->num_flows;i++) { if(fprintf(fp, ",%f", data->flow_values[i]) < 0) { ion_error(__func__, "fprintf", Exit, WriteFileError); } } if(fprintf(fp, "\n") < 0) { ion_error(__func__, "fprintf", Exit, WriteFileError); } } }
uint32_t sff_read_header_write(FILE *fp, sff_read_header_t *rh) { uint32_t n = 0; sff_read_header_calc_bytes(rh); // convert values to big-endian sff_read_header_hton(rh); if(1 != fwrite(&rh->rheader_length, sizeof(uint16_t), 1, fp) || 1 != fwrite(&rh->name_length, sizeof(uint16_t), 1, fp) || 1 != fwrite(&rh->n_bases, sizeof(uint32_t), 1, fp) || 1 != fwrite(&rh->clip_qual_left, sizeof(uint16_t), 1, fp) || 1 != fwrite(&rh->clip_qual_right, sizeof(uint16_t), 1, fp) || 1 != fwrite(&rh->clip_adapter_left, sizeof(uint16_t), 1, fp) || 1 != fwrite(&rh->clip_adapter_right, sizeof(uint16_t), 1, fp)) { ion_error(__func__, "fwrite", Exit, WriteFileError); } n += sizeof(uint32_t) + 6*sizeof(uint16_t); // convert values from big-endian sff_read_header_ntoh(rh); if(rh->name_length != fwrite(rh->name->s, sizeof(char), rh->name_length, fp)) { ion_error(__func__, "fwrite", Exit, ReadFileError); } n += sizeof(char)*rh->name_length; n += ion_write_padding(fp, n); return n; }
void sff_sort(sff_file_t *fp_in, sff_file_t *fp_out) { int32_t i, row, col; sff_t *sff; int32_t requires_sort = 0; sff_sort_t *sffs = NULL; int32_t sffs_mem = 0, sffs_len = 0; // initialize memory sffs_mem = 1024; sffs = ion_malloc(sizeof(sff_sort_t) * sffs_mem, __func__, "sffs"); // go through the input file while(NULL != (sff = sff_read(fp_in))) { // get the row/col co-ordinates if(0 == ion_readname_to_rowcol(sff->rheader->name->s, &row, &col)) { ion_error(__func__, "could not understand the read name", Exit, OutOfRange); } // copy over while(sffs_mem <= sffs_len) { sffs_mem <<= 1; // double sffs = ion_realloc(sffs, sizeof(sff_sort_t) * sffs_mem, __func__, "sffs"); } sffs[sffs_len].row = row; sffs[sffs_len].col = col; sffs[sffs_len].sff = sff; sff = NULL; // check if we need to sort, for later if(0 < sffs_len && __sff_sort_lt(sffs[sffs_len], sffs[sffs_len-1])) { requires_sort = 1; } sffs_len++; } // resize sffs_mem = sffs_len; sffs = ion_realloc(sffs, sizeof(sff_sort_t) * sffs_mem, __func__, "sffs"); if(1 == requires_sort) { // sort ion_sort_introsort(sff_sort, sffs_len, sffs); } // write for(i=0;i<sffs_len;i++) { if(0 == sff_write(fp_out, sffs[i].sff)) { ion_error(__func__, "sff_write", Exit, WriteFileError); } } // destroy for(i=0;i<sffs_len;i++) { sff_destroy(sffs[i].sff); } free(sffs); }
uint32_t sff_index_write(FILE *fp, sff_index_t *idx) { int32_t i; uint32_t n = 0; uint64_t len = 0; if(NULL == idx) { return 0; } // convert values to big-endian sff_index_hton(idx); // index header if(1 != fwrite(&idx->index_magic_number, sizeof(uint32_t), 1, fp) || 1 != fwrite(&idx->index_version, sizeof(uint32_t), 1, fp) || 1 != fwrite(&idx->num_rows, sizeof(int32_t), 1, fp) || 1 != fwrite(&idx->num_cols, sizeof(int32_t), 1, fp) || 1 != fwrite(&idx->type, sizeof(int32_t), 1, fp)) { ion_error(__func__, "fwrite", Exit, WriteFileError); } n += sizeof(uint32_t)*2 + sizeof(int32_t)*3; // convert values from big-endian sff_index_ntoh(idx); // offsets if(SFF_INDEX_ROW_ONLY == idx->type) { len = 1 + idx->num_rows; } else if(SFF_INDEX_ALL == idx->type) { len = 1 + (idx->num_rows * idx->num_cols); } else { ion_error(__func__, "could not understand index type", Exit, OutOfRange); } // convert values to big-endian for(i=0;i<len;i++) { idx->offset[i] = htonll(idx->offset[i]); } // write if(len != fwrite(idx->offset, sizeof(uint64_t), len, fp)) { ion_error(__func__, "fwrite", Exit, WriteFileError); } n += sizeof(uint64_t) * len; // convert values from big-endian for(i=0;i<len;i++) { idx->offset[i] = ntohll(idx->offset[i]); } // padding n += ion_write_padding(fp, n); return n; }
int wells_mask_view_main(int argc, char *argv[]) { FILE *fp_in; int32_t i; int c; int32_t min_row, max_row, min_col, max_col; wells_mask_t *mask = NULL; min_row = max_row = min_col = max_col = -1; while((c = getopt(argc, argv, "r:c:h")) >= 0) { switch(c) { case 'r': if(ion_parse_range(optarg, &min_row, &max_row) < 0) { ion_error(__func__, "-r : format not recognized", Exit, OutOfRange); } break; case 'c': if(ion_parse_range(optarg, &min_col, &max_col) < 0) { ion_error(__func__, "-c : format not recognized", Exit, OutOfRange); } break; case 'h': default: return usage(); } } if(argc == optind) { return usage(); } else { for(i=optind;i<argc;i++) { if(!(fp_in = fopen(argv[i], "rb"))) { fprintf(stderr, "** Could not open %s for reading. **\n", argv[i]); ion_error(__func__, argv[i], Exit, OpenFileError); } if(NULL == (mask = wells_mask_read(fp_in))) { ion_error(__func__, argv[i], Exit, ReadFileError); } fclose(fp_in); fp_in = NULL; wells_mask_print(stdout, mask); wells_mask_destroy(mask); } } return 0; }
sff_index_t * sff_index_read(FILE *fp) { int32_t i; uint32_t n = 0; uint64_t len = 0; sff_index_t *idx; idx = sff_index_init(); // index header if(1 != fread(&idx->index_magic_number, sizeof(uint32_t), 1, fp) || 1 != fread(&idx->index_version, sizeof(uint32_t), 1, fp) || 1 != fread(&idx->num_rows, sizeof(int32_t), 1, fp) || 1 != fread(&idx->num_cols, sizeof(int32_t), 1, fp) || 1 != fread(&idx->type, sizeof(int32_t), 1, fp)) { ion_error(__func__, "fread", Exit, WriteFileError); } n += sizeof(uint32_t)*2 + sizeof(int32_t)*3; // convert values from big-endian sff_index_ntoh(idx); // offsets if(SFF_INDEX_ROW_ONLY == idx->type) { len = 1 + idx->num_rows; } else if(SFF_INDEX_ALL == idx->type) { len = 1 + (idx->num_rows * idx->num_cols); } else { ion_error(__func__, "could not understand index type", Exit, OutOfRange); } // alloc idx->offset = ion_malloc(sizeof(uint64_t) * len, __func__, "idx->offset"); // read if(len != fread(idx->offset, sizeof(uint64_t), len, fp)) { ion_error(__func__, "fread", Exit, WriteFileError); } // convert values from big-endian for(i=0;i<len;i++) { idx->offset[i] = ntohll(idx->offset[i]); } n += sizeof(uint64_t) * len; // padding n += ion_read_padding(fp, n); return idx; }
void wells_mask_write(FILE *fp, wells_mask_t *mask) { int32_t i; if(fwrite(&mask->num_rows, sizeof(int32_t), 1, fp) != 1 || fwrite(&mask->num_cols, sizeof(int32_t), 1, fp) != 1) { ion_error(__func__, "fwrite", Exit, WriteFileError); } for(i=0;i<mask->num_rows;i++) { if(fwrite(mask->masks[i], sizeof(uint16_t), mask->num_cols, fp) != mask->num_cols) { ion_error(__func__, "fwrite", Exit, WriteFileError); } } }
uint32_t sff_read_write(FILE *fp, sff_header_t *gh, sff_read_header_t *rh, sff_read_t *r) { uint32_t i, n = 0; // convert flowgram to network order for(i=0;i<gh->flow_length;i++) { r->flowgram[i] = htons(r->flowgram[i]); } if(gh->flow_length != fwrite(r->flowgram, sizeof(uint16_t), gh->flow_length, fp) || rh->n_bases != fwrite(r->flow_index, sizeof(uint8_t), rh->n_bases, fp) || rh->n_bases != fwrite(r->bases->s, sizeof(char), rh->n_bases, fp) || rh->n_bases != fwrite(r->quality->s, sizeof(char), rh->n_bases, fp)) { ion_error(__func__, "fread", Exit, ReadFileError); } n += sizeof(uint16_t)*gh->flow_length + 3*sizeof(uint8_t)*rh->n_bases; // convert flowgram to host order for(i=0;i<gh->flow_length;i++) { r->flowgram[i] = ntohs(r->flowgram[i]); } n += ion_write_padding(fp, n); return n; }
int dat_frame_write(FILE *fp, dat_frame_t *cur, dat_frame_t *prev, dat_header_t *header) { int32_t i; uint32_t compressed=0; // first frame or uninterlaced if(NULL == prev || DAT_HEADER_UNINTERLACED == header->interlace_type) { // timestamp and comprssion compressed = 0; if(fwrite_big_endian_uint32_t(fp, &cur->timestamp) != 1 || fwrite_big_endian_uint32_t(fp, &compressed) != 1) { return EOF; } // manually convert to big-endian for(i=0;i<header->rows*header->cols;i++) { cur->data[i] = htons(cur->data[i]); } // write the data if(fwrite(cur->data, sizeof(uint16_t), header->rows*header->cols, fp) != header->rows*header->cols) { // image data return EOF; } // manually convert from big-endian for(i=0;i<header->rows*header->cols;i++) { cur->data[i] = ntohs(cur->data[i]); } } else { // Currently not supported // TODO ion_error(__func__, "Writing interlaced DAT files currently not supported", Warn, OutOfRange); return EOF; } return 1; }
uint32_t sff_index_length(sff_index_t *idx) { uint32_t n = 0; uint64_t len = 0; // index header n += sizeof(uint32_t)*2 + sizeof(int32_t)*3; // offsets if(SFF_INDEX_ROW_ONLY == idx->type) { len = 1 + idx->num_rows; } else if(SFF_INDEX_ALL == idx->type) { len = 1 + (idx->num_rows * idx->num_cols); } else { ion_error(__func__, "could not understand index type", Exit, OutOfRange); } n += sizeof(uint64_t) * len; // padding n += ion_write_padding(NULL, n); return n; }
sff_read_header_t * sff_read_header_read(FILE *fp) { sff_read_header_t *rh = NULL; uint32_t n = 0; rh = sff_read_header_init(); if(1 != fread(&rh->rheader_length, sizeof(uint16_t), 1, fp) || 1 != fread(&rh->name_length, sizeof(uint16_t), 1, fp) || 1 != fread(&rh->n_bases, sizeof(uint32_t), 1, fp) || 1 != fread(&rh->clip_qual_left, sizeof(uint16_t), 1, fp) || 1 != fread(&rh->clip_qual_right, sizeof(uint16_t), 1, fp) || 1 != fread(&rh->clip_adapter_left, sizeof(uint16_t), 1, fp) || 1 != fread(&rh->clip_adapter_right, sizeof(uint16_t), 1, fp)) { free(rh); return NULL; } n += sizeof(uint32_t) + 6*sizeof(uint16_t); // convert values from big-endian sff_read_header_ntoh(rh); rh->name = ion_string_init(rh->name_length+1); if(rh->name_length != fread(rh->name->s, sizeof(char), rh->name_length, fp)) { // truncated file, error ion_error(__func__, "fread", Exit, ReadFileError); } n += sizeof(char)*rh->name_length; // set read name length and null-terminator rh->name->l = rh->name_length; rh->name->s[rh->name->l]='\0'; n += ion_read_padding(fp, n); #ifdef ION_SFF_DEBUG sff_read_header_print(stderr, rh); #endif if(rh->rheader_length != n) { ion_error(__func__, "SFF read header length did not match", Exit, ReadFileError); } return rh; }
dat_header_t * dat_header_read(FILE *fp) { dat_header_t *h=NULL; h = ion_malloc(sizeof(dat_header_t), __func__, "h"); if(fread_big_endian_uint32_t(fp, &h->signature) != 1 || fread_big_endian_uint32_t(fp, &h->version) != 1 || fread_big_endian_uint32_t(fp, &h->header_size) != 1 || fread_big_endian_uint32_t(fp, &h->data_size) != 1 || fread_big_endian_uint32_t(fp, &h->wall_time) != 1 || fread_big_endian_uint16_t(fp, &h->rows) != 1 || fread_big_endian_uint16_t(fp, &h->cols) != 1 || fread_big_endian_uint16_t(fp, &h->channels) != 1 || fread_big_endian_uint16_t(fp, &h->interlace_type) != 1 || fread_big_endian_uint16_t(fp, &h->frames_in_file) != 1 || fread_big_endian_uint16_t(fp, &h->reserved) != 1 || fread_big_endian_uint32_t(fp, &h->sample_rate) != 1 || fread_big_endian_uint16_t(fp, &h->full_scale_voltage[0]) != 1 || fread_big_endian_uint16_t(fp, &h->full_scale_voltage[1]) != 1 || fread_big_endian_uint16_t(fp, &h->full_scale_voltage[2]) != 1 || fread_big_endian_uint16_t(fp, &h->full_scale_voltage[3]) != 1 || fread_big_endian_uint16_t(fp, &h->channel_offsets[0]) != 1 || fread_big_endian_uint16_t(fp, &h->channel_offsets[1]) != 1 || fread_big_endian_uint16_t(fp, &h->channel_offsets[2]) != 1 || fread_big_endian_uint16_t(fp, &h->channel_offsets[3]) != 1 || fread_big_endian_uint16_t(fp, &h->ref_electrode_offset) != 1 || fread_big_endian_uint16_t(fp, &h->frame_interval) != 1) { free(h); return NULL; } if(3 != h->version) { // from Image.cpp ion_error(__func__, "h->version", Exit, OutOfRange); } // Check signature if(h->signature != DAT_HEADER_SIGNATURE) { ion_error(__func__, "h->signature", Exit, OutOfRange); } return h; }
void wells_header_print(FILE *fp, wells_header_t *h) { if(fprintf(fp, "@HD,num_wells=%d,num_flows=%d,flow_order=%s\n", h->num_wells, h->num_flows, h->flow_order) < 0) { ion_error(__func__, "fprintf", Exit, WriteFileError); } }
void wells_mask_print(FILE *fp, wells_mask_t *mask) { int32_t i, j, ctr; for(i=ctr=0;i<mask->num_rows;i++) { // row-major for(j=0;j<mask->num_cols;j++,ctr++) { if(0 < i && j < 0) { if(EOF == fputc(',', fp)) { ion_error(__func__, "fputc", Exit, WriteFileError); } } // TODO: speed up fprintf if(fprintf(fp, "%d", mask->masks[i][j]) < 0) { ion_error(__func__, "fprintf", Exit, WriteFileError); } } if(EOF == fputc('\n', fp)) { ion_error(__func__, "fputc", Exit, WriteFileError); } } }
void sff_read_print(FILE *fp, sff_read_t *r, sff_header_t *gh, sff_read_header_t *rh) { uint32_t i; // flowgram for(i=0;i<gh->flow_length;i++) { if(0 < i) { if(-1L == fputc(',', fp)) { ion_error(__func__, "fputc", Exit, WriteFileError); } } if(fprintf(fp, "%u", r->flowgram[i]) < 0) { ion_error(__func__, "fprintf", Exit, WriteFileError); } } if(-1L == fputc('\n', fp)) { ion_error(__func__, "fputc", Exit, WriteFileError); } // flow index for(i=0;i<rh->n_bases;i++) { if(0 < i) { if(-1L == fputc(',', fp)) { ion_error(__func__, "fputc", Exit, WriteFileError); } } if(fprintf(fp, "%u", r->flow_index[i]) < 0) { ion_error(__func__, "fprintf", Exit, WriteFileError); } } if(-1L == fputc('\n', fp)) { ion_error(__func__, "fputc", Exit, WriteFileError); } // bases if(fprintf(fp, "%s\n", r->bases->s) < 0) { ion_error(__func__, "fprintf", Exit, WriteFileError); } // quality for(i=0;i<r->quality->l;i++) { if(EOF == fputc(QUAL2CHAR(r->quality->s[i]), fp)) { ion_error(__func__, "fputc", Exit, WriteFileError); } } fputc('\n', fp); }
sff_read_t * sff_read_read(FILE *fp, sff_header_t *gh, sff_read_header_t *rh) { sff_read_t *r = NULL; uint32_t i, n = 0; r = sff_read_init(); r->flowgram = ion_malloc(sizeof(uint16_t)*gh->flow_length, __func__, "r->flowgram"); r->flow_index = ion_malloc(sizeof(uint8_t)*rh->n_bases, __func__, "r->flow_index"); r->bases = ion_string_init(rh->n_bases+1); r->quality = ion_string_init(rh->n_bases+1); if(gh->flow_length != fread(r->flowgram, sizeof(uint16_t), gh->flow_length, fp) || rh->n_bases != fread(r->flow_index, sizeof(uint8_t), rh->n_bases, fp) || rh->n_bases != fread(r->bases->s, sizeof(char), rh->n_bases, fp) || rh->n_bases != fread(r->quality->s, sizeof(char), rh->n_bases, fp)) { // truncated file, error ion_error(__func__, "fread", Exit, ReadFileError); } n += sizeof(uint16_t)*gh->flow_length + 3*sizeof(uint8_t)*rh->n_bases; // set length and null-terminators r->bases->l = rh->n_bases; r->quality->l = rh->n_bases; r->bases->s[r->bases->l]='\0'; r->quality->s[r->quality->l]='\0'; // convert flowgram to host order for(i=0;i<gh->flow_length;i++) { r->flowgram[i] = ntohs(r->flowgram[i]); } n += ion_read_padding(fp, n); #ifdef ION_SFF_DEBUG sff_read_print(stderr, r, gh, rh); #endif return r; }
int sff_index_create_main(int argc, char *argv[]) { int c; sff_file_t *fp_in, *fp_out; int32_t num_rows, num_cols, type; sff_header_t *fp_out_header; sff_index_t* index; sff_t *sff; num_rows = num_cols = -1; type = SFF_INDEX_ALL; while((c = getopt(argc, argv, "r:c:C:Rh")) >= 0) { switch(c) { case 'r': num_rows = atoi(optarg); break; case 'c': num_cols = atoi(optarg); break; case 'C': switch(atoi(optarg)) { case 0: num_rows = 1152; num_cols = 1280; break; case 1: num_rows = 2640; num_cols = 2736; break; case 2: num_rows = 3792; num_cols = 3392; break; default: break; } case 'R': type = SFF_INDEX_ROW_ONLY; break; case 'h': default: return usage(); } } if(argc != 1+optind) { return usage(); } else { // check cmd line args if(num_rows < 0) { ion_error(__func__, "-r must be specified and greater than zero", Exit, CommandLineArgument); } if(num_cols < 0) { ion_error(__func__, "-c must be specified and greater than zero", Exit, CommandLineArgument); } switch(type) { case SFF_INDEX_ROW_ONLY: case SFF_INDEX_ALL: break; default: ion_error(__func__, "bug encountered", Exit, OutOfRange); break; } fp_in = sff_fopen(argv[optind], "rb", NULL, NULL); fp_out_header = sff_header_clone(fp_in->header); index = sff_index_create(fp_in, fp_out_header, num_rows, num_cols, type); fp_out = sff_fdopen(fileno(stdout), "wbi", fp_out_header, index); // seek the input file to the beginning of the the entries, which is the same // location as where the index begins in the output file. if(0 != fseek(fp_in->fp, fp_out_header->index_offset, SEEK_SET)) { ion_error(__func__, "fseek", Exit, ReadFileError); } // write the sff entries while(NULL != (sff = sff_read(fp_in))) { sff_write(fp_out, sff); sff_destroy(sff); } // destroy the header. Don't destroy index, sff_fclose does that sff_header_destroy(fp_out_header); // sff_index_destroy(index); sff_fclose(fp_in); sff_fclose(fp_out); } return 0; }
// TODO: should we change the header: // - must trake index_length // - assumes row-major order sff_index_t* sff_index_create(sff_file_t *fp_in, sff_header_t *fp_out_header, int32_t num_rows, int32_t num_cols, int32_t type) { int64_t len = 0; int32_t i, prev_row, prev_col, row, col; sff_index_t *idx; sff_t *sff; uint64_t fp_in_start, prev_pos; idx = sff_index_init(); idx->num_rows = num_rows; idx->num_cols = num_cols; idx->type = type; // alloc switch(type) { case SFF_INDEX_ROW_ONLY: len = 1 + idx->num_rows; idx->offset = ion_malloc(len * sizeof(uint64_t), __func__, "idx->offset"); break; case SFF_INDEX_ALL: len = 1 + (idx->num_rows * idx->num_cols); idx->offset = ion_malloc(len * sizeof(uint64_t), __func__, "idx->offset"); break; default: ion_error(__func__, "this index type is currently not supported", Exit, OutOfRange); } // save where the sff entries started prev_pos = fp_in_start = ftell(fp_in->fp); if(-1L == fp_in_start) { ion_error(__func__, "ftell", Exit, ReadFileError); } // go through the input file i = 0; prev_row = prev_col = 0; while(NULL != (sff = sff_read(fp_in))) { // out of range if(len-1 <= i) { ion_error(__func__, "bug encountered", Exit, OutOfRange); } // get the row/col co-ordinates if(0 == ion_readname_to_rowcol(sff->rheader->name->s, &row, &col)) { ion_error(__func__, "could not understand the read name", Exit, OutOfRange); } // assumes row-major order, skips over reads that are not present if(row < prev_row || (row == prev_row && col < prev_col)) { ion_error(__func__, "SFF file was not sorted in row-major order", Exit, OutOfRange); } while(row != prev_row || col != prev_col) { // add in empty entry switch(type) { case SFF_INDEX_ROW_ONLY: if(0 == prev_col) { // first column idx->offset[i] = UINT64_MAX; // do not increment i, since we only do this when moving to a new row } break; case SFF_INDEX_ALL: // all rows and columns idx->offset[i] = UINT64_MAX; i++; break; default: ion_error(__func__, "this index type is currently not supported", Exit, OutOfRange); } if(len-1 <= i) { ion_error(__func__, "x/y was out of range", Exit, OutOfRange); } prev_col++; if(prev_col == idx->num_cols) { // new row prev_col = 0; prev_row++; if(SFF_INDEX_ROW_ONLY == type) { i++; } } } // add to the index switch(type) { case SFF_INDEX_ROW_ONLY: if(0 == col) { // first column idx->offset[i] = prev_pos; } else if(0 < col && UINT64_MAX == idx->offset[i]) { idx->offset[i] = prev_pos; // do not move onto the next } break; case SFF_INDEX_ALL: // all rows and columns idx->offset[i] = prev_pos; i++; break; default: ion_error(__func__, "this index type is currently not supported", Exit, OutOfRange); } prev_row = row; prev_col = col; // destroy sff_destroy(sff); // next prev_col++; if(prev_col == idx->num_cols) { // new row prev_col = 0; prev_row++; if(SFF_INDEX_ROW_ONLY == type) { i++; } } prev_pos = ftell(fp_in->fp); if(-1L == prev_pos) { ion_error(__func__, "ftell", Exit, ReadFileError); } } // get the last offset idx->offset[len-1] = prev_pos; // update the index offset in the header fp_out_header->index_offset = fp_in_start; // insert between the header and sff entries // update the index length in the header fp_out_header->index_length = sff_index_length(idx); // update the offsets based on the index length for(i=0;i<len;i++) { if(UINT64_MAX != idx->offset[i]) { idx->offset[i] += fp_out_header->index_length; } } return idx; }
int sff_view_main(int argc, char *argv[]) { int i, c; sff_file_t *sff_file_in=NULL, *sff_file_out=NULL; sff_iter_t *sff_iter = NULL; sff_t *sff = NULL; char *fn_names = NULL; char **names = NULL; int32_t names_num = 0, names_mem = 0; int32_t out_mode, min_row, max_row, min_col, max_col; out_mode = 0; min_row = max_row = min_col = max_col = -1; while((c = getopt(argc, argv, "r:c:R:bqh")) >= 0) { switch(c) { case 'r': if(ion_parse_range(optarg, &min_row, &max_row) < 0) { ion_error(__func__, "-r : format not recognized", Exit, OutOfRange); } break; case 'c': if(ion_parse_range(optarg, &min_col, &max_col) < 0) { ion_error(__func__, "-c : format not recognized", Exit, OutOfRange); } break; case 'R': free(fn_names); fn_names = strdup(optarg); break; case 'q': out_mode |= 1; break; case 'b': out_mode |= 2; break; case 'h': default: return usage(); } } if(argc != 1+optind) { return usage(); } else { sff_header_t *header = NULL; if(3 == out_mode) { ion_error(__func__, "options -b and -q cannot be used together", Exit, CommandLineArgument); } // open the input SFF if(-1 != min_row || -1 != max_row || -1 != min_col || -1 != max_col) { sff_file_in = sff_fopen(argv[optind], "rbi", NULL, NULL); } else { sff_file_in = sff_fopen(argv[optind], "rb", NULL, NULL); } header = sff_header_clone(sff_file_in->header); /* copy header, but update n_reads if using index or names */ // read in the names if(NULL != fn_names) { FILE *fp = NULL; char name[1024]="\0"; // lets hope we don't exceed this length names_num = names_mem = 0; names = NULL; if(!(fp = fopen(fn_names, "rb"))) { fprintf(stderr, "** Could not open %s for reading. **\n", fn_names); ion_error(__func__, fn_names, Exit, OpenFileError); } while(EOF != fscanf(fp, "%s", name)) { while(names_num == names_mem) { if(0 == names_mem) names_mem = 4; else names_mem *= 2; names = ion_realloc(names, sizeof(char*) * names_mem, __func__, "names"); } names[names_num] = strdup(name); if(NULL == names[names_num]) { ion_error(__func__, name, Exit, MallocMemory); } names_num++; } names = ion_realloc(names, sizeof(char*) * names_num, __func__, "names"); fclose(fp); header->n_reads = names_num; } else { // if using index, then iterate once through the index to count the entries // so we can set the count correctly in the header if (-1 != min_row || -1 != max_row || -1 != min_col || -1 != max_col) { int entries = 0; sff_iter = sff_iter_query(sff_file_in, min_row, max_row, min_col, max_col); while (NULL != (sff = sff_iter_read(sff_file_in, sff_iter))) entries++; header->n_reads = entries; /* reset sff_iter */ sff_iter_destroy(sff_iter); sff_iter = sff_iter_query(sff_file_in, min_row, max_row, min_col, max_col); } } // print the header switch(out_mode) { case 0: sff_header_print(stdout, header); break; case 1: // do nothing: FASTQ break; case 2: sff_file_out = sff_fdopen(fileno(stdout), "wb", header, NULL); break; } while(1) { int32_t to_print = 1; if(-1 != min_row || -1 != max_row || -1 != min_col || -1 != max_col) { if(NULL == (sff = sff_iter_read(sff_file_in, sff_iter))) { break; } } else { if(NULL == (sff = sff_read(sff_file_in))) { break; } } if(0 < names_mem) { to_print = 0; for(i=0;i<names_num;i++) { if(0 == strcmp(names[i], sff_name(sff))) { to_print = 1; break; } } // shift down if(1 == to_print) { // i < names_num free(names[i]); names[i] = NULL; for(;i<names_num-1;i++) { names[i] = names[i+1]; names[i+1] = NULL; } names_num--; } } if(1 == to_print) { switch(out_mode) { case 0: sff_print(stdout, sff); break; case 1: if(fprintf(stdout, "@%s\n%s\n+\n", sff->rheader->name->s, sff->read->bases->s + sff->gheader->key_length) < 0) { ion_error(__func__, "stdout", Exit, WriteFileError); } for(i=sff->gheader->key_length;i<sff->read->quality->l;i++) { if(fputc(QUAL2CHAR(sff->read->quality->s[i]), stdout) < 0) { ion_error(__func__, "stdout", Exit, WriteFileError); } } if(fputc('\n', stdout) < 0) { ion_error(__func__, "stdout", Exit, WriteFileError); } break; case 2: sff_write(sff_file_out, sff); break; } } sff_destroy(sff); } sff_fclose(sff_file_in); if(2 == out_mode) { sff_fclose(sff_file_out); } if(-1 != min_row || -1 != max_row || -1 != min_col || -1 != max_col) { sff_iter_destroy(sff_iter); } if(0 != names_num) { fprintf(stderr, "** Did not find all the reads with (-R). **\n"); ion_error(__func__, fn_names, Exit, OutOfRange); } sff_header_destroy(header); } if(NULL != names && 0 < names_num) { free(names); } free(fn_names); return 0; }
int wells_combine_main(int argc, char *argv[]) { FILE **fps_in = NULL; wells_chip_t **chips = NULL; int c; int32_t i, j, k, l, n; int32_t nonzero, min_row, max_row, min_col, max_col; min_row = max_row = min_col = max_col = -1; nonzero=0; while((c = getopt(argc, argv, "r:c:zh")) >= 0) { switch(c) { case 'r': if(ion_parse_range(optarg, &min_row, &max_row) < 0) { ion_error(__func__, "-r : format not recognized", Exit, OutOfRange); } break; case 'c': if(ion_parse_range(optarg, &min_col, &max_col) < 0) { ion_error(__func__, "-c : format not recognized", Exit, OutOfRange); } break; case 'z': nonzero = 1; break; case 'h': default: return usage(); } } if(argc - optind < 2) { return usage(); } else { n = argc - optind; // open the files fps_in = ion_calloc(n, sizeof(FILE*), __func__, "fps_in"); for(i=optind;i<argc;i++) { if(!(fps_in[i-optind] = fopen(argv[i], "rb"))) { fprintf(stderr, "** Could not open %s for reading. **\n", argv[i]); ion_error(__func__, argv[i], Exit, OpenFileError); } } // read in the headers chips = ion_calloc(n, sizeof(wells_chip_t*), __func__, "chips"); for(i=0;i<n;i++) { // NB: reads in both wells files if(NULL == (chips[i] = wells_chip_read1(fps_in[i]))) { ion_error(__func__, argv[i+optind], Exit, ReadFileError); } } // check we can combine the data for(i=1;i<n;i++) { if(chips[i-1]->header->num_wells != chips[i]->header->num_wells) { ion_error(__func__, "# of wells did not match", Exit, OutOfRange); } else if(chips[i-1]->header->num_flows != chips[i]->header->num_flows) { ion_error(__func__, "# of flows did not match", Exit, OutOfRange); } else if(0 != strcmp(chips[i-1]->header->flow_order, chips[i]->header->flow_order)) { ion_error(__func__, "flow order did not match", Exit, OutOfRange); } else if(chips[i-1]->num_rows != chips[i]->num_rows) { ion_error(__func__, "# of rows did not match", Exit, OutOfRange); } else if(chips[i-1]->num_cols != chips[i]->num_cols) { ion_error(__func__, "# of columns did not match", Exit, OutOfRange); } } // write the header if(0 == wells_header_write(stdout, chips[0]->header)) { ion_error(__func__, "Could not write to the output file", Exit, WriteFileError); } // combine the data // NB: modifies the wells for the first chip for(k=0;k<chips[0]->num_cols;k++) { // cols for(j=0;j<chips[0]->num_rows;j++) { // rows wells_data_t data_out; // make room for the new flow values data_out.flow_values = ion_calloc(chips[0]->header->num_flows, sizeof(float), __func__, "data_out->flow_values"); for(i=0;i<n;i++) { // chip wells_data_t *data_in = NULL; // read data in if(NULL == (data_in = wells_data_read(fps_in[i], chips[i]->header))) { ion_error(__func__, argv[i+optind], Exit, ReadFileError); } // copy over relevant data if(0 == i) { data_out.x = data_in->x; data_out.y = data_in->y; data_out.rank = data_in->rank; } for(l=0;l<chips[i]->header->num_flows;l++) { // flows // update sum data_out.flow_values[l] += data_in->flow_values[l]; } // destroy wells_data_destroy(data_in); } // update for(l=0;l<chips[0]->header->num_flows;l++) { // flows data_out.flow_values[l] /= n; } // write if(0 == wells_data_write(stdout, chips[0]->header, &data_out)) { ion_error(__func__, "Could not write to the output file", Exit, WriteFileError); } // destroy free(data_out.flow_values); } } // close the files for(i=0;i<n;i++) { fclose(fps_in[i]); } // free free(fps_in); free(chips); } return 0; }
dat_frame_t * dat_frame_read1(FILE *fp, dat_frame_t *cur, dat_frame_t *prev, dat_header_t *header) { int32_t i, mode; uint32_t ctr, compressed; int8_t *tmp_data8=NULL; //FILE *fp_debug = stdout; // for debuggin // read the timestamp and compression flag for this frame if(fread_big_endian_uint32_t(fp, &cur->timestamp) != 1 || fread_big_endian_uint32_t(fp, &compressed) != 1) { return NULL; } // the first frame is always uncompressed... if(NULL == prev || DAT_HEADER_UNINTERLACED == header->interlace_type) { if(0 != compressed) { ion_error(__func__, "compressed", Exit, OutOfRange); } // read in the data if(fread(cur->data, sizeof(uint16_t), header->rows*header->cols, fp) != header->rows*header->cols) { // image data return NULL; } // manually convert from big-endian for(i=0;i<header->rows*header->cols;i++) { cur->data[i] = ntohs(cur->data[i]) & DAT_FRAME_DATA_MASK; // unmask data } } else { uint32_t len, transitions, total, sentinel; uint32_t observed_transitions = 0; // read in the length of the frame, the # of transitions, the // total sum of hte pixel values, and hte sentinel if(fread_big_endian_uint32_t(fp, &len) != 1 || fread_big_endian_uint32_t(fp, &transitions) != 1 || fread_big_endian_uint32_t(fp, &total) != 1 || fread_big_endian_uint32_t(fp, &sentinel) != 1) { return NULL; } // check the sentinel if(sentinel != DAT_HEADER_SIGNATURE) { ion_error(__func__, "cur->sentinel", Exit, OutOfRange); } // subtract len, transitions, total, sentinel len -= sizeof(uint32_t)*4; assert(0 < len); // initialize memory cur->data = ion_calloc(header->rows*header->cols, sizeof(uint16_t), __func__, "cur->data"); tmp_data8 = ion_malloc(len*sizeof(int8_t), __func__, "tmp_data8"); // read in the whole frame // NOTE: could read in byte-by-byte and process to reduce memory overhead if(len != fread(tmp_data8, sizeof(int8_t), len, fp)) { free(tmp_data8); return NULL; } // de-interlace the data i=mode=ctr=0; while(ctr < header->rows*header->cols) { if(len <= i) { // not enough bytes read ion_error(__func__, "len <= i", Exit, OutOfRange); } // switch to 8-bit mode, or 16-bit mode where appropriate if(i < len-1 && DAT_FRAME_KEY_0 == (uint8_t)tmp_data8[i]) { if(DAT_FRAME_KEY_8_1 == (uint8_t)tmp_data8[i+1]) { // 16-bit to 8-bit observed_transitions++; /* fprintf(stderr, "[%d-%d] from %d-bit mode to 8-bit mode #%d/%d ctr=%d\n", i, i+1, mode, observed_transitions, transitions, ctr); */ mode = 8; i+=2; } else if(DAT_FRAME_KEY_16_1 == (uint8_t)tmp_data8[i+1]) { // 8-bit to 16-bit observed_transitions++; /* fprintf(stderr, "[%d-%d] from %d-bit mode to 16-bit mode #%d/%d ctr=%d\n", i, i+1, mode, observed_transitions, transitions, ctr); */ mode = 16; i+=2; } } // Note: assumes we must have data read between mode switches // read in data switch(mode) { case 8: // 8-bit mode cur->data[ctr] = tmp_data8[i] + prev->data[ctr]; ctr++; i++; break; case 16: // 16-bit mode cur->data[ctr] = (ntohs((int16_t)((tmp_data8[i] << 8) | tmp_data8[i+1])) & DAT_FRAME_DATA_MASK) + prev->data[ctr]; ctr++; i+=2; break; default: // mode? ion_error(__func__, "mode", Exit, OutOfRange); break; } } if(((i+3) & ~0x3) != len) { // check that the data was quad-word aligned ion_error(__func__, "quad word alignment", Exit, OutOfRange); } // free tmp_data8 free(tmp_data8); // check that the observed # of transitions equals the state # of // transitions if(transitions != observed_transitions) { ion_error(__func__, "transitions != observed_transitions", Exit, OutOfRange); } } return cur; }