#include #include #include #include #include #include #include #include "libpq-fe.h" // PostgreSQL #include "etcache.h" #include "easygene.h" static void exit_nicely(PGconn *conn) { PQfinish(conn); exit(1); } /* 指定条件を満たす遺伝子情報を含むEasyGeneTrack/EasyGraphTrackを出力する。 */ /* 戻り値 1: 成功(EasyGeneTrackを出力) */ /* 2: 成功(EasyGraphTrackを出力) */ /* 0: 失敗 */ /* 副作用 指定されたストリームにEasyGeneTrack/EasyGraphTrackを書き出す */ int getEasyGeneOrGraphTrack ( char *trackname, /* 今回表示すべきEasyTrackの名前 */ char *species, /* 表示すべき種 */ char *revision, /* 表示すべき種のリビジョン */ char *target, /* 表示すべき対象 */ int start, /* 表示開始位置(0-origin) */ int end, /* 表示終了位置(0-origin) */ int width, /* 出力すべき画像幅の指標 */ char *date, /* 表示すべきEasyTrackの作成日付 */ char *stream, /* 出力先ストリーム(ファイル)名 */ int gene_threshold, /* EasyGraphTrackへの閾値 */ int bUseOptSelect, /* 追加属性のSelect型で検索する */ char *strOptSelect, /* : 追加属性のSelect型の名前 */ char *strOptSelectEle, /* : 追加属性のSelect型の値 */ int bUseOptReal, /* : 追加属性のReal型で検索する */ char *strOptReal, /* : 追加属性のReal型の名前 */ double optRealLower, /* : 追加属性のReal型で下限値 */ double optRealUpper /* : 追加属性のReal型の上限値 */ ) { PGconn *conn; PGresult *res; PGresult *resTrack; PGresult *resGene; PGresult *resTemp; char strConnectInfo[1024]; char sql[1024]; int nTuples; int nFields; int i, j; int start_temp, end_temp; double start_end_temp; FILE *fp; int *pGraph; int gene_start, gene_end, gene_temp, gene_start_pos, gene_end_pos; int returnValue = -1; clock_t t1, t2; struct tms ts1, ts2; float dtr, dtu, dts; int hitGeneID; int nHitGenesNum; int nOptSelectNameID = -1; int nOptRealNameID = -1; double nOptTempValue = -1; char* strTemp; fprintf(stderr, "-------------- \n"); fprintf(stderr, "DB connect time \n"); t1=times(&ts1); /* DB接続開始時刻の取得 */ // DB 接続 // sprintf(strConnectInfo, "dbname=cachegene_%s_%s_%s user=browser", trackname, species, revision); sprintf(strConnectInfo, "dbname=cachegene_%s_%s_%s user=postgres", trackname, species, revision); conn = PQconnectdb(&strConnectInfo[0]); if (PQstatus(conn) != CONNECTION_OK) { fprintf(stderr, "Connection to database '%s' failed.\n", PQdb(conn)); fprintf(stderr, "%s", PQerrorMessage(conn)); exit_nicely(conn); } // トランザクション開始 res = PQexec(conn, "BEGIN"); if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "BEGIN command failed: %s", PQerrorMessage(conn)); PQclear(res); exit_nicely(conn); } PQclear(res); t2=times(&ts2); /* 終了時刻の取得 */ dtr=(float)(t2-t1) / CLK_TCK; /* 時間の算出 */ dtu=(float)(ts2.tms_utime-ts1.tms_utime) / CLK_TCK; /* ユーザ時間の算出 */ dts=(float)(ts2.tms_stime-ts1.tms_stime) / CLK_TCK; /* システム時間の算出 */ fprintf(stderr, "Real time: %.2f\n", dtr); /* 時間の表示 */ fprintf(stderr, "User time: %.2f\n", dtu); fprintf(stderr, "System time: %.2f\n", dts); fprintf(stderr, "-------------- \n"); // (start > end) の場合に対応 if (start <= end) { start_temp = start; end_temp = end; } else { start_temp = end; end_temp = start; } start_end_temp = end_temp - start_temp; fprintf(stderr, "-------------- \n"); fprintf(stderr, "DB search time \n"); t1=times(&ts1); /* 開始時刻の取得 */ // Track行のテーブルのリソースを取得 sprintf(sql, "SELECT * FROM Track;"); resTrack = PQexec(conn, sql); if (PQntuples(resTrack) != 1) { // error fprintf(stderr, "Could not find Track from Cache DB.\n"); exit_nicely(conn); } // 範囲内の遺伝子を検索する(Exonは関係なし) // 高速化のため、追加属性の検索はここでは行わない。(TargetとRangeのみ) sprintf(sql, "SELECT * FROM Data WHERE target=\'%s\'AND ((range_start <= %d AND %d <= range_end) OR (range_end <= %d AND %d <= range_start));", target, end_temp, start_temp, end_temp, start_temp); resGene = PQexec(conn, sql); t2=times(&ts2); /* 終了時刻の取得 */ dtr=(float)(t2-t1) / CLK_TCK; /* 時間の算出 */ dtu=(float)(ts2.tms_utime-ts1.tms_utime) / CLK_TCK; /* ユーザ時間の算出 */ dts=(float)(ts2.tms_stime-ts1.tms_stime) / CLK_TCK; /* システム時間の算出 */ fprintf(stderr, "Real time: %.2f\n", dtr); /* 時間の表示 */ fprintf(stderr, "User time: %.2f\n", dtu); fprintf(stderr, "System time: %.2f\n", dts); fprintf(stderr, "-------------- \n"); nTuples = PQntuples(resGene); nFields = PQnfields(resGene); if (stream == NULL || strcmp(stream, "") == 0 || strcmp(stream, "stdout") == 0) { // 標準出力 fp = stdout; } else { fp = fopen(stream, "w"); if (!fp) { fprintf(stderr, "Could not open Output stream file: %s\n", stream); return 0; } } // 追加属性検索用 if (bUseOptSelect == 1) { sprintf(sql, "SELECT * FROM OptattrSelectName WHERE select_name_str='%s'", strOptSelect); resTemp = PQexec(conn, sql); if (PQntuples(resTemp) >= 1) { nOptSelectNameID = atoi(PQgetvalue(resTemp, 0, PQfnumber(resTemp, "select_name_id"))); } PQclear(resTemp); } if (bUseOptReal == 1) { sprintf(sql, "SELECT * FROM OptattrRealName WHERE real_name_str='%s'", strOptReal); resTemp = PQexec(conn, sql); if (PQntuples(resTemp) >= 1) { nOptRealNameID = atoi(PQgetvalue(resTemp, 0, PQfnumber(resTemp, "real_name_id"))); } PQclear(resTemp); } // 追加属性でフィルタリングした後の遺伝子数を計算する。 // 高速化のために生じた重複処理。 nHitGenesNum = 0; if (bUseOptSelect != 1 && bUseOptReal != 1) { nHitGenesNum = nTuples; } else { for (i = 0; i < nTuples; i++) { // 遺伝子IDを取得 hitGeneID = atoi(PQgetvalue(resGene, i, PQfnumber(resGene, "data_id"))); // OptSelectでフィルタリング if (bUseOptSelect == 1) { sprintf(sql, "SELECT * FROM OptattrDataSelect WHERE data_id=%d AND select_name_id=%d", hitGeneID, nOptSelectNameID); resTemp = PQexec(conn, sql); if (PQntuples(resTemp) < 1) { PQclear(resTemp); continue; } strTemp = PQgetvalue(resTemp, 0, PQfnumber(resTemp, "select_name")); PQclear(resTemp); if (strcmp(strOptSelectEle, strTemp) != 0) { continue; } } // OptRealでフィルタリング if (bUseOptReal == 1) { sprintf(sql, "SELECT * FROM OptattrDataReal WHERE data_id=%d AND real_name_id=%d", hitGeneID, nOptRealNameID); resTemp = PQexec(conn, sql); if (PQntuples(resTemp) < 1) { PQclear(resTemp); continue; } nOptTempValue = atof(PQgetvalue(resTemp, 0, PQfnumber(resTemp, "real_value"))); PQclear(resTemp); if (nOptTempValue < optRealLower || optRealUpper < nOptTempValue) { continue; } } nHitGenesNum++; } } if (nHitGenesNum <= gene_threshold) { // EasyGeneTrack を出力する。 // 結果がゼロでも、ヘッダ行だけを出力する。 t1=times(&ts1); /* 開始時刻の取得 */ fprintf(fp, "geneTrack name=%s comment=\"%s\" description_url=%s color=%s,%s,%s species=\"%s\" revision=\"%s\" species_url=%s date=%s optattr=\"%s\" #%s\n", PQgetvalue(resTrack, 0, PQfnumber(resTrack, "track_name")), PQgetvalue(resTrack, 0, PQfnumber(resTrack, "comment")), PQgetvalue(resTrack, 0, PQfnumber(resTrack, "description_url")), PQgetvalue(resTrack, 0, PQfnumber(resTrack, "color_red")), PQgetvalue(resTrack, 0, PQfnumber(resTrack, "color_green")), PQgetvalue(resTrack, 0, PQfnumber(resTrack, "color_blue")), PQgetvalue(resTrack, 0, PQfnumber(resTrack, "species")), PQgetvalue(resTrack, 0, PQfnumber(resTrack, "revision")), PQgetvalue(resTrack, 0, PQfnumber(resTrack, "species_url")), PQgetvalue(resTrack, 0, PQfnumber(resTrack, "date")), PQgetvalue(resTrack, 0, PQfnumber(resTrack, "optattr_str")), PQgetvalue(resTrack, 0, PQfnumber(resTrack, "memo")) ); PQclear(resTrack); // Hitした遺伝子 // 逆順で取得される for (i = nTuples - 1; i >= 0; i--) { // 遺伝子IDを取得 hitGeneID = atoi(PQgetvalue(resGene, i, PQfnumber(resGene, "data_id"))); // OptSelectでフィルタリング if (bUseOptSelect == 1) { sprintf(sql, "SELECT * FROM OptattrDataSelect WHERE data_id=%d AND select_name_id=%d", hitGeneID, nOptSelectNameID); resTemp = PQexec(conn, sql); if (PQntuples(resTemp) < 1) { PQclear(resTemp); continue; } strTemp = PQgetvalue(resTemp, 0, PQfnumber(resTemp, "select_name")); PQclear(resTemp); if (strcmp(strOptSelectEle, strTemp) != 0) { continue; } } // OptRealでフィルタリング if (bUseOptReal == 1) { sprintf(sql, "SELECT * FROM OptattrDataReal WHERE data_id=%d AND real_name_id=%d", hitGeneID, nOptRealNameID); resTemp = PQexec(conn, sql); if (PQntuples(resTemp) < 1) { PQclear(resTemp); continue; } nOptTempValue = atof(PQgetvalue(resTemp, 0, PQfnumber(resTemp, "real_value"))); PQclear(resTemp); if (nOptTempValue < optRealLower || optRealUpper < nOptTempValue) { continue; } } // 高速化のために、all_str を使用する。更新の際は、all_strも更新すること。 fprintf(fp, "%s\n", PQgetvalue(resGene, i, PQfnumber(resGene, "all_str"))); } fprintf(stderr, "-------------- \n"); fprintf(stderr, "num of hit genes : %d \n", nHitGenesNum); t2=times(&ts2); /* 終了時刻の取得 */ dtr=(float)(t2-t1) / CLK_TCK; /* 時間の算出 */ dtu=(float)(ts2.tms_utime-ts1.tms_utime) / CLK_TCK; /* ユーザ時間の算出 */ dts=(float)(ts2.tms_stime-ts1.tms_stime) / CLK_TCK; /* システム時間の算出 */ fprintf(stderr, "-------------- \n"); fprintf(stderr, "EasyGeneTrackFile output time \n"); fprintf(stderr, "Real time: %.2f\n", dtr); /* 時間の表示 */ fprintf(stderr, "User time: %.2f\n", dtu); fprintf(stderr, "System time: %.2f\n", dts); fprintf(stderr, "-------------- \n"); returnValue = 1; } // EasyGraphTrack-------------------------------------------------------------------------------- else { // EasyGraphTrack を出力する。 t1=times(&ts1); /* 開始時刻の取得 */ // 1行目 // EasyGeneTrack の内容をそのまま使っている // max, min, blend は省略 fprintf(fp, "graphTrack name=%s comment=\"%s\" description_url=%s color=%s,%s,%s species=\"%s\" revision=\"%s\" species_url=%s date=%s #%s\n", PQgetvalue(resTrack, 0, PQfnumber(resTrack, "track_name")), PQgetvalue(resTrack, 0, PQfnumber(resTrack, "comment")), PQgetvalue(resTrack, 0, PQfnumber(resTrack, "description_url")), PQgetvalue(resTrack, 0, PQfnumber(resTrack, "color_red")), PQgetvalue(resTrack, 0, PQfnumber(resTrack, "color_green")), PQgetvalue(resTrack, 0, PQfnumber(resTrack, "color_blue")), PQgetvalue(resTrack, 0, PQfnumber(resTrack, "species")), PQgetvalue(resTrack, 0, PQfnumber(resTrack, "revision")), PQgetvalue(resTrack, 0, PQfnumber(resTrack, "species_url")), PQgetvalue(resTrack, 0, PQfnumber(resTrack, "date")), //PQgetvalue(resTrack, 0, PQfnumber(resTrack, "optattr_str")), PQgetvalue(resTrack, 0, PQfnumber(resTrack, "memo")) ); PQclear(resTrack); // int[width] の配列に、各遺伝子の範囲に対応する部分をインクリメント pGraph = malloc(sizeof(int)*width); if (pGraph == NULL) { // malloc failed fclose(fp); PQclear(resGene); res = PQexec(conn, "END"); PQclear(res); PQfinish(conn); return 0; } onmemIntArrays++; // 初期化 for (i = 0; i <= width - 1; i++) pGraph[i] = 0; // Hitした遺伝子 for (i = 0; i < nTuples; i++) { // 遺伝子IDを取得 hitGeneID = atoi(PQgetvalue(resGene, i, PQfnumber(resGene, "data_id"))); // OptSelectでフィルタリング if (bUseOptSelect == 1) { sprintf(sql, "SELECT * FROM OptattrDataSelect WHERE data_id=%d AND select_name_id=%d", hitGeneID, nOptSelectNameID); resTemp = PQexec(conn, sql); if (PQntuples(resTemp) < 1) { PQclear(resTemp); continue; } strTemp = PQgetvalue(resTemp, 0, PQfnumber(resTemp, "select_name")); PQclear(resTemp); if (strcmp(strOptSelectEle, strTemp) != 0) { continue; } } // OptRealでフィルタリング if (bUseOptReal == 1) { sprintf(sql, "SELECT * FROM OptattrDataReal WHERE data_id=%d AND real_name_id=%d", hitGeneID, nOptRealNameID); resTemp = PQexec(conn, sql); if (PQntuples(resTemp) < 1) { PQclear(resTemp); continue; } nOptTempValue = atof(PQgetvalue(resTemp, 0, PQfnumber(resTemp, "real_value"))); PQclear(resTemp); if (nOptTempValue < optRealLower || optRealUpper < nOptTempValue) { continue; } } // 遺伝子領域を取得して、グラフ内の位置に変換する。 gene_start = atoi(PQgetvalue(resGene, i, PQfnumber(resGene, "range_start"))); gene_end = atoi(PQgetvalue(resGene, i, PQfnumber(resGene, "range_end"))); if (gene_start > gene_end) { gene_temp = gene_start; gene_start = gene_end; gene_end = gene_temp; } gene_start_pos = (width - 1) * ((double)(gene_start - start_temp) / start_end_temp); gene_end_pos = (width - 1) * ((double)(gene_end - start_temp) / start_end_temp); if (gene_start_pos < 0) { // これはあり gene_start_pos = 0; } else if (gene_start_pos >= width) { // error continue; } if (gene_end_pos < 0) { // error continue; } else if (gene_end_pos >= width) { // これはあり gene_end_pos = width - 1; } for (j = gene_start_pos; j <= gene_end_pos; j++ ) { pGraph[j]++; } } // 一行のみ(target は、一つ目のものを使用) fprintf(fp, "graph target=%s range=%d,%d unit=%d nums=", PQgetvalue(resGene, 0, PQfnumber(resGene, "target")), start, end, abs(end - start) / width); for (j = 0; j < width - 1; j++) { fprintf(fp, "%d,", pGraph[j]); } fprintf(fp, "%d\n", pGraph[width - 1]); free(pGraph); onmemIntArrays--; fprintf(stderr, "-------------- \n"); fprintf(stderr, "num of hit genes : %d \n", nHitGenesNum); t2=times(&ts2); /* 終了時刻の取得 */ dtr=(float)(t2-t1) / CLK_TCK; /* 時間の算出 */ dtu=(float)(ts2.tms_utime-ts1.tms_utime) / CLK_TCK; /* ユーザ時間の算出 */ dts=(float)(ts2.tms_stime-ts1.tms_stime) / CLK_TCK; /* システム時間の算出 */ fprintf(stderr, "-------------- \n"); fprintf(stderr, "EasyGraphTrackFile output time \n"); fprintf(stderr, "Real time: %.2f\n", dtr); /* 時間の表示 */ fprintf(stderr, "User time: %.2f\n", dtu); fprintf(stderr, "System time: %.2f\n", dts); fprintf(stderr, "-------------- \n"); returnValue = 2; } fclose(fp); PQclear(resGene); /* end the transaction */ res = PQexec(conn, "END"); PQclear(res); /* close the connection to the database and cleanup */ PQfinish(conn); return returnValue; }