diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 71ac201..44a4d64 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -18,8 +18,15 @@ jobs:
target_arch: arm64
- os: ubuntu-latest
target_arch: arm64
+ include:
+ - os: macos-latest
+ target_arch: x86_64
+ runs-on: macos-13
+ - os: macos-latest
+ target_arch: arm64
+ runs-on: macos-latest
- runs-on: ${{ matrix.os }}
+ runs-on: ${{ matrix.runs-on || matrix.os }}
steps:
- name: Check runner OS
run: echo "Runner OS is ${{ runner.os }}"
@@ -27,6 +34,12 @@ jobs:
- name: Checkout code
uses: actions/checkout@v2
+ - name: Install NSIS on Windows
+ if: runner.os == 'Windows'
+ shell: powershell
+ run: |
+ choco install nsis -y --no-progress
+
- name: install GL and x11 for Linux
if: runner.os == 'Linux'
run: |
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index bf88ad0..e6e8c63 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -37,6 +37,7 @@ jobs:
if: runner.os == 'Windows'
shell: cmd
run: |
+ choco install nsis -y --no-progress
install.cmake.bat
- name: Run install script on Linux
diff --git a/.gitignore b/.gitignore
index 1570b61..9a55a13 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@ app/
ascii.dSYM/
build_cmake/
builddir/
+build/
*.DS_Store
__pycache__/
*.pyc
@@ -35,8 +36,8 @@ python/classic_cut/show_hic_density.py
python/colormap_colorblind/*
python/greedy_topo_sort_test/*
python/linear_weight_test/*
+python/frag_cluster/kmeans_main_test.cpp
-subprojects/eigen
subprojects/glfw
subprojects/glm
subprojects/imgui
@@ -71,6 +72,7 @@ include/GLFW/glfw3native.h
include/libdeflate.h
src/aisort_cz.cpp
src/aisort_cz.h
+src/parse_agp_test.cpp
PretextViewAI.zip
test_data/
diff --git a/.gitmodules b/.gitmodules
index cfbf012..eee42f1 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -18,3 +18,9 @@
[submodule "subprojects/fmt"]
path = subprojects/fmt
url = https://github.com/fmtlib/fmt.git
+[submodule "subprojects/pybind11"]
+ path = subprojects/pybind11
+ url = https://github.com/pybind/pybind11.git
+[submodule "subprojects/eigen"]
+ path = subprojects/eigen
+ url = https://gitlab.com/libeigen/eigen.git
diff --git a/AGPCorrect b/AGPCorrect
old mode 100755
new mode 100644
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e800b11..9b15866 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.17)
-project(PretextView VERSION "1.0.3")
+project(PretextView VERSION "1.0.4")
option(FORCE_MAC_X86 "Force macOS x86_64 build" OFF)
@@ -7,6 +7,8 @@ option(BUILD_UNIVERSAL "Build macOS universal binary" OFF)
option(WITH_TORCH "Find and link torch lib" OFF)
option(DEBUG_OUTPUT_LIKELIHOOD_TABLE "Output likelihood table to file" OFF)
option(DEBUG_OUTPUT_PIXEL_CUT_FILE "Output the pixel cut files" OFF)
+option(PYTHON_SCOPED_INTERPRETER "Use Python scoped interpreter" OFF)
+option(AI_PIC_DETECTION "Enable AI error pattern detection " OFF)
set(CMAKE_C_STANDARD 17)
set(CMAKE_CXX_STANDARD 17)
@@ -15,6 +17,8 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(target_name PretextViewAI)
+
+
if (APPLE)
if(FORCE_MAC_X86)
message(STATUS "Forcing x86_64 architecture build")
@@ -64,11 +68,11 @@ message(STATUS "Install path: ${CMAKE_INSTALL_PREFIX}")
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
- message(STATUS "Debug version")
+ message(STATUS "Build version: Debug ")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g -O0")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -O0")
else()
- message(STATUS "Release version")
+ message(STATUS "Build version: Release ")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
endif()
@@ -76,11 +80,11 @@ endif()
include_directories(
include
src
- subprojects/imgui
subprojects/glfw/include
subprojects/libdeflate
subprojects/glm
subprojects/fmt/include
+ subprojects/eigen
)
add_subdirectory(subprojects/glfw)
@@ -101,6 +105,15 @@ else()
endif()
+# test the parse_agp
+if (AGP_TEST_FLAG)
+ add_executable(parse_agp_test src/parse_agp_test.cpp)
+ target_link_libraries(parse_agp_test PRIVATE ${lib_fmt})
+ if (CMAKE_BUILD_TYPE STREQUAL "Debug")
+ target_compile_definitions(parse_agp_test PRIVATE DEBUG)
+ endif()
+endif()
+
find_library(
lib_deflate_static
NAMES deflate deflatestatic
@@ -115,7 +128,7 @@ else()
message(STATUS "lib_deflate_static found: ${lib_deflate_static}")
endif()
-add_library(lib_yahs STATIC
+add_library(yahs STATIC
src/yahs_sort.cpp
)
@@ -134,27 +147,18 @@ if (WITH_TORCH)
sortlib PUBLIC
${TORCH_LIBRARIES}
${torchscatter}
- lib_yahs)
+ yahs)
else()
message(STATUS "Libtorch: Build without libtorch")
add_library(sortlib STATIC src/frag_sort.cpp )
- target_link_libraries(sortlib PRIVATE lib_yahs)
+ target_link_libraries(sortlib PRIVATE yahs)
endif()
add_library(glad STATIC src/glad.c)
add_library(utilsPretextView STATIC src/utilsPretextView.cpp)
add_library(copy_texture STATIC src/copy_texture.cpp)
-# target_link_libraries(copy_texture PRIVATE Eigen3::Eigen)
-add_library(imgui STATIC
- subprojects/imgui/imgui_demo.cpp
- subprojects/imgui/imgui_draw.cpp
- subprojects/imgui/imgui_tables.cpp
- subprojects/imgui/imgui_widgets.cpp
- subprojects/imgui/imgui.cpp
- subprojects/imgui/backends/imgui_impl_glfw.cpp
- subprojects/imgui/backends/imgui_impl_opengl3.cpp
- )
+
if(NOT APPLE)
add_executable( ${target_name} PretextView.cpp )
@@ -170,14 +174,20 @@ target_compile_definitions(${target_name} PRIVATE PV=${PROJECT_VERSION})
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
target_compile_definitions(${target_name} PRIVATE DEBUG)
target_compile_definitions(copy_texture PRIVATE DEBUG)
- message(STATUS "Debug version: flag (${CMAKE_BUILD_TYPE}) with DEBUG")
-else()
- message(STATUS "Release version: flag (${CMAKE_BUILD_TYPE}) without DEBUG")
endif()
if (DEBUG_OUTPUT_LIKELIHOOD_TABLE)
- message(STATUS "Debug version: flag (${CMAKE_BUILD_TYPE}) with DEBUG_OUTPUT_LIKELIHOOD_TABLE")
+ message(STATUS "DEBUG_OUTPUT_LIKELIHOOD_TABLE: defined")
target_compile_definitions(${target_name} PRIVATE DEBUG_OUTPUT_LIKELIHOOD_TABLE)
+else()
+ message(STATUS "DEBUG_OUTPUT_LIKELIHOOD_TABLE: not defined")
endif()
+if (AI_PIC_DETECTION)
+ message(STATUS "AI_PIC_DETECTION: defined")
+ target_compile_definitions(${target_name} PRIVATE AI_PIC_DETECTION)
+else()
+ message(STATUS "AI_PIC_DETECTION: not defined")
+endif()
+
target_link_libraries(
${target_name} PRIVATE
@@ -188,11 +198,27 @@ target_link_libraries(
glad
utilsPretextView
copy_texture
- imgui
glfw
- lib_yahs
+ yahs
)
+# link libraries only for debug version
+if (CMAKE_BUILD_TYPE STREQUAL "Debug")
+ include_directories(
+ subprojects/imgui
+ )
+ add_library(imgui STATIC
+ subprojects/imgui/imgui_demo.cpp
+ subprojects/imgui/imgui_draw.cpp
+ subprojects/imgui/imgui_tables.cpp
+ subprojects/imgui/imgui_widgets.cpp
+ subprojects/imgui/imgui.cpp
+ subprojects/imgui/backends/imgui_impl_glfw.cpp
+ subprojects/imgui/backends/imgui_impl_opengl3.cpp
+ )
+ target_link_libraries(${target_name} PRIVATE imgui)
+endif()
+
if (APPLE)
set(library_need Cocoa OpenGL IOKit CoreVideo)
find_library(METAL_LIB Metal)
@@ -229,6 +255,50 @@ foreach (library ${library_need})
endforeach()
+
+# ============ Kmeans for Clustering ==============
+
+if (PYTHON_SCOPED_INTERPRETER)
+ find_package(Python COMPONENTS Development Interpreter)
+else()
+ message(STATUS "PYTHON_SCOPED_INTERPRETER defined, but Python not found, build without PYTHON_SCOPED_INTERPRETER")
+endif()
+
+if (PYTHON_SCOPED_INTERPRETER AND Python_FOUND)
+ message(STATUS "PYTHON_SCOPED_INTERPRETER defined, build with PYTHON_SCOPED_INTERPRETER")
+ add_subdirectory(subprojects/pybind11)
+ # 拷贝python lib文件到编译目录下
+ get_filename_component(Python_LIBRARIES "${Python_LIBRARIES}" REALPATH)
+ get_filename_component(Python_lib_name "${Python_LIBRARIES}" NAME)
+ file(COPY ${Python_LIBRARIES} DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
+ message(STATUS "Python lib realpath: ${Python_LIBRARIES}, name: ${Python_lib_name}")
+ # 获取拷贝后文件的路径
+ # find_library(PYTHON_LIB_PATH
+ # NAMES ${Python_lib_name}
+ # PATHS ${CMAKE_CURRENT_BINARY_DIR}
+ # REQUIRED)
+ set(PYTHON_LIB_PATH "${CMAKE_CURRENT_BINARY_DIR}/${Python_lib_name}")
+ add_custom_command(TARGET ${target_name} POST_BUILD
+ COMMAND install_name_tool -id @rpath/${Python_lib_name} ${Python_LIBRARIES}
+ COMMENT "Fix install_name of python lib")
+ message(STATUS "Build with PYTHON_SCOPED_INTERPRETER. Python search path: ${CMAKE_CURRENT_BINARY_DIR}, Python version: ${Python_VERSION}, Python_lib: ${PYTHON_LIB_PATH}")
+
+ # 将 Python 脚本复制到构建目录
+ configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/python/frag_cluster/kmeans_utils.py
+ ${CMAKE_CURRENT_BINARY_DIR}/kmeans_utils.py
+ COPYONLY )
+
+ # 链接 pybind11 和 Python 库
+ target_link_libraries(${target_name} PRIVATE
+ ${PYTHON_LIB_PATH}
+ pybind11::embed
+ )
+ message(STATUS "Using Python scoped interpreter for Kmeans")
+ target_compile_definitions(${target_name} PRIVATE PYTHON_SCOPED_INTERPRETER)
+endif()
+
+
# ============ CMAKE INSTALLATION ==============
file(GLOB aimodel_files "${CMAKE_CURRENT_SOURCE_DIR}/ai_model/*")
file(GLOB torch_copy_libs "${TORCH_INSTALL_PREFIX}/lib/*")
@@ -259,21 +329,36 @@ if(APPLE)
set_target_properties(
${target_name}
PROPERTIES
- INSTALL_RPATH "@executable_path/../Frameworks")
+ INSTALL_RPATH "@executable_path/../Frameworks"
+ BUILD_WITH_INSTALL_RPATH TRUE
+ MACOSX_RPATH TRUE
+ BUNDLE TRUE
+ )
install(TARGETS ${target_name}
BUNDLE DESTINATION .
- COMPONENT Runtime) # generate the ${target_name}.app package under ${cmake_install_prefix}
- install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist"
- DESTINATION "${target_name}.app/Contents")
+ COMPONENT Runtime)
+ # install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist"
+ # DESTINATION "${target_name}.app/Contents")
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/icon.icns"
DESTINATION "${target_name}.app/Contents/Resources" )
+ install(
+ FILES ${lib_deflate_static}
+ DESTINATION "${target_name}.app/Contents/Frameworks")
if (WITH_TORCH)
install(FILES ${torch_copy_libs}
DESTINATION "${target_name}.app/Contents/Frameworks" )
install(FILES ${aimodel_files}
DESTINATION "${target_name}.app/Contents/Resources/ai_model" )
endif()
-elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
+ if (PYTHON_SCOPED_INTERPRETER)
+ install(
+ FILES ${PYTHON_LIB_PATH}
+ DESTINATION "${target_name}.app/Contents/Frameworks" )
+ install(
+ FILES ${CMAKE_CURRENT_SOURCE_DIR}/python/frag_cluster/kmeans_utils.py
+ DESTINATION "${target_name}.app/Contents/Resources" )
+ endif ()
+elseif(UNIX AND NOT APPLE) # Linux
message(STATUS "[Cmake Install]: Linux")
set_target_properties(
${target_name}
@@ -283,6 +368,9 @@ elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
TARGETS ${target_name}
RUNTIME DESTINATION "bin"
COMPONENT Runtime)
+ install(
+ FILES ${lib_deflate_static}
+ DESTINATION "lib")
if (WITH_TORCH)
install(
FILES ${torch_copy_libs}
@@ -291,6 +379,14 @@ elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
FILES ${aimodel_files}
DESTINATION "ai_model")
endif()
+ if (PYTHON_SCOPED_INTERPRETER)
+ install(
+ FILES ${PYTHON_LIB_PATH}
+ DESTINATION "lib" )
+ install(
+ FILES ${CMAKE_CURRENT_SOURCE_DIR}/python/frag_cluster/kmeans_utils.py
+ DESTINATION "." )
+ endif ()
else () # windows
message(STATUS "[Cmake Install]: Windows")
target_sources(${target_name} PRIVATE "${CMAKE_SOURCE_DIR}/PretextView.rc") # add logo to win version
@@ -298,6 +394,9 @@ else () # windows
TARGETS ${target_name}
RUNTIME DESTINATION .
COMPONENT Runtime)
+ install(
+ FILES ${lib_deflate_static}
+ DESTINATION .)
if (WITH_TORCH)
install(
FILES ${torch_copy_libs}
@@ -306,6 +405,14 @@ else () # windows
FILES ${aimodel_files}
DESTINATION "ai_model")
endif()
+ if (PYTHON_SCOPED_INTERPRETER)
+ install(
+ FILES ${PYTHON_LIB_PATH}
+ DESTINATION . )
+ install(
+ FILES ${CMAKE_CURRENT_SOURCE_DIR}/python/frag_cluster/kmeans_utils.py
+ DESTINATION . )
+ endif ()
endif()
@@ -314,7 +421,7 @@ include(InstallRequiredSystemLibraries)
set(CPACK_PACKAGE_NAME ${target_name})
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
set(CPACK_PACKAGE_DIRECTORY ${CMAKE_BINARY_DIR})
-set(CPACK_PACKAGE_HOMEPAGE_URL "https://github.com/guanshaoheng/PretextView")
+set(CPACK_PACKAGE_HOMEPAGE_URL "https://github.com/sanger-tol/PretextView")
set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}-${ARCH_TYPE}")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENCE.txt")
diff --git a/Info.plist b/Info.plist
index d9961f5..a0bd507 100644
--- a/Info.plist
+++ b/Info.plist
@@ -13,7 +13,7 @@
CFBundleIconFile
icon.icns
CFBundleShortVersionString
- 1.0.3
+ 1.0.4
CFBundleInfoDictionaryVersion
6.0
CFBundlePackageType
diff --git a/PretextView.cpp b/PretextView.cpp
index ea20743..de67a4f 100644
--- a/PretextView.cpp
+++ b/PretextView.cpp
@@ -30,6 +30,10 @@ SOFTWARE.
#include // place this before add Header.h to avoid macro conflict
+
+#ifdef PYTHON_SCOPED_INTERPRETER
+ #include "kmeans_pybind.h"
+#endif // PYTHON_SCOPED_INTERPRETER
#include
#ifdef DEBUG
@@ -84,7 +88,7 @@ SOFTWARE.
#define STBI_ONLY_PNG
#ifndef DEBUG
-#define STBI_ASSERT(x)
+ #define STBI_ASSERT(x)
#endif // debug
#ifndef STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION
@@ -98,6 +102,19 @@ SOFTWARE.
#pragma clang diagnostic pop
+#ifdef DEBUG_STUCK_PROBLEM
+ #include
+ #include
+ #define Stuck_Problem_Check_Debug { \
+ fmt::println("Stuck problem check :: File: {}, line: {}, time: {:%H:%M:%S}", \
+ __FILE__, __LINE__, \
+ fmt::localtime(std::time(nullptr))\
+ ); \
+ }
+#else
+ #define Stuck_Problem_Check_Debug
+#endif //DEBUG_STUCK_PROBLEM
+
#include "Resources.cpp" // defines icons, fonts
@@ -108,6 +125,7 @@ SOFTWARE.
#include "frag_cut_calculation.h"
#include "grey_out_settings.h"
#include "user_profile_settings.h"
+#include "parse_agp.h"
#include "shaderSource.h"
/*
@@ -395,6 +413,29 @@ s32
useCustomOrder = 0;
+#define text_box_font_size_default 20.0f
+struct TextBoxSize
+{
+ f32 font_size = text_box_font_size_default;
+
+ TextBoxSize(): font_size(text_box_font_size_default) {}
+
+ void increase_size(){
+ font_size += 2.0f;
+ font_size = my_Min(font_size, 36.0f);
+ }
+
+ void decrease_size(){
+ font_size -= 2.0f;
+ font_size = my_Max(font_size, 8.0f);
+ }
+
+ void defult_size(){
+ font_size = text_box_font_size_default;
+ }
+};
+global_variable TextBoxSize text_box_size;
+
global_variable
quad_data *
Grid_Data;
@@ -573,6 +614,7 @@ meta_mode_data *
Extension_Mode_Data;
+
/*
用于显示在input sequences中点击后选中的片段的名字,
显示label持续 5 秒钟
@@ -639,7 +681,7 @@ Global_Mode = mode_normal;
#define Scaff_Edit_Mode (Global_Mode == mode_scaff_edit)
#define MetaData_Edit_Mode (Global_Mode == mode_meta_edit)
#define Extension_Mode (Global_Mode == mode_extension)
-#define Select_Sort_Area_Mode (Global_Mode == mode_selectExclude_sort_area)
+#define Select_Sort_Area_Mode (Global_Mode == mode_select_sort_area)
global_variable
s32
@@ -679,7 +721,7 @@ auto_sort_state = 0;
global_variable
u32
-auto_cut_state = 0;
+auto_cut_state = 0; // 0: not auto cut, 1: cut, 2: glue the cutted contigs
global_variable s32 auto_cut_button = 0;
global_variable s32 auto_sort_button = 0;
@@ -799,10 +841,16 @@ Default_Tags[] =
"B2",
"B3",
"FalseDuplicate",
- "Primary"
+ "Primary",
+ "vertPaint", // paint vertically
+ "horzPaint", // paint horizontally
+ "crossPaint", // paint with cross
};
+char searchbuf[256] = {0};
+s32 caseSensitive_search_sequences = 0;
+
global_variable
map_state *
Map_State;
@@ -813,3031 +861,2890 @@ Map_State;
FragSortTool* frag_sort_method = new FragSortTool();
global_variable auto auto_curation_state = AutoCurationState();
+#ifdef PYTHON_SCOPED_INTERPRETER
+ global_variable KmeansClusters* kmeans_cluster = nullptr;
+#endif // PYTHON_SCOPED_INTERPRETER
-global_function
-void
-UpdateContigsFromMapState() // reading 从map的状态更新contigs
-{
- u32 lastScaffID = Map_State->scaffIds[0]; // 第一个scaff的编号
- u32 scaffId = lastScaffID ? 1 : 0; //
- u32 lastId = Map_State->originalContigIds[0]; // 第一个像素点对应的id
- u32 lastCoord = Map_State->contigRelCoords[0]; // 第一个像素点的局部坐标
- u32 contigPtr = 0;
- u32 length = 0;
- u32 startCoord = lastCoord;
- u08 inverted = Map_State->contigRelCoords[1] < lastCoord; // 判断是不是反转的
- Map_State->contigIds[0] = 0;
-
- u32 pixelIdx = 0;
- ForLoop(Number_of_Original_Contigs) (Original_Contigs + index)->nContigs = 0; // 将每一个contig的 片段数目 置为零
- ForLoop(Number_of_Pixels_1D - 1) // 遍历每一个像素点 更新 Original_Contigs, Contigs
- // 遍历完之后,contigPtr为214,但是Number_of_Original_Contigs = 218
- {
- if (contigPtr == Max_Number_of_Contigs) break; // 确保 contigPtr 不超出最大contig的数值
+#include "spectral_cluster.h"
- ++length; // current fragment length
- pixelIdx = index + 1; // 像素点编号, 加一因为第一个已经用来初始化了
- u32 id = Map_State->originalContigIds[pixelIdx]; // 像素点的 original contig id, 这里 不使用 % Max_Number_of_Contigs的值是为了区分后面cut之后的片段
- u32 coord = Map_State->contigRelCoords[pixelIdx]; // 像素点的局部坐标
-
- if (
- id != lastId ||
- (inverted && coord != (lastCoord - 1)) ||
- (!inverted && coord != (lastCoord + 1))
- ) // 如果不是一个连续片段
- {
- Original_Contigs[lastId % Max_Number_of_Contigs].contigMapPixels[Original_Contigs[lastId%Max_Number_of_Contigs].nContigs] = pixelIdx - 1 - (length >> 1); // update Original_Contigs: contigMapPixels
- Original_Contigs[lastId % Max_Number_of_Contigs].nContigs++; // update Original_Contigs: nContigs, contigMapPixels
+global_function void
+UserSaveState(const char *headerHash = "userprofile", u08 overwrite = 1, char *path = 0);
- contig *last_cont = Contigs->contigs_arr + contigPtr; // 获取上一个contig的指针, 并且给contigPtr + 1
- contigPtr++;
- last_cont->originalContigId = lastId; // 更新这个片段的id
- last_cont->length = length; // 更新长度
- last_cont->startCoord = startCoord; // 更新开头为当前片段在该contig上的局部坐标 endCoord = startCoord + length - 1
- last_cont->metaDataFlags = Map_State->metaDataFlags + pixelIdx - 1; // Finished (shaoheng): memory problem: assign the pointer to the cont->metaDataFlags, the original is nullptr, the let this ptr point to the last pixel of the contig
- u32 thisScaffID = Map_State->scaffIds[pixelIdx - 1]; // 上一个像素点对应的 scaffid
- last_cont->scaffId = thisScaffID ? ((thisScaffID == lastScaffID) ? (scaffId) : (++scaffId)) : 0; // 如果存在scaffid则(判断是不是同一个scaff,如果是则继续用scaffid,否则++scaffid),否则为0
- lastScaffID = thisScaffID; // 更新
+global_variable
+u08
+Grey_Haplotigs = 1;
+global_variable
+GreyOutSettings* Grey_Out_Settings = nullptr;
- // 余数表示8数的第几位,如果未反向则对应位为0,若反向则对应位为1
- if (IsContigInverted(contigPtr - 1)) // 判断上一个contig是否反向
- { // 位操作更新contigflag
- // 每8个片段的正反采用一个u08表示,每一个bit表示一个正反,余数表示这八个中的第几个,如果没有反向则对应位为0
- if (!inverted) Contigs->contigInvertFlags[(contigPtr - 1) >> 3] &= ~(1 << ((contigPtr - 1) & 7));
- }
- else
- { // 如果反向则额对应位的bit为1
- if (inverted) Contigs->contigInvertFlags[(contigPtr - 1) >> 3] |= (1 << ((contigPtr - 1) & 7)); // 如果反向
- }
+global_variable
+UserProfileSettings* user_profile_settings_ptr = nullptr;
- startCoord = coord; // 当前片段开始的坐标
- length = 0; // 当前片段长度清零0
- if (pixelIdx < (Number_of_Pixels_1D - 1)) inverted = Map_State->contigRelCoords[pixelIdx + 1] < coord; // 更新inverted
- }
- // 更新上一个id和局部坐标
- Map_State->contigIds[pixelIdx] = (u32)contigPtr; // 像素点对应的 片段id 修改为当前的统计得到片段id
- lastId = id; // 更新上一个像素点的id
- lastCoord = coord; // 更新上一个像素点的局部坐标
- }
+global_variable
+u08
+Deferred_Close_UI = 0;
- if (contigPtr < Max_Number_of_Contigs) // contigptr 小于 Number_of_Original_Contigs
- // 更新最后一个contig的最后一个片段信息
- {
- (Original_Contigs + lastId % Max_Number_of_Contigs)->contigMapPixels[(Original_Contigs + lastId % Max_Number_of_Contigs)->nContigs++] = pixelIdx - 1 - (length >> 1);
- ++length;
- contig *cont = Contigs->contigs_arr + contigPtr++;
- cont->originalContigId = lastId;
- cont->length = length;
- cont->startCoord = startCoord;
- cont->metaDataFlags = Map_State->metaDataFlags + pixelIdx - 1;
-
- u32 thisScaffID = Map_State->scaffIds[pixelIdx];
- cont->scaffId = thisScaffID ? ((thisScaffID == lastScaffID) ? (scaffId) : (++scaffId)) : 0;
-
- if (IsContigInverted(contigPtr - 1))
- {
- if (!inverted) Contigs->contigInvertFlags[(contigPtr - 1) >> 3] &= ~(1 << ((contigPtr - 1) & 7));
- }
- else
- {
- if (inverted) Contigs->contigInvertFlags[(contigPtr - 1) >> 3] |= (1 << ((contigPtr - 1) & 7));
- }
- }
+// File Browser
+// from nuklear file browser example
+/* ===============================================================
+ *
+ * GUI
+ *
+ * ===============================================================*/
+struct
+icons
+{
+ struct nk_image home;
+ struct nk_image computer;
+ struct nk_image directory;
- Contigs->numberOfContigs = contigPtr;
-}
+ struct nk_image default_file;
+ struct nk_image img_file;
+};
-global_function
-void
-AddMapEdit(s32 delta, pointui finalPixels, u32 invert);
+enum
+file_groups
+{
+ FILE_GROUP_DEFAULT,
+ FILE_GROUP_PRETEXT,
+ FILE_GROUP_MAX
+};
-global_function
-void
-RebuildContig(u32 pixel)
+enum
+file_types
{
- for (;;)
- {
- u32 contigId = Map_State->contigIds[pixel];
- u32 origContigId = Map_State->get_original_contig_id(pixel);
+ FILE_DEFAULT,
+ FILE_PRETEXT,
+ FILE_PSTM,
+ FILE_MAX
+};
- u32 top = (u32)pixel;
- while (top && (Map_State->contigIds[top - 1] == contigId)) --top;
+struct
+file_group
+{
+ enum file_groups group;
+ u32 pad;
+ const char *name;
+ struct nk_image *icon;
+};
- u32 bottom = pixel;
- while ((bottom < (Number_of_Pixels_1D - 1)) && (Map_State->contigIds[bottom + 1] == contigId)) ++bottom;
+struct
+file
+{
+ enum file_types type;
+ enum file_groups group;
+ const char *suffix;
+};
- if (IsContigInverted(contigId))
- {
- InvertMap(top, bottom);
- AddMapEdit(0, {top, bottom}, 1);
- continue;
- }
+struct
+media
+{
+ int font;
+ int icon_sheet;
+ struct icons icons;
+ struct file_group group[FILE_GROUP_MAX];
+ struct file files[FILE_MAX];
+};
- u08 fragmented = 0;
- ForLoop(Number_of_Pixels_1D)
- {
- if ((Map_State->contigIds[index] != contigId) && (Map_State->get_original_contig_id(index) == origContigId))
- {
- fragmented = 1;
- break;
- }
- }
+#define MAX_PATH_LEN 512
+struct
+file_browser
+{
+ /* path */
+ char file[MAX_PATH_LEN];
+ char home[MAX_PATH_LEN];
+ char directory[MAX_PATH_LEN];
- if (fragmented)
- {
- u32 contigTopCoord = Map_State->contigRelCoords[top];
- if (contigTopCoord)
- {
- u32 otherPixel = 0;
- ForLoop(Number_of_Pixels_1D)
- {
- if ((Map_State->get_original_contig_id(index) == origContigId) && (Map_State->contigRelCoords[index] == (contigTopCoord - 1)))
- {
- otherPixel = index;
- break;
- }
- }
+ /* directory content */
+ char **files;
+ char **directories;
+ size_t file_count;
+ size_t dir_count;
+ struct media *media;
+};
- u08 invert = !otherPixel || (Map_State->contigIds[otherPixel - 1] != Map_State->contigIds[otherPixel]);
- u32 otherPixel2 = otherPixel;
- if (invert)
- {
- while ((otherPixel < (Number_of_Pixels_1D - 1)) && (Map_State->contigIds[otherPixel + 1] == Map_State->contigIds[otherPixel2])) ++otherPixel;
- }
- else
- {
- while (otherPixel2 && (Map_State->contigIds[otherPixel2 - 1] == Map_State->contigIds[otherPixel])) --otherPixel2;
- }
+// file browser
+struct file_browser browser;
+struct file_browser saveBrowser;
+struct file_browser loadBrowser;
+struct file_browser saveAGPBrowser;
+struct file_browser loadAGPBrowser;
- s32 delta = (s32)top - (s32)otherPixel;
- if (delta > 0) --delta;
- else delta = (s32)top - (s32)otherPixel2;
- pointui finalPixels = {(u32)((s32)otherPixel2 + delta), (u32)((s32)otherPixel + delta)};
- RearrangeMap(otherPixel2, otherPixel, delta);
- if (invert) InvertMap(finalPixels.x, finalPixels.y);
- AddMapEdit(delta, finalPixels, invert);
- }
- else
- {
- u32 contigBottomCoord = Map_State->contigRelCoords[bottom];
- u32 otherPixel = 0;
- ForLoop(Number_of_Pixels_1D)
- {
- if ((Map_State->get_original_contig_id(index) == origContigId) && (Map_State->contigRelCoords[index] == (contigBottomCoord + 1)))
- {
- otherPixel = index;
- break;
- }
- }
+#if defined __unix__ || defined __APPLE__
+#include
+#include
+#endif
- u08 invert = (otherPixel == (Number_of_Pixels_1D - 1)) || (Map_State->contigIds[otherPixel + 1] != Map_State->contigIds[otherPixel]);
- u32 otherPixel2 = otherPixel;
-
- if (!invert)
- {
- while ((otherPixel < (Number_of_Pixels_1D - 1)) && (Map_State->contigIds[otherPixel + 1] == Map_State->contigIds[otherPixel2])) ++otherPixel;
- }
- else
- {
- while (otherPixel2 && (Map_State->contigIds[otherPixel2 - 1] == Map_State->contigIds[otherPixel])) --otherPixel2;
- }
-
- s32 delta = (s32)bottom - (s32)otherPixel2;
- if (delta < 0) ++delta;
- else delta = (s32)bottom - (s32)otherPixel;
- pointui finalPixels = {(u32)((s32)otherPixel2 + delta), (u32)((s32)otherPixel + delta)};
- RearrangeMap(otherPixel2, otherPixel, delta);
- if (invert) InvertMap(finalPixels.x, finalPixels.y);
- AddMapEdit(delta, finalPixels, invert);
- }
-
- continue;
- }
- else break;
- }
-}
-
-struct
-map_edit
-{
- u32 finalPix1;
- u32 finalPix2;
- s32 delta;
-};
-
-struct
-waypoint;
-
-struct
-waypoint_quadtree_node
-{
- waypoint *wayp;
- waypoint_quadtree_node *next;
- waypoint_quadtree_node *prev;
-};
-
-struct
-waypoint
-{
- point2f coords;
- f32 z;
- u32 index;
- waypoint *prev;
- waypoint *next;
- waypoint_quadtree_node *node;
- // u16 long_waypoint_mode;
-};
-
-#define Edits_Stack_Size 32768
-#define Waypoints_Stack_Size 128
-
-struct
-map_editor
-{
- map_edit *edits;
- u32 nEdits;
- u32 editStackPtr;
- u32 nUndone;
- u32 pad;
-};
-
-global_variable
-map_editor *
-Map_Editor;
-
-#define Waypoints_Quadtree_Levels 5
-
-struct
-waypoint_quadtree_level
-{
-#ifdef Internal
- u32 show;
-#else
- u32 pad;
-#endif
- f32 size;
- point2f lowerBound;
- waypoint_quadtree_level *children[4];
- waypoint_quadtree_node headNode;
-};
-
-struct
-waypoint_editor
-{
- waypoint freeWaypoints;
- waypoint activeWaypoints;
- waypoint_quadtree_level *quadtree;
- waypoint_quadtree_node freeNodes;
- u32 nWaypointsActive;
- u32 pad;
-};
-
-global_variable
-waypoint_editor *
-Waypoint_Editor;
-
-global_variable u16 Long_Waypoints_Mode = 0; // mode 0: vertical, mode 1: horizontal, mode 2: both
-
-#define Waypoint_Select_Distance 8.0f
-global_variable
-waypoint *
-Selected_Waypoint = 0;
+#ifndef _WIN32
+#include
+#endif
global_function
-waypoint_quadtree_level *
-PushQuadTree(memory_arena *arena, u32 level = 0, point2f lowerBound = {-0.5f, -0.5f}, f32 size = 1.0f)
+char*
+StrDuplicate(const char *src)
{
- waypoint_quadtree_level *quadtreeLevel = 0;
-
- if (level < Waypoints_Quadtree_Levels)
- {
- quadtreeLevel = PushStructP(arena, waypoint_quadtree_level);
- quadtreeLevel->size = size;
- quadtreeLevel->lowerBound = lowerBound;
- quadtreeLevel->headNode = {};
-
-#ifdef Internal
- quadtreeLevel->show = 0;
-#endif
-
- f32 halfSize = size * 0.5f;
- quadtreeLevel->children[0] = PushQuadTree(arena, level + 1, {lowerBound.x, lowerBound.y}, halfSize);
- quadtreeLevel->children[1] = PushQuadTree(arena, level + 1, {lowerBound.x, lowerBound.y + halfSize}, halfSize);
- quadtreeLevel->children[2] = PushQuadTree(arena, level + 1, {lowerBound.x + halfSize, lowerBound.y}, halfSize);
- quadtreeLevel->children[3] = PushQuadTree(arena, level + 1, {lowerBound.x + halfSize, lowerBound.y + halfSize}, halfSize);
- }
-
- return(quadtreeLevel);
+ char *ret;
+ size_t len = strlen(src);
+ if (!len) return 0;
+ ret = (char*)malloc(len+1);
+ if (!ret) return 0;
+ memcpy(ret, src, len);
+ ret[len] = '\0';
+ return ret;
}
global_function
void
-#ifdef Internal
-GetWaypointsWithinRectange(point2f lowerBound, point2f size, waypoint ***bufferPtr, u32 reset = 1);
-#else
-GetWaypointsWithinRectange(point2f lowerBound, point2f size, waypoint ***bufferPtr);
-#endif
-
-global_function
-void
-UpdateWayPoint(waypoint *wayp, point2f coords);
-
-global_function
-void
-MoveWayPoints(map_edit *edit, u32 undo = 0);
+DirFreeList(char **list, size_t size)
+{
+ size_t i;
+ for (i = 0; i < size; ++i)
+ free(list[i]);
+ free(list);
+}
global_function
-void
-AddMapEdit(s32 delta, pointui finalPixels, u32 invert)
+u32
+StringIsLexBigger(char *string, char *toCompareTo)
{
- ++Map_Editor->nEdits;
- Map_Editor->nUndone = 0;
-
- map_edit *edit = Map_Editor->edits + Map_Editor->editStackPtr++;
+ u32 result;
+ u32 equal;
- if (Map_Editor->editStackPtr == Edits_Stack_Size)
+ do
{
- Map_Editor->editStackPtr = 0;
- }
-
- u32 pix1 = (u32)(invert ? my_Max(finalPixels.x, finalPixels.y) : my_Min(finalPixels.x, finalPixels.y));
- u32 pix2 = (u32)(invert ? my_Min(finalPixels.x, finalPixels.y) : my_Max(finalPixels.x, finalPixels.y));
-
- edit->delta = (s32)delta;
- edit->finalPix1 = pix1;
- edit->finalPix2 = pix2;
-}
+ equal = *string == *toCompareTo;
+ result = *string > *(toCompareTo++);
+ } while (equal && (*(string++) != '\0'));
-global_function
-void
-UpdateScaffolds()
-{
- ForLoop(Number_of_Pixels_1D) Map_State->scaffIds[index] = (Contigs->contigs_arr + Map_State->contigIds[index])->scaffId;
+ return(result);
}
global_function
void
-UndoMapEdit()
+CharArrayBubbleSort(char **list, u32 size)
{
- if (Map_Editor->nEdits && !Edit_Pixels.editing)
+ while (size > 1)
{
- --Map_Editor->nEdits;
- ++Map_Editor->nUndone;
-
- if (!Map_Editor->editStackPtr)
- {
- Map_Editor->editStackPtr = Edits_Stack_Size + 1;
- }
-
- map_edit *edit = Map_Editor->edits + (--Map_Editor->editStackPtr);
-
- if (edit->finalPix1 > edit->finalPix2)
- {
- InvertMap((u32)edit->finalPix1, (u32)edit->finalPix2);
+ u32 newSize = 0;
+ ForLoop(size - 1)
+ {
+ if (StringIsLexBigger(list[index], list[index + 1]))
+ {
+ char *tmp = list[index];
+ list[index] = list[index + 1];
+ list[index + 1] = tmp;
+ newSize = index + 1;
+ }
}
-
- u32 start = my_Min(edit->finalPix1, edit->finalPix2);
- u32 end = my_Max(edit->finalPix1, edit->finalPix2);
-
- RearrangeMap(start, end, -edit->delta);
-
- UpdateScaffolds();
+ size = newSize;
}
}
global_function
-void
-RedoMapEdit()
+char**
+DirList(const char *dir, u32 return_subdirs, size_t *count)
{
- if (Map_Editor->nUndone && !Edit_Pixels.editing)
- {
- ++Map_Editor->nEdits;
- --Map_Editor->nUndone;
+ size_t n = 0;
+ char buffer[MAX_PATH_LEN];
+ char **results = NULL;
+#ifndef _WIN32
+ const DIR *none = NULL;
+ DIR *z;
+#else
+ WIN32_FIND_DATA ffd;
+ HANDLE hFind = INVALID_HANDLE_VALUE;
+ char dirBuff[MAX_PATH_LEN];
+#endif
+ size_t capacity = 32;
+ size_t size;
- map_edit *edit = Map_Editor->edits + Map_Editor->editStackPtr++;
+ Assert(dir);
+ Assert(count);
+ strncpy(buffer, dir, MAX_PATH_LEN);
+ n = strlen(buffer);
- if (Map_Editor->editStackPtr == Edits_Stack_Size)
- {
- Map_Editor->editStackPtr = 0;
- }
-
- u32 start = my_Min(edit->finalPix1, edit->finalPix2);
- u32 end = my_Max(edit->finalPix1, edit->finalPix2);
-
- RearrangeMap((u32)((s32)start - edit->delta), (u32)((s32)end - edit->delta), edit->delta);
-
- if (edit->finalPix1 > edit->finalPix2)
- {
- InvertMap((u32)edit->finalPix1, (u32)edit->finalPix2);
- }
-
- UpdateScaffolds();
- }
-}
+#ifndef _WIN32
+ if (n > 0 && (buffer[n-1] != '/'))
+ buffer[n++] = '/';
+#else
+ if (n > 0 && (buffer[n-1] != '\\'))
+ buffer[n++] = '\\';
+#endif
+ size = 0;
-global_function
-void
-MoveWayPoints(map_edit *edit, u32 undo)
-{
- pointui tmp;
- s32 delta;
- pointui finalPixels;
- if (undo)
- {
- tmp = {(u32)edit->finalPix1, (u32)edit->finalPix2};
- delta = -(s32)edit->delta;
- finalPixels = {(u32)((s32)tmp.x + delta), (u32)((s32)tmp.y + delta)};
- }
- else
+#ifndef _WIN32
+ z = opendir(dir);
+#else
+ strncpy(dirBuff, buffer, MAX_PATH_LEN);
+ dirBuff[n] = '*';
+ hFind = FindFirstFile(dirBuff, &ffd);
+#endif
+
+#ifndef _WIN32
+ if (z != none)
+#else
+ if (hFind != INVALID_HANDLE_VALUE)
+#endif
{
- tmp = {(u32)((s32)edit->finalPix1 - (s32)edit->delta), (u32)((s32)edit->finalPix2 - (s32)edit->delta)};
- delta = (s32)edit->delta;
- finalPixels = {(u32)edit->finalPix1, (u32)edit->finalPix2};
- }
+#ifndef _WIN32
+ u32 nonempty = 1;
+ struct dirent *data = readdir(z);
+ nonempty = (data != NULL);
+ if (!nonempty) return NULL;
+#endif
+ do
+ {
+#ifndef _WIN32
+ DIR *y;
+#endif
+ char *p;
+ u32 is_subdir;
+#ifndef _WIN32
+ if (data->d_name[0] == '.')
+#else
+ if (ffd.cFileName[0] == '.')
+#endif
+ continue;
- pointui startPixels = {my_Min(tmp.x, tmp.y), my_Max(tmp.x, tmp.y)};
- u32 lengthMove = startPixels.y - startPixels.x + 1;
- pointui editRange;
+#ifndef _WIN32
+ strncpy(buffer + n, data->d_name, MAX_PATH_LEN-n);
+ y = opendir(buffer);
+ is_subdir = (y != NULL);
+ if (y != NULL) closedir(y);
+#else
+ strncpy(buffer + n, ffd.cFileName, MAX_PATH_LEN-n);
+ is_subdir = ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
+#endif
- if (delta > 0)
- {
- editRange.x = startPixels.x;
- editRange.y = my_Max(finalPixels.x, finalPixels.y);
- }
- else
- {
- editRange.x = my_Min(finalPixels.x, finalPixels.y);
- editRange.y = startPixels.y;
+ if ((return_subdirs && is_subdir) || (!is_subdir && !return_subdirs))
+ {
+ if (!size)
+ {
+ results = (char**)calloc(sizeof(char*), capacity);
+ }
+ else if (size >= capacity)
+ {
+ void *old = results;
+ capacity = capacity * 2;
+ results = (char**)realloc(results, capacity * sizeof(char*));
+ Assert(results);
+ if (!results) free(old);
+ }
+#ifndef _WIN32
+ p = StrDuplicate(data->d_name);
+#else
+ p = StrDuplicate(ffd.cFileName);
+#endif
+ results[size++] = p;
+ }
+#ifndef _WIN32
+ } while ((data = readdir(z)) != NULL);
+#else
+ } while (FindNextFile(hFind, &ffd) != 0);
+#endif
}
- f32 ooNPixels = (f32)(1.0 / (f64)Number_of_Pixels_1D);
- point2f editRangeModel = {((f32)editRange.x * ooNPixels) - 0.5f, ((f32)editRange.y * ooNPixels) - 0.5f};
- f32 dRange = editRangeModel.y - editRangeModel.x;
+#ifndef _WIN32
+ if (z) closedir(z);
+#else
+ FindClose(hFind);
+#endif
+ *count = size;
+
+ CharArrayBubbleSort(results, (u32)size);
+
+ return results;
+}
- waypoint **searchBuffer = PushArray(Working_Set, waypoint*, Waypoints_Stack_Size);
- waypoint **bufferEnd = searchBuffer;
+global_function
+struct file_group
+FILE_GROUP(enum file_groups group, const char *name, struct nk_image *icon)
+{
+ struct file_group fg;
+ fg.group = group;
+ fg.name = name;
+ fg.icon = icon;
+ return fg;
+}
- GetWaypointsWithinRectange({editRangeModel.x, -0.5f}, {dRange, 0.999f}, &bufferEnd);
- GetWaypointsWithinRectange({-0.5f, editRangeModel.x}, {0.999f, dRange}, &bufferEnd
-#ifdef Internal
-, 0
-#endif
- );
+global_function
+struct file
+FILE_DEF(enum file_types type, const char *suffix, enum file_groups group)
+{
+ struct file fd;
+ fd.type = type;
+ fd.suffix = suffix;
+ fd.group = group;
+ return fd;
+}
- u32 nWayp = (u32)((my_Max((size_t)bufferEnd, (size_t)searchBuffer) - my_Min((size_t)bufferEnd, (size_t)searchBuffer)) / sizeof(searchBuffer));
- waypoint **seen = PushArray(Working_Set, waypoint*, nWayp);
- u32 seenIdx = 0;
+global_function
+struct nk_image*
+MediaIconForFile(struct media *media, const char *file)
+{
+ u32 i = 0;
+ const char *s = file;
+ char suffix[16];
+ u32 found = 0;
+ memset(suffix, 0, sizeof(suffix));
- for ( waypoint **waypPtr = searchBuffer;
- waypPtr != bufferEnd;
- ++waypPtr )
+ /* extract suffix .xxx from file */
+ while (*s++ != '\0')
{
- waypoint *wayp = *waypPtr;
- u32 newWayP = 1;
+ if (found && i < (sizeof(suffix)-1))
+ suffix[i++] = *s;
- ForLoop(seenIdx)
+ if (*s == '.')
{
- if (wayp == seen[index])
+ if (found)
{
- newWayP = 0;
+ found = 0;
break;
}
+ found = 1;
}
+ }
- if (newWayP)
+ /* check for all file definition of all groups for fitting suffix*/
+ for ( i = 0;
+ i < FILE_MAX && found;
+ ++i)
+ {
+ struct file *d = &media->files[i];
{
- point2f normCoords = {my_Min(wayp->coords.x, wayp->coords.y), my_Max(wayp->coords.x, wayp->coords.y)};
-
- u32 inXRange = normCoords.x >= editRangeModel.x && normCoords.x < editRangeModel.y;
- u32 inYRange = normCoords.y >= editRangeModel.x && normCoords.y < editRangeModel.y;
- u32 inRange = inXRange || inYRange;
-
- if (inRange)
+ const char *f = d->suffix;
+ s = suffix;
+ while (f && *f && *s && *s == *f)
{
- u32 upperTri = wayp->coords.x > wayp->coords.y;
-
- pointui pix = {(u32)((0.5f + wayp->coords.x) / ooNPixels), (u32)((0.5f + wayp->coords.y) / ooNPixels)};
-
- if (pix.x >= startPixels.x && pix.x < startPixels.y)
- {
- pix.x = (u32)((s32)pix.x + delta);
-
- if (edit->finalPix1 > edit->finalPix2)
- {
- pix.x = my_Max(finalPixels.x, finalPixels.y) - pix.x + my_Min(finalPixels.x, finalPixels.y);
- }
- }
- else if (pix.x >= editRange.x && pix.x < editRange.y)
- {
- pix.x = delta > 0 ? pix.x - lengthMove : pix.x + lengthMove;
- }
-
- if (pix.y >= startPixels.x && pix.y < startPixels.y)
- {
- pix.y = (u32)((s32)pix.y + delta);
-
- if (edit->finalPix1 > edit->finalPix2)
- {
- pix.y = my_Max(finalPixels.x, finalPixels.y) - pix.y + my_Min(finalPixels.x, finalPixels.y);
- }
- }
- else if (pix.y >= editRange.x && pix.y < editRange.y)
- {
- pix.y = delta > 0 ? pix.y - lengthMove : pix.y + lengthMove;
- }
-
- point2f newCoords = {((f32)pix.x * ooNPixels) - 0.5f, ((f32)pix.y * ooNPixels) - 0.5f};
-
- u32 upperTriNew = newCoords.x > newCoords.y;
- if (upperTriNew != upperTri)
- {
- newCoords = {newCoords.y, newCoords.x};
- }
-
- UpdateWayPoint(wayp, newCoords);
+ s++; f++;
}
- seen[seenIdx++] = wayp;
+ /* found correct file definition so */
+ if (f && *s == '\0' && *f == '\0')
+ return media->group[d->group].icon;
}
}
-
- FreeLastPush(Working_Set); // searchBuffer
- FreeLastPush(Working_Set); // seen
-}
+ return &media->icons.default_file;
+}
global_function
void
-GetWaypointsWithinRectange(waypoint_quadtree_level *level, point2f lowerBound, point2f size, waypoint ***bufferPtr)
+MediaInit(struct media *media)
{
- if (level->children[0])
- {
- u08 toSearch[4] = {1, 1, 1, 1};
-#define epsilon 0.001f
- ForLoop(4)
- {
- // bottom left
- waypoint_quadtree_level *child = level->children[index];
- point2f insertSize = {lowerBound.x - child->lowerBound.x, lowerBound.y - child->lowerBound.y};
- if (insertSize.x >= 0 && insertSize.x < child->size && insertSize.y >= 0 && insertSize.y < child->size)
- {
- point2f recSize = {my_Min(size.x, child->size - insertSize.x - epsilon), my_Min(size.y, child->size - insertSize.y - epsilon)};
- GetWaypointsWithinRectange(child, lowerBound, recSize, bufferPtr);
- toSearch[index] = 0;
- break;
- }
- }
- ForLoop(4)
- {
- if (toSearch[index])
- {
- // bottom right
- waypoint_quadtree_level *child = level->children[index];
- point2f insertSize = {lowerBound.x + size.x - child->lowerBound.x, lowerBound.y - child->lowerBound.y};
- if (insertSize.x >= 0 && insertSize.x < child->size && insertSize.y >= 0 && insertSize.y < child->size)
- {
- point2f recSize = {my_Min(size.x, insertSize.x), my_Min(size.y, child->size - insertSize.y - epsilon)};
- GetWaypointsWithinRectange(child, {child->lowerBound.x + insertSize.x - recSize.x, lowerBound.y}, recSize, bufferPtr);
- toSearch[index] = 0;
- break;
- }
- }
- }
- ForLoop(4)
- {
- if (toSearch[index])
- {
- // top left
- waypoint_quadtree_level *child = level->children[index];
- point2f insertSize = {lowerBound.x - child->lowerBound.x, lowerBound.y + size.y - child->lowerBound.y};
- if (insertSize.x >= 0 && insertSize.x < child->size && insertSize.y >= 0 && insertSize.y < child->size)
- {
- point2f recSize = {my_Min(size.x, child->size - insertSize.x - epsilon), my_Min(size.y, insertSize.y)};
- GetWaypointsWithinRectange(child, {lowerBound.x, child->lowerBound.y + insertSize.y - recSize.y}, recSize, bufferPtr);
- toSearch[index] = 0;
- break;
- }
- }
- }
- ForLoop(4)
- {
- if (toSearch[index])
- {
- // top right
- waypoint_quadtree_level *child = level->children[index];
- point2f insertSize = {lowerBound.x + size.x - child->lowerBound.x, lowerBound.y + size.y - child->lowerBound.y};
- if (insertSize.x >= 0 && insertSize.x < child->size && insertSize.y >= 0 && insertSize.y < child->size)
- {
- point2f recSize = {my_Min(size.x, insertSize.x), my_Min(size.y, insertSize.y)};
- GetWaypointsWithinRectange(child, {child->lowerBound.x + insertSize.x - recSize.x, child->lowerBound.y + insertSize.y - recSize.y}, recSize, bufferPtr);
-#ifdef Internal
- toSearch[index] = 0;
-#endif
- break;
- }
- }
- }
-
-#ifdef Internal
- ForLoop(4)
- {
- if (!toSearch[index]) level->children[index]->show = 1;
- }
-#endif
-
- }
- else
- {
- TraverseLinkedList(level->headNode.next, waypoint_quadtree_node)
- {
- **bufferPtr = node->wayp;
- ++(*bufferPtr);
- }
- }
+ /* file groups */
+ struct icons *icons = &media->icons;
+ media->group[FILE_GROUP_DEFAULT] = FILE_GROUP(FILE_GROUP_DEFAULT,"default",&icons->default_file);
+ media->group[FILE_GROUP_PRETEXT] = FILE_GROUP(FILE_GROUP_PRETEXT, "pretext", &icons->img_file);
+
+ /* files */
+ media->files[FILE_DEFAULT] = FILE_DEF(FILE_DEFAULT, NULL, FILE_GROUP_DEFAULT);
+ media->files[FILE_PRETEXT] = FILE_DEF(FILE_PRETEXT, "pretext", FILE_GROUP_PRETEXT);
+ media->files[FILE_PSTM] = FILE_DEF(FILE_PSTM, "pstm", FILE_GROUP_PRETEXT);
}
-#ifdef Internal
global_function
void
-TurnOffDrawingForQuadTreeLevel(waypoint_quadtree_level *level = 0)
+FileBrowserReloadDirectoryContent(struct file_browser *browser, const char *path)
{
- if (!level) level = Waypoint_Editor->quadtree;
- level->show = 0;
- ForLoop(4)
- {
- if (level->children[index]) TurnOffDrawingForQuadTreeLevel(level->children[index]);
+ // check if the path is valid, yes: run the load, no: set the path to the home directory
+ if (path && std::filesystem::exists(path) && std::filesystem::is_directory(path))
+ strncpy(browser->directory, path, MAX_PATH_LEN); // copy the path to the browser directory
+ else{
+ fmt::println("[FileBrowserReloadDirectoryContent::Warning]: Invalid path: {}, setting to home directory {}.", path, browser->home);
+ strncpy(browser->directory, browser->home, MAX_PATH_LEN); // if not valid, set the path to the home directory
}
+ DirFreeList(browser->files, browser->file_count);
+ DirFreeList(browser->directories, browser->dir_count);
+ browser->files = DirList(path, 0, &browser->file_count);
+ browser->directories = DirList(path, 1, &browser->dir_count);
+ UserSaveState(); // save the current directory to the user profile cache
}
-#endif
global_function
void
-GetWaypointsWithinSquare(point2f lowerBound, f32 size, waypoint ***bufferPtr
-#ifdef Internal
- , u32 reset = 1)
-#else
- )
-#endif
+FileBrowserInit(struct file_browser *browser, struct media *media)
{
-#ifdef Internal
- if (reset) TurnOffDrawingForQuadTreeLevel();
-#endif
- GetWaypointsWithinRectange(Waypoint_Editor->quadtree, lowerBound, {size, size}, bufferPtr);
-}
-
-global_function
-void
-GetWaypointsWithinRectange(point2f lowerBound, point2f size, waypoint ***bufferPtr
-#ifdef Internal
- , u32 reset)
+ memset(browser, 0, sizeof(*browser));
+ browser->media = media;
+ {
+ /* load files and sub-directory list */
+ const char *home = getenv("HOME");
+#ifdef _WIN32
+ if (!home) home = getenv("USERPROFILE");
#else
- )
+ if (!home) home = getpwuid(getuid())->pw_dir;
#endif
-{
-#ifdef Internal
- if (reset) TurnOffDrawingForQuadTreeLevel();
+ {
+ size_t l;
+ strncpy(browser->home, home, MAX_PATH_LEN);
+ l = strlen(browser->home);
+#ifdef _WIN32
+ char *sep = (char *)"\\";
+#else
+ char *sep = (char *)"/";
#endif
- GetWaypointsWithinRectange(Waypoint_Editor->quadtree, lowerBound, size, bufferPtr);
+ strcpy(browser->home + l, sep);
+ strcpy(browser->directory, browser->home);
+ }
+
+ browser->files = DirList(browser->directory, 0, &browser->file_count);
+ browser->directories = DirList(browser->directory, 1, &browser->dir_count);
+ }
}
+global_variable
+char
+Save_State_Name_Buffer[1024] = {0};
+
+global_variable
+char
+AGP_Name_Buffer[1024] = {0};
+
global_function
-waypoint_quadtree_level *
-GetWaypointQuadTreeLevel(point2f coords)
+void
+SetSaveStateNameBuffer(char *name)
{
- coords = {my_Max(my_Min(coords.x, 0.499f), -0.5f), my_Max(my_Min(coords.y, 0.499f), -0.5f)};
-
- waypoint_quadtree_level *level = Waypoint_Editor->quadtree;
-
- while (level->children[0])
+ u32 ptr = 0;
+ while (*name)
{
-#ifdef DEBUG
- u32 found = 0;
-#endif
- ForLoop(4)
- {
- point2f insertSize = {coords.x - level->children[index]->lowerBound.x, coords.y - level->children[index]->lowerBound.y};
- f32 size = level->children[index]->size;
- if (insertSize.x >= 0 && insertSize.x < size && insertSize.y >= 0 && insertSize.y < size)
- {
- level = level->children[index];
-
-#ifdef DEBUG
- found = 1;
-#endif
-
- break;
- }
- }
-
-#ifdef DEBUG
- if (!found)
- {
- Assert(found);
- }
-#endif
-
+ AGP_Name_Buffer[ptr] = *name;
+ Save_State_Name_Buffer[ptr++] = *name++;
}
+
+ u32 ptr1 = ptr;
+ name = (char *)".savestate_1";
+ while (*name) Save_State_Name_Buffer[ptr++] = *name++;
+ Save_State_Name_Buffer[ptr] = 0;
- return(level);
+ ptr = ptr1;
+ name = (char *)".agp_1";
+ while (*name) AGP_Name_Buffer[ptr++] = *name++;
+ AGP_Name_Buffer[ptr] = 0;
}
+
+/*
+@params:
+ - save 0 file open
+ 1 save state
+ 2 agp state
+*/
global_function
-void
-AddWayPoint(point2f coords)
+u08
+FileBrowserRun(const char *name, struct file_browser *browser, struct nk_context *ctx, u32 show, u08 save = 0)
{
- u32 nFree = Waypoints_Stack_Size - Waypoint_Editor->nWaypointsActive;
+#ifndef _WIN32
+ char pathSep = '/';
+#else
+ char pathSep = '\\';
+#endif
+
+ struct nk_window *window = nk_window_find(ctx, name);
+ u32 doesExist = window != 0;
- if (nFree)
+ if (!show && !doesExist)
{
- waypoint *wayp = Waypoint_Editor->freeWaypoints.next;
- Waypoint_Editor->freeWaypoints.next = wayp->next;
- if (Waypoint_Editor->freeWaypoints.next) Waypoint_Editor->freeWaypoints.next->prev = &Waypoint_Editor->freeWaypoints;
+ return(0);
+ }
- wayp->next = Waypoint_Editor->activeWaypoints.next;
- if (Waypoint_Editor->activeWaypoints.next) Waypoint_Editor->activeWaypoints.next->prev = wayp;
- Waypoint_Editor->activeWaypoints.next = wayp;
- wayp->prev = &Waypoint_Editor->activeWaypoints;
- wayp->index = wayp->next ? wayp->next->index + 1 : 0;
+ if (show && doesExist && (window->flags & NK_WINDOW_HIDDEN))
+ {
+ window->flags &= ~(nk_flags)NK_WINDOW_HIDDEN;
+ FileBrowserReloadDirectoryContent(browser, browser->directory);
+ }
- wayp->coords = coords;
- wayp->z = Camera_Position.z;
- ++Waypoint_Editor->nWaypointsActive;
+ u08 ret = 0;
+ struct media *media = browser->media;
+ struct nk_rect total_space;
- waypoint_quadtree_level *level = GetWaypointQuadTreeLevel(wayp->coords);
-
- waypoint_quadtree_node *node = Waypoint_Editor->freeNodes.next;
- if (node->next) node->next->prev = &Waypoint_Editor->freeNodes;
- Waypoint_Editor->freeNodes.next = node->next;
+ if (nk_begin(ctx, name, nk_rect(Screen_Scale.x * 50, Screen_Scale.y * 50, Screen_Scale.x * 800, Screen_Scale.y * 700),
+ NK_WINDOW_BORDER|NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_MOVABLE|NK_WINDOW_TITLE|NK_WINDOW_CLOSABLE))
+ {
+ static f32 ratio[] = {0.25f, NK_UNDEFINED};
+ f32 spacing_x = ctx->style.window.spacing.x;
+ nk_style_set_font(ctx, &NK_Font_Browser->handle);
- if (level->headNode.next) level->headNode.next->prev = node;
- node->next = level->headNode.next;
- node->prev = &level->headNode;
- level->headNode.next = node;
+ /* output path directory selector in the menubar */
+ ctx->style.window.spacing.x = 0;
+ nk_menubar_begin(ctx);
+ {
+ char *d = browser->directory;
+ char *begin = d + 1;
+ nk_layout_row_dynamic(ctx, Screen_Scale.y * 25.0f, 6);
+ while (*d++)
+ {
+ if (*d == pathSep)
+ {
+ *d = '\0';
+ if (nk_button_label(ctx, begin))
+ {
+ *d++ = pathSep; *d = '\0';
+ FileBrowserReloadDirectoryContent(browser, browser->directory);
+ break;
+ }
+ *d = pathSep;
+ begin = d + 1;
+ }
+ }
+ }
+ nk_menubar_end(ctx);
+ ctx->style.window.spacing.x = spacing_x;
- wayp->node = node;
- node->wayp = wayp;
- }
-}
+ /* window layout */
+ f32 endSpace = save ? 100.0f : 0; // Resolved: end space is clipped as the space is not enough
+ total_space = nk_window_get_content_region(ctx);
+ nk_layout_row(ctx, NK_DYNAMIC, total_space.h - endSpace, 2, ratio);
+ nk_group_begin(ctx, "Special", NK_WINDOW_NO_SCROLLBAR);
+ {
+ struct nk_image home = media->icons.home;
+ struct nk_image computer = media->icons.computer;
-global_function
-void
-RemoveWayPoint(waypoint *wayp)
-{
- switch (Waypoint_Editor->nWaypointsActive)
- {
- case 0:
- wayp = 0;
- break;
+ nk_layout_row_dynamic(ctx, Screen_Scale.y * 40.0f, 1);
+ if (nk_button_image_label(ctx, home, "home", NK_TEXT_CENTERED))
+ FileBrowserReloadDirectoryContent(browser, browser->home);
+ if (nk_button_image_label(ctx,computer,"computer",NK_TEXT_CENTERED))
+#ifndef _WIN32
+ FileBrowserReloadDirectoryContent(browser, "/");
+#else
+ FileBrowserReloadDirectoryContent(browser, "C:\\");
+#endif
+ nk_group_end(ctx);
+ }
- case 1:
- Waypoint_Editor->activeWaypoints.next = 0;
- Waypoint_Editor->nWaypointsActive = 0;
- break;
+ /* output directory content window */
+ nk_group_begin(ctx, "Content", 0);
+ {
+ /* define a string here for filtering */
+ std::string searchbuf_str="";
+ if (!save){ // only need this while loading something
+ nk_layout_row_dynamic(NK_Context, Screen_Scale.y * 25.0f, 3);
+ nk_label(NK_Context, "Search: ", NK_TEXT_LEFT);
+ nk_edit_string_zero_terminated(NK_Context, NK_EDIT_FIELD, searchbuf, sizeof(searchbuf) - 1, nk_filter_default);
+ caseSensitive_search_sequences = nk_check_label(NK_Context, "Case Sensitive", caseSensitive_search_sequences) ? 1 : 0;
+ searchbuf_str = std::string(searchbuf);
+ if (!caseSensitive_search_sequences) std::transform(searchbuf_str.begin(), searchbuf_str.end(), searchbuf_str.begin(), ::tolower);
+ }
+
+ s32 index = -1;
+ size_t i = 0, j = 0;//, k = 0;
+ size_t rows = 0, cols = 0;
+ size_t count = browser->dir_count + browser->file_count;
+ f32 iconRatio[] = {0.05f, NK_UNDEFINED};
- default:
- if (wayp->next) wayp->next->prev = wayp->prev;
- if (wayp->prev) wayp->prev->next = wayp->next;
- --Waypoint_Editor->nWaypointsActive;
- }
+ cols = 1;
+ rows = count / cols;
+ for ( i = 0;
+ i <= rows;
+ i += 1)
+ {
+ size_t n = j + cols;
+ // nk_layout_row(ctx, NK_DYNAMIC, Screen_Scale.y * 25.0f, 2, iconRatio);
+ for ( ;
+ j < count && j < n;
+ ++j)
+ {
+ /* draw one row of icons */
+ if (j < browser->dir_count)
+ {
+ if (!searchbuf_str.empty()){
+ std::string dir_str = browser->directories[j];
+ if (!caseSensitive_search_sequences) std::transform(dir_str.begin(), dir_str.end(), dir_str.begin(), ::tolower);
+ if (dir_str.find(searchbuf_str) == std::string::npos) continue; // not found
+ }
+ /* draw and execute directory buttons */
+ if (j == n - cols) nk_layout_row(ctx, NK_DYNAMIC, Screen_Scale.y * 25.0f, 2, iconRatio);
+ if (nk_button_image(ctx,media->icons.directory)) index = (s32)j;
+ nk_label(ctx, browser->directories[j], NK_TEXT_LEFT);
+ }
+ else
+ {
+ /* draw and execute files buttons */
+ struct nk_image *icon;
+ size_t fileIndex = ((size_t)j - browser->dir_count);
+ if (!searchbuf_str.empty()){
+ std::string dir_str = browser->files[fileIndex];
+ if (!caseSensitive_search_sequences) std::transform(dir_str.begin(), dir_str.end(), dir_str.begin(), ::tolower);
+ if (dir_str.find(searchbuf_str) == std::string::npos) continue; // not found
+ }
+ if (j == n - cols) nk_layout_row(ctx, NK_DYNAMIC, Screen_Scale.y * 25.0f, 2, iconRatio);
+ icon = MediaIconForFile(media,browser->files[fileIndex]);
+ if (nk_button_image(ctx, *icon))
+ {
+ if (save)
+ {
+ strncpy(save == 2 ? AGP_Name_Buffer : Save_State_Name_Buffer, browser->files[fileIndex], sizeof(save == 2 ? AGP_Name_Buffer : Save_State_Name_Buffer));
+ }
+ else
+ {
+ strncpy(browser->file, browser->directory, MAX_PATH_LEN);
+ n = strlen(browser->file);
+ strncpy(browser->file + n, browser->files[fileIndex], MAX_PATH_LEN - n);
+ ret = 1;
+ }
+ }
+ nk_label(ctx,browser->files[fileIndex],NK_TEXT_LEFT);
+ }
+ }
+ }
- if (wayp)
- {
- wayp->next = Waypoint_Editor->freeWaypoints.next;
- if (Waypoint_Editor->freeWaypoints.next) Waypoint_Editor->freeWaypoints.next->prev = wayp;
- Waypoint_Editor->freeWaypoints.next = wayp;
- wayp->prev = &Waypoint_Editor->freeWaypoints;
+ if (index != -1)
+ {
+ size_t n = strlen(browser->directory);
+ strncpy(browser->directory + n, browser->directories[index], MAX_PATH_LEN - n);
+ n = strlen(browser->directory);
+ if (n < MAX_PATH_LEN - 1)
+ {
+ browser->directory[n] = pathSep;
+ browser->directory[n+1] = '\0';
+ }
+ FileBrowserReloadDirectoryContent(browser, browser->directory);
+ }
+
+ nk_group_end(ctx);
+ }
- waypoint_quadtree_node *node = wayp->node;
+ if (save)
+ {
+ Deferred_Close_UI = 0;
- if (node->next) node->next->prev = node->prev;
- if (node->prev) node->prev->next = node->next;
- node->prev = 0;
+ nk_layout_row(ctx, NK_DYNAMIC, endSpace - 5.0f, 1, ratio + 1);
+ nk_group_begin(ctx, "File", NK_WINDOW_NO_SCROLLBAR);
+ {
+ f32 fileRatio[] = {0.8f, 0.1f, NK_UNDEFINED};
+ f32 fileRatio2[] = {0.45f, 0.1f, 0.18f, 0.17f, NK_UNDEFINED};
+ nk_layout_row(ctx, NK_DYNAMIC, Screen_Scale.y * 35.0f, save == 2 ? 5 : 3, save == 2 ? fileRatio2 : fileRatio);
- if (Waypoint_Editor->freeNodes.next) Waypoint_Editor->freeNodes.next->prev = node;
- node->next = Waypoint_Editor->freeNodes.next;
- Waypoint_Editor->freeNodes.next = node;
- node->prev = &Waypoint_Editor->freeNodes;
+ u08 saveViaEnter = (nk_edit_string_zero_terminated(ctx, NK_EDIT_FIELD | NK_EDIT_SIG_ENTER, save == 2 ? AGP_Name_Buffer : Save_State_Name_Buffer, sizeof(save == 2 ? AGP_Name_Buffer : Save_State_Name_Buffer), 0) & NK_EDIT_COMMITED) ? 1 : 0;
+
+ static u08 overwrite = 0;
+ overwrite = (u08)nk_check_label(ctx, "Override", overwrite);
+
+ static u08 singletons = 0;
+ if (save == 2) singletons = (u08)nk_check_label(ctx, "Format Singletons", singletons);
+ static u08 preserveOrder = 0;
+ if (save == 2) preserveOrder = (u08)nk_check_label(ctx, "Preserve Order", preserveOrder);
+
+ if (nk_button_label(ctx, "Save") || saveViaEnter)
+ {
+ strncpy(browser->file, browser->directory, MAX_PATH_LEN);
+ size_t n = strlen(browser->file);
+ strncpy(browser->file + n, save == 2 ? AGP_Name_Buffer : Save_State_Name_Buffer, MAX_PATH_LEN - n);
+ ret = 1 | (overwrite ? 2 : 0) | (singletons ? 4 : 0) | (preserveOrder ? 8 : 0);
+ }
+
+ nk_group_end(ctx);
+ }
+ }
+
+ nk_style_set_font(ctx, &NK_Font->handle);
}
+ nk_end(ctx);
+
+ return(ret);
}
global_function
void
-UpdateWayPoint(waypoint *wayp, point2f coords)
+MetaTagsEditorRun(struct nk_context *ctx, u08 show)
{
- waypoint_quadtree_node *node = wayp->node;
+ const char *name = "Meta Data Tag Editor";
+ struct nk_window *window = nk_window_find(ctx, name);
- if (node->next) node->next->prev = node->prev;
- if (node->prev) node->prev->next = node->next;
- node->prev = 0;
+ u08 doesExist = window != 0;
+ if (!show && !doesExist) return;
+ if (show && doesExist && (window->flags & NK_WINDOW_HIDDEN)) window->flags &= ~(nk_flags)NK_WINDOW_HIDDEN;
- wayp->coords = coords;
+ if (nk_begin(ctx, name, nk_rect(Screen_Scale.x * 50, Screen_Scale.y * 50, Screen_Scale.x * 800, Screen_Scale.y * 600),
+ NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE|NK_WINDOW_NO_SCROLLBAR))
+ {
+ Deferred_Close_UI = 0;
- waypoint_quadtree_level *level = GetWaypointQuadTreeLevel(wayp->coords);
+ struct nk_rect total_space = nk_window_get_content_region(ctx);
+ f32 ratio[] = {0.05f, NK_UNDEFINED};
+ nk_layout_row(ctx, NK_DYNAMIC, total_space.h, 1, ratio + 1);
- if (level->headNode.next) level->headNode.next->prev = node;
- node->next = level->headNode.next;
- node->prev = &level->headNode;
- level->headNode.next = node;
+ nk_group_begin(ctx, "Content", 0);
+ {
+ nk_layout_row(ctx, NK_DYNAMIC, Screen_Scale.y * 35.0f, 2, ratio);
- wayp->node = node;
- node->wayp = wayp;
+ ForLoop(ArrayCount(Meta_Data->tags))
+ {
+ char buff[4];
+ stbsp_snprintf(buff, sizeof(buff), "%u:", index + 1);
+ nk_label(ctx, buff, NK_TEXT_LEFT);
+ if (nk_edit_string_zero_terminated(ctx, NK_EDIT_FIELD, (char *)Meta_Data->tags[index], sizeof(Meta_Data->tags[index]), 0) & NK_EDIT_ACTIVE)
+ {
+ if (!strlen((const char *)Meta_Data->tags[index]))
+ {
+ ForLoop2(Number_of_Pixels_1D) Map_State->metaDataFlags[index2] &= ~(1 << index);
+ u32 nextActive = index;
+ ForLoop2((ArrayCount(Meta_Data->tags) - 1))
+ {
+ if (++nextActive == ArrayCount(Meta_Data->tags)) nextActive = 0;
+ if (strlen((const char *)Meta_Data->tags[nextActive]))
+ {
+ MetaData_Active_Tag = nextActive;
+ break;
+ }
+ }
+ }
+ else if (!strlen((const char *)Meta_Data->tags[MetaData_Active_Tag])) MetaData_Active_Tag = index;
+ }
+ }
+
+ nk_group_end(ctx);
+ }
+ }
+ nk_end(ctx);
}
global_function
void
-MouseMove(GLFWwindow* window, f64 x, f64 y)
+AboutWindowRun(struct nk_context *ctx, u32 show)
{
- if (Loading || auto_sort_state || auto_cut_state)
+ struct nk_window *window = nk_window_find(ctx, "About");
+ u32 doesExist = window != 0;
+
+ if (!show && !doesExist)
{
return;
}
- (void)window;
-
- u32 redisplay = 0;
-
- if (UI_On)
+ if (show && doesExist && (window->flags & NK_WINDOW_HIDDEN))
{
+ window->flags &= ~(nk_flags)NK_WINDOW_HIDDEN;
}
- else // ui_on == false
- {
- if (Edit_Mode)
- {
- static s32 netDelta = 0;
- s32 w, h;
- glfwGetWindowSize(window, &w, &h);
- f32 height = (f32)h;
- f32 width = (f32)w;
-
- f32 factor1 = 1.0f / (2.0f * Camera_Position.z);
- f32 factor2 = 2.0f / height;
- f32 factor3 = width * 0.5f;
+ enum windowMode {showAcknowledgements, showLicence, showThirdParty};
- f32 wx = (factor1 * factor2 * ((f32)x - factor3)) + Camera_Position.x;
- f32 wy = (-factor1 * (1.0f - (factor2 * (f32)y))) - Camera_Position.y;
+ static windowMode mode = showAcknowledgements;
- wx = my_Max(-0.5f, my_Min(0.5f, wx));
- wy = my_Max(-0.5f, my_Min(0.5f, wy));
+ if (nk_begin_titled(ctx, "About", PretextView_Version, nk_rect(Screen_Scale.x * 50, Screen_Scale.y * 50, Screen_Scale.x * 870, Screen_Scale.y * 610),
+ NK_WINDOW_BORDER|NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_MOVABLE|NK_WINDOW_TITLE|NK_WINDOW_CLOSABLE))
+ {
+ nk_menubar_begin(ctx);
+ {
+ nk_layout_row_dynamic(ctx, Screen_Scale.y * 35.0f, 3);
+ if (nk_button_label(ctx, "Acknowledgements"))
+ {
+ mode = showAcknowledgements;
+ }
+ if (nk_button_label(ctx, "Licence"))
+ {
+ mode = showLicence;
+ }
+ if (nk_button_label(ctx, "Third Party Software"))
+ {
+ mode = showThirdParty;
+ }
+ }
+ nk_menubar_end(ctx);
- u32 nPixels = Number_of_Pixels_1D;
+ struct nk_rect total_space = nk_window_get_content_region(ctx);
+ f32 one = NK_UNDEFINED;
+ nk_layout_row(ctx, NK_DYNAMIC, total_space.h, 1, &one);
- u32 pixel1 = (u32)((f64)nPixels * (0.5 + (f64)wx));
- u32 pixel2 = (u32)((f64)nPixels * (0.5 + (f64)wy));
-
- // 防止在尾部溢出
- pixel1 = my_Max(0, my_Min(nPixels - 1, pixel1));
- pixel2 = my_Max(0, my_Min(nPixels - 1, pixel2));
+ nk_group_begin(ctx, "About_Content", 0);
+ {
+ if (mode == showThirdParty)
+ {
+ u08 text[] = R"text(PretextView was made possible thanks to the following third party libraries and
+resources, click each entry to view its licence.)text";
- u32 contig = Map_State->contigIds[pixel1];
+ nk_layout_row_static(ctx, Screen_Scale.y * 60, (s32)(Screen_Scale.x * 820), 1);
+ s32 len = sizeof(text);
+ nk_edit_string(ctx, NK_EDIT_READ_ONLY | NK_EDIT_NO_CURSOR | NK_EDIT_SELECTABLE | NK_EDIT_MULTILINE, (char *)text, &len, len, 0);
- if (!Edit_Pixels.editing && !Edit_Pixels.selecting && Map_State->contigIds[pixel2] != contig)
- {
- u32 testPixel = pixel1;
- u32 testContig = contig;
- while (testContig == contig) // move testContig to the 1 before the first or 1 after the last pixel of the contig
+ ForLoop(Number_of_ThirdParties)
{
+ u32 nameIndex = 2 * index;
+ u32 licenceIndex = nameIndex + 1;
+ s32 *sizes = ThirdParty_Licence_Sizes[index];
- if (pixel1 < pixel2)
- {
- testPixel ++ ;
- }
- else
+ if (nk_tree_push_id(NK_Context, NK_TREE_TAB, (const char *)ThirdParty[nameIndex], NK_MINIMIZED, (s32)index))
{
- testPixel -- ;
+ nk_layout_row_static(ctx, Screen_Scale.y * (f32)sizes[0], (s32)(Screen_Scale.x * (f32)sizes[1]), 1);
+ len = (s32)StringLength(ThirdParty[licenceIndex]);
+ nk_edit_string(ctx, NK_EDIT_READ_ONLY | NK_EDIT_NO_CURSOR | NK_EDIT_SELECTABLE | NK_EDIT_MULTILINE, (char *)ThirdParty[licenceIndex], &len, len, 0);
+ nk_tree_pop(NK_Context);
}
-
- testContig = Map_State->contigIds[testPixel];
-
- if (testPixel == 0 || testPixel >= (nPixels - 1)) break;
-
- // testContig = pixel1 < pixel2 ? Map_State->contigIds[++testPixel] : Map_State->contigIds[--testPixel];
- // if (testPixel == 0 || testPixel >= (nPixels - 1)) break;
- }
- if (Map_State->contigIds[testPixel] == contig)
- {
- pixel2 = testPixel;
- }
- else
- {
- pixel2 = pixel1 < pixel2 ? testPixel - 1 : testPixel + 1;
}
}
-
-
- if (Edit_Pixels.selecting) // select the contig
+ else if (mode == showAcknowledgements)
{
- Edit_Pixels.selectPixels.x = my_Max(pixel1, my_Max(Edit_Pixels.selectPixels.x, Edit_Pixels.selectPixels.y)); // used to select multiple contigs with pressing space and dragging the mouse
- // Edit_Pixels.selectPixels.x = pixel1;
- while( Edit_Pixels.selectPixels.x < (Number_of_Pixels_1D - 1) &&
- ((Edit_Pixels.scaffSelecting && Map_State->scaffIds[Edit_Pixels.selectPixels.x] && Map_State->scaffIds[Edit_Pixels.selectPixels.x] == Map_State->scaffIds[1 + Edit_Pixels.selectPixels.x] ) ||
- Map_State->contigIds[Edit_Pixels.selectPixels.x] == Map_State->contigIds[1 + Edit_Pixels.selectPixels.x]))
- {
- ++Edit_Pixels.selectPixels.x;
- }
+ nk_layout_row_static(ctx, Screen_Scale.y * 500, (s32)(Screen_Scale.x * 820), 1);
+ s32 len = sizeof(Acknowledgements);
+ nk_edit_string(ctx, NK_EDIT_READ_ONLY | NK_EDIT_NO_CURSOR | NK_EDIT_SELECTABLE | NK_EDIT_MULTILINE, (char *)Acknowledgements, &len, len, 0);
+ }
+ else
+ {
+ nk_layout_row_static(ctx, Screen_Scale.y * 500, (s32)(Screen_Scale.x * 820), 1);
+ s32 len = sizeof(Licence);
+ nk_edit_string(ctx, NK_EDIT_READ_ONLY | NK_EDIT_NO_CURSOR | NK_EDIT_SELECTABLE | NK_EDIT_MULTILINE, (char *)Licence, &len, len, 0);
+ }
+
+ nk_group_end(ctx);
+ }
+ }
- Edit_Pixels.selectPixels.y = my_Min(pixel1, my_Min(Edit_Pixels.selectPixels.x, Edit_Pixels.selectPixels.y));
- // Edit_Pixels.selectPixels.y = pixel1;
- while( Edit_Pixels.selectPixels.y > 0 &&
- ((Edit_Pixels.scaffSelecting && Map_State->scaffIds[Edit_Pixels.selectPixels.y] && Map_State->scaffIds[Edit_Pixels.selectPixels.y] == Map_State->scaffIds[Edit_Pixels.selectPixels.y - 1]) || Map_State->contigIds[Edit_Pixels.selectPixels.y] == Map_State->contigIds[Edit_Pixels.selectPixels.y - 1]))
- {
- --Edit_Pixels.selectPixels.y;
- }
+ nk_end(ctx);
+}
- pixel1 = Edit_Pixels.selectPixels.x;
- pixel2 = Edit_Pixels.selectPixels.y;
- }
- if (Edit_Pixels.editing)
- {
- u32 midPixel = (pixel1 + pixel2) >> 1;
- u32 oldMidPixel = (Edit_Pixels.pixels.x + Edit_Pixels.pixels.y) >> 1;
- s32 diff = (s32)midPixel - (s32)oldMidPixel;
+global_function
+void
+UpdateContigsFromMapState() // reading 从map的状态更新contigs
+{
+ u32 lastScaffID = Map_State->scaffIds[0]; // 第一个scaff的编号
+ u32 scaffId = lastScaffID ? 1 : 0; //
+ u32 lastId_original_contig = Map_State->originalContigIds[0]; // 第一个像素点对应的id
+ u32 lastCoord = Map_State->contigRelCoords[0]; // 第一个像素点的局部坐标
+ u32 contigPtr = 0;
+ u32 length = 0;
+ u32 startCoord = lastCoord;
+ u08 inverted = Map_State->contigRelCoords[1] < lastCoord; // 判断是不是反转的
+ Map_State->contigIds[0] = 0;
+
+ u32 pixelIdx = 0;
+ ForLoop(Number_of_Original_Contigs) (Original_Contigs + index)->nContigs = 0; // 将每一个contig的 片段数目 置为零
+ ForLoop(Number_of_Pixels_1D - 1) // 遍历每一个像素点 更新 Original_Contigs, Contigs
+ // 遍历完之后,contigPtr为214,但是Number_of_Original_Contigs = 218
+ {
+ if (contigPtr >= Max_Number_of_Contigs) break; // 确保 contigPtr 不超出最大contig的数值
- u32 forward = diff > 0;
-
- s32 newX = (s32)Edit_Pixels.pixels.x + diff;
- newX = my_Max(0, my_Min((s32)nPixels - 1, newX));
- s32 newY = (s32)Edit_Pixels.pixels.y + diff;
- newY = my_Max(0, my_Min((s32)nPixels - 1, newY));
+ ++length; // current fragment length
- s32 diffx = newX - (s32)Edit_Pixels.pixels.x;
- s32 diffy = newY - (s32)Edit_Pixels.pixels.y;
+ pixelIdx = index + 1; // 像素点编号, 加一因为第一个已经用来初始化了
+ u32 original_contig_id = Map_State->originalContigIds[pixelIdx]; // 像素点的 original contig id, 这里 不使用 % Max_Number_of_Contigs的值是为了区分后面cut之后的片段
+ u32 coord = Map_State->contigRelCoords[pixelIdx]; // 像素点的局部坐标
+
+ if (
+ original_contig_id != lastId_original_contig ||
+ (inverted && coord != (lastCoord - 1)) ||
+ (!inverted && coord != (lastCoord + 1))
+ ) // not a continuous fragment
+ {
+ Original_Contigs[lastId_original_contig % Max_Number_of_Contigs].contigMapPixels[Original_Contigs[lastId_original_contig % Max_Number_of_Contigs].nContigs] = pixelIdx - 1 - (length >> 1); // update Original_Contigs: contigMapPixels
+ Original_Contigs[lastId_original_contig % Max_Number_of_Contigs].nContigs++; // update Original_Contigs: nContigs, contigMapPixels
- diff = forward ? my_Min(diffx, diffy) : my_Max(diffx, diffy);
-
- //newX = (s32)Edit_Pixels.pixels.x + diff;
- //newY = (s32)Edit_Pixels.pixels.y + diff;
-
- diff = RearrangeMap(Edit_Pixels.pixels.x, Edit_Pixels.pixels.y, diff, Edit_Pixels.snap);
- netDelta += diff;
+ contig *last_cont = Contigs->contigs_arr + contigPtr; // 获取上一个contig的指针, 并且给contigPtr + 1
+ contigPtr++;
+ last_cont->originalContigId = lastId_original_contig; // 更新这个片段的id
+ last_cont->length = length; // 更新长度
+ last_cont->startCoord = startCoord; // 更新开头为当前片段在该contig上的局部坐标 endCoord = startCoord + length - 1
+ last_cont->metaDataFlags = Map_State->metaDataFlags + pixelIdx - 1; // Finished (shaoheng): memory problem: assign the pointer to the cont->metaDataFlags, the original is nullptr, the let this ptr point to the last pixel of the contig
- newX = (s32)Edit_Pixels.pixels.x + diff;
- newY = (s32)Edit_Pixels.pixels.y + diff;
-
- Edit_Pixels.pixels.x = (u32)newX;
- Edit_Pixels.pixels.y = (u32)newY;
+ u32 thisScaffID = Map_State->scaffIds[pixelIdx - 1]; // 上一个像素点对应的 scaffid
+ last_cont->scaffId = thisScaffID ? ((thisScaffID == lastScaffID) ? (scaffId) : (++scaffId)) : 0; // 如果存在scaffid则(判断是不是同一个scaff,如果是则继续用scaffid,否则++scaffid),否则为0
+ lastScaffID = thisScaffID; // 更新
- Edit_Pixels.worldCoords.x = (f32)(((f64)((2 * Edit_Pixels.pixels.x) + 1)) / ((f64)(2 * nPixels))) - 0.5f;
- Edit_Pixels.worldCoords.y = (f32)(((f64)((2 * Edit_Pixels.pixels.y) + 1)) / ((f64)(2 * nPixels))) - 0.5f;
- }
- else // edit_pixels.editing == 0
- {
- if (netDelta || Global_Edit_Invert_Flag)
- {
- AddMapEdit(netDelta, Edit_Pixels.pixels, Global_Edit_Invert_Flag);
- netDelta = 0;
- }
-
- wx = (f32)(((f64)((2 * pixel1) + 1)) / ((f64)(2 * nPixels))) - 0.5f;
- wy = (f32)(((f64)((2 * pixel2) + 1)) / ((f64)(2 * nPixels))) - 0.5f;
- Edit_Pixels.pixels.x = pixel1;
- Edit_Pixels.pixels.y = pixel2;
- Edit_Pixels.worldCoords.x = wx;
- Edit_Pixels.worldCoords.y = wy;
-
- Global_Edit_Invert_Flag = 0;
+ // 余数表示8数的第几位,如果未反向则对应位为0,若反向则对应位为1
+ if (IsContigInverted(contigPtr - 1)) // 判断上一个contig是否反向
+ { // 位操作更新contigflag
+ // 每8个片段的正反采用一个u08表示,每一个bit表示一个正反,余数表示这八个中的第几个,如果没有反向则对应位为0
+ if (!inverted) Contigs->contigInvertFlags[(contigPtr - 1) >> 3] &= ~(1 << ((contigPtr - 1) & 7));
+ }
+ else
+ { // 如果反向则额对应位的bit为1
+ if (inverted) Contigs->contigInvertFlags[(contigPtr - 1) >> 3] |= (1 << ((contigPtr - 1) & 7)); // 如果反向
}
- redisplay = 1;
+ startCoord = coord; // 当前片段开始的坐标
+ length = 0; // 当前片段长度清零0
+ if (pixelIdx < (Number_of_Pixels_1D - 1)) inverted = Map_State->contigRelCoords[pixelIdx + 1] < coord; // 更新inverted
}
- else if (
- Tool_Tip->on ||
- Waypoint_Edit_Mode ||
- Scaff_Edit_Mode ||
- MetaData_Edit_Mode ||
- Select_Sort_Area_Mode)
- {
- s32 w, h;
- glfwGetWindowSize(window, &w, &h);
- f32 height = (f32)h;
- f32 width = (f32)w;
+ // 更新上一个id和局部坐标
+ Map_State->contigIds[pixelIdx] = (u32)contigPtr; // 像素点对应的 片段id 修改为当前的统计得到片段id
+ lastId_original_contig = original_contig_id; // 更新上一个像素点的id
+ lastCoord = coord; // 更新上一个像素点的局部坐标
+ }
- f32 factor1 = 1.0f / (2.0f * Camera_Position.z);
- f32 factor2 = 2.0f / height;
- f32 factor3 = width * 0.5f;
+ if (contigPtr < Max_Number_of_Contigs) // contigptr 小于 Number_of_Original_Contigs
+ // 更新最后一个contig的最后一个片段信息
+ {
+ (Original_Contigs + lastId_original_contig % Max_Number_of_Contigs)->contigMapPixels[(Original_Contigs + lastId_original_contig % Max_Number_of_Contigs)->nContigs++] = pixelIdx - 1 - (length >> 1);
- f32 wx = (factor1 * factor2 * ((f32)x - factor3)) + Camera_Position.x;
- f32 wy = (-factor1 * (1.0f - (factor2 * (f32)y))) - Camera_Position.y;
+ ++length;
+ contig *cont = Contigs->contigs_arr + contigPtr++;
+ cont->originalContigId = lastId_original_contig;
+ cont->length = length;
+ cont->startCoord = startCoord;
+ cont->metaDataFlags = Map_State->metaDataFlags + pixelIdx - 1;
+
+ u32 thisScaffID = Map_State->scaffIds[pixelIdx];
+ cont->scaffId = thisScaffID ? ((thisScaffID == lastScaffID) ? (scaffId) : (++scaffId)) : 0;
+
+ if (IsContigInverted(contigPtr - 1))
+ {
+ if (!inverted) Contigs->contigInvertFlags[(contigPtr - 1) >> 3] &= ~(1 << ((contigPtr - 1) & 7));
+ }
+ else
+ {
+ if (inverted) Contigs->contigInvertFlags[(contigPtr - 1) >> 3] |= (1 << ((contigPtr - 1) & 7));
+ }
+ }
- wx = my_Max(-0.5f, my_Min(0.5f, wx));
- wy = my_Max(-0.5f, my_Min(0.5f, wy));
-
- u32 nPixels = Number_of_Textures_1D * Texture_Resolution;
-
- u32 pixel1 = my_Min((u32)((f64)nPixels * (0.5 + (f64)wx)), (nPixels - 1));
- u32 pixel2 = my_Min((u32)((f64)nPixels * (0.5 + (f64)wy)), (nPixels - 1));
+ Contigs->numberOfContigs = contigPtr;
+}
- Tool_Tip_Move.pixels.x = pixel1;
- Tool_Tip_Move.pixels.y = pixel2;
- Tool_Tip_Move.worldCoords.x = wx;
- Tool_Tip_Move.worldCoords.y = wy;
+global_function
+void
+AddMapEdit(s32 delta, pointui finalPixels, u32 invert);
- if (Waypoint_Edit_Mode)
- {
- Selected_Waypoint = 0;
- f32 selectDis = Waypoint_Select_Distance / (height * Camera_Position.z);
- f32 closestDistanceSq = selectDis * selectDis;
+global_function
+void
+RebuildContig(u32 pixel)
+{
+ for (;;)
+ {
+ u32 contigId = Map_State->contigIds[pixel];
+ u32 origContigId = Map_State->get_original_contig_id(pixel);
- waypoint **searchBuffer = PushArray(Working_Set, waypoint*, Waypoints_Stack_Size);
- waypoint **bufferEnd = searchBuffer;
- GetWaypointsWithinSquare( // add waypoints within the square to the buffer
- {Tool_Tip_Move.worldCoords.x - selectDis, Tool_Tip_Move.worldCoords.y - selectDis},
- 2.0f * selectDis,
- &bufferEnd);
- for ( waypoint **waypPtr = searchBuffer;
- waypPtr != bufferEnd;
- ++waypPtr ) { // make sure select the closest waypoint to the mouse
- waypoint *wayp = *waypPtr;
+ u32 top = (u32)pixel;
+ while (top && (Map_State->contigIds[top - 1] == contigId)) --top;
- f32 dx = Tool_Tip_Move.worldCoords.x - wayp->coords.x;
- f32 dy = Tool_Tip_Move.worldCoords.y - wayp->coords.y;
- f32 disSq = (dx * dx) + (dy * dy);
+ u32 bottom = pixel;
+ while ((bottom < (Number_of_Pixels_1D - 1)) && (Map_State->contigIds[bottom + 1] == contigId)) ++bottom;
- if (disSq < closestDistanceSq)
- {
- closestDistanceSq = disSq;
- Selected_Waypoint = wayp;
- }
- }
+ if (IsContigInverted(contigId))
+ {
+ InvertMap(top, bottom);
+ AddMapEdit(0, {top, bottom}, 1);
+ continue;
+ }
- FreeLastPush(Working_Set); // searchBuffer
+ u08 fragmented = 0;
+ ForLoop(Number_of_Pixels_1D)
+ {
+ if ((Map_State->contigIds[index] != contigId) && (Map_State->get_original_contig_id(index) == origContigId))
+ {
+ fragmented = 1;
+ break;
}
- else if (Scaff_Edit_Mode && Scaff_Painting_Flag)
+ }
+
+ if (fragmented)
+ {
+ u32 contigTopCoord = Map_State->contigRelCoords[top];
+ if (contigTopCoord)
{
- if (Scaff_Painting_Flag == 1)
+ u32 otherPixel = 0;
+ ForLoop(Number_of_Pixels_1D)
{
- if (!Scaff_Painting_Id)
+ if ((Map_State->get_original_contig_id(index) == origContigId) && (Map_State->contigRelCoords[index] == (contigTopCoord - 1)))
{
- if (Map_State->scaffIds[Tool_Tip_Move.pixels.x])
- {
- Scaff_Painting_Id = Map_State->scaffIds[Tool_Tip_Move.pixels.x];
- }
- else
- {
- u32 max = 0;
- ForLoop(Number_of_Pixels_1D) max = my_Max(max, Map_State->scaffIds[index]);
- Scaff_Painting_Id = max + 1;
- }
+ otherPixel = index;
+ break;
}
}
- else Scaff_Painting_Id = 0;
- if (Map_State->scaffIds[Tool_Tip_Move.pixels.x] != Scaff_Painting_Id || (Scaff_FF_Flag & 1))
- {
- u32 pixel = Tool_Tip_Move.pixels.x;
+ u08 invert = !otherPixel || (Map_State->contigIds[otherPixel - 1] != Map_State->contigIds[otherPixel]);
+ u32 otherPixel2 = otherPixel;
- u32 currScaffId = Map_State->scaffIds[pixel];
- u32 contigId = Map_State->contigIds[pixel];
- Map_State->scaffIds[pixel] = Scaff_Painting_Id;
+ if (invert)
+ {
+ while ((otherPixel < (Number_of_Pixels_1D - 1)) && (Map_State->contigIds[otherPixel + 1] == Map_State->contigIds[otherPixel2])) ++otherPixel;
+ }
+ else
+ {
+ while (otherPixel2 && (Map_State->contigIds[otherPixel2 - 1] == Map_State->contigIds[otherPixel])) --otherPixel2;
+ }
- // set the pixels with same contig_id into the same scaff
- u32 testPixel = pixel;
- while (testPixel && (Map_State->contigIds[testPixel - 1] == contigId)) Map_State->scaffIds[--testPixel] = Scaff_Painting_Id;
- testPixel = pixel;
- while ((testPixel < (Number_of_Pixels_1D - 1)) && (Map_State->contigIds[testPixel + 1] == contigId)) Map_State->scaffIds[++testPixel] = Scaff_Painting_Id;
+ s32 delta = (s32)top - (s32)otherPixel;
+ if (delta > 0) --delta;
+ else delta = (s32)top - (s32)otherPixel2;
+ pointui finalPixels = {(u32)((s32)otherPixel2 + delta), (u32)((s32)otherPixel + delta)};
+ RearrangeMap(otherPixel2, otherPixel, delta);
+ if (invert) InvertMap(finalPixels.x, finalPixels.y);
+ AddMapEdit(delta, finalPixels, invert);
+ }
+ else
+ {
+ u32 contigBottomCoord = Map_State->contigRelCoords[bottom];
- if (Scaff_FF_Flag & 1)
+ u32 otherPixel = 0;
+ ForLoop(Number_of_Pixels_1D)
+ {
+ if ((Map_State->get_original_contig_id(index) == origContigId) && (Map_State->contigRelCoords[index] == (contigBottomCoord + 1)))
{
- ++testPixel;
- while ((testPixel < Number_of_Pixels_1D) && ((Scaff_FF_Flag & 2) || (Map_State->scaffIds[testPixel] == (Scaff_Painting_Flag == 1 ? 0 : currScaffId)))) Map_State->scaffIds[testPixel++] = Scaff_Painting_Id;
+ otherPixel = index;
+ break;
}
}
- UpdateContigsFromMapState();
- }
- else if (Select_Sort_Area_Mode)
- {
- auto_curation_state.update_sort_area(Tool_Tip_Move.pixels.x, Map_State, Number_of_Pixels_1D);
- }
- else if (
- MetaData_Edit_Mode &&
- MetaData_Edit_State &&
- strlen((const char *)Meta_Data->tags[MetaData_Active_Tag])
- )
- {
- u32 pixel = Tool_Tip_Move.pixels.x;
- u32 contigId = Map_State->contigIds[pixel];
+ u08 invert = (otherPixel == (Number_of_Pixels_1D - 1)) || (Map_State->contigIds[otherPixel + 1] != Map_State->contigIds[otherPixel]);
+ u32 otherPixel2 = otherPixel;
- if (MetaData_Edit_State == 1)
- Map_State->metaDataFlags[pixel] |= (1 << MetaData_Active_Tag); // set the active tag
- else
- Map_State->metaDataFlags[pixel] &= ~(1 << MetaData_Active_Tag); // clear the active tag
-
- u32 testPixel = pixel;
- while (testPixel && (Map_State->contigIds[testPixel - 1] == contigId))
+ if (!invert)
{
- if (MetaData_Edit_State == 1)
- Map_State->metaDataFlags[--testPixel] |= (1 << MetaData_Active_Tag);
- else
- Map_State->metaDataFlags[--testPixel] &= ~(1 << MetaData_Active_Tag);
+ while ((otherPixel < (Number_of_Pixels_1D - 1)) && (Map_State->contigIds[otherPixel + 1] == Map_State->contigIds[otherPixel2])) ++otherPixel;
}
-
- testPixel = pixel;
- while ((testPixel < (Number_of_Pixels_1D - 1)) && (Map_State->contigIds[testPixel + 1] == contigId))
+ else
{
- if (MetaData_Edit_State == 1)
- Map_State->metaDataFlags[++testPixel] |= (1 << MetaData_Active_Tag);
- else
- Map_State->metaDataFlags[++testPixel] &= ~(1 << MetaData_Active_Tag);
+ while (otherPixel2 && (Map_State->contigIds[otherPixel2 - 1] == Map_State->contigIds[otherPixel])) --otherPixel2;
}
- UpdateContigsFromMapState();
+ s32 delta = (s32)bottom - (s32)otherPixel2;
+ if (delta < 0) ++delta;
+ else delta = (s32)bottom - (s32)otherPixel;
+ pointui finalPixels = {(u32)((s32)otherPixel2 + delta), (u32)((s32)otherPixel + delta)};
+ RearrangeMap(otherPixel2, otherPixel, delta);
+ if (invert) InvertMap(finalPixels.x, finalPixels.y);
+ AddMapEdit(delta, finalPixels, invert);
}
- redisplay = 1;
- }
-
- if (Mouse_Move.x >= 0.0)
- {
- s32 w, h;
- glfwGetWindowSize(window, &w, &h);
- f32 height = (f32)h;
-
- f32 factor = 1.0f / (height * Camera_Position.z);
- f32 dx = (f32)(Mouse_Move.x - x) * factor;
- f32 dy = (f32)(y - Mouse_Move.y) * factor;
-
- Camera_Position.x += dx;
- Camera_Position.y += dy;
- ClampCamera();
-
- Mouse_Move.x = x;
- Mouse_Move.y = y;
-
- redisplay = 1;
+ continue;
}
+ else break;
}
+}
- if (redisplay)
+struct
+map_edit
+{
+ u32 finalPix1;
+ u32 finalPix2;
+ s32 delta;
+
+ map_edit() {finalPix1 = 0; finalPix2 = 0; delta = 0;}
+ map_edit(u32 fp1, u32 fp2, s32 d)
{
- Redisplay = 1;
+ finalPix1 = fp1;
+ finalPix2 = fp2;
+ delta = d;
}
-}
+};
+struct
+waypoint;
-global_variable
-u08
-Grey_Haplotigs = 1;
+struct
+waypoint_quadtree_node
+{
+ waypoint *wayp;
+ waypoint_quadtree_node *next;
+ waypoint_quadtree_node *prev;
+};
-global_variable
-GreyOutSettings* Grey_Out_Settings = nullptr;
+struct
+waypoint
+{
+ point2f coords;
+ f32 z;
+ u32 index;
+ waypoint *prev;
+ waypoint *next;
+ waypoint_quadtree_node *node;
+ // u16 long_waypoint_mode;
+};
-global_variable
-UserProfileSettings* user_profile_settings_ptr = nullptr;
+#define Edits_Stack_Size 32768
+#define Waypoints_Stack_Size 128
+
+struct
+map_editor
+{
+ map_edit *edits;
+ u32 nEdits;
+ u32 editStackPtr;
+ u32 nUndone;
+ u32 pad;
+};
global_variable
-u08
-Deferred_Close_UI = 0;
+map_editor *
+Map_Editor;
-global_function
-void
-Mouse(GLFWwindow* window, s32 button, s32 action, s32 mods)
+#define Waypoints_Quadtree_Levels 5
+
+struct
+waypoint_quadtree_level
{
- s32 primaryMouse = user_profile_settings_ptr->invert_mouse ? GLFW_MOUSE_BUTTON_RIGHT : GLFW_MOUSE_BUTTON_LEFT;
- s32 secondaryMouse = user_profile_settings_ptr->invert_mouse ? GLFW_MOUSE_BUTTON_LEFT : GLFW_MOUSE_BUTTON_RIGHT;
-
- if (Loading || auto_sort_state)
- {
- return;
- }
-
- (void)mods;
+#ifdef Internal
+ u32 show;
+#else
+ u32 pad;
+#endif
+ f32 size;
+ point2f lowerBound;
+ waypoint_quadtree_level *children[4];
+ waypoint_quadtree_node headNode;
+};
- f64 x, y;
- glfwGetCursorPos(window, &x, &y);
+struct
+waypoint_editor
+{
+ waypoint freeWaypoints;
+ waypoint activeWaypoints;
+ waypoint_quadtree_level *quadtree;
+ waypoint_quadtree_node freeNodes;
+ u32 nWaypointsActive;
+ u32 pad;
+};
- if (UI_On)
- {
- if (button == GLFW_MOUSE_BUTTON_MIDDLE && action == GLFW_PRESS)
- {
- Deferred_Close_UI = 1;
- }
- }
- else // UI not on
- {
- if (button == primaryMouse && Edit_Mode && action == GLFW_PRESS)
- {
- Edit_Pixels.editing = !Edit_Pixels.editing;
- MouseMove(window, x, y);
- if (!Edit_Pixels.editing) UpdateScaffolds();
- }
- else if (button == GLFW_MOUSE_BUTTON_MIDDLE && Edit_Mode && action == GLFW_RELEASE && !Edit_Pixels.editing)
- {
- Edit_Pixels.editing = 1;
- Edit_Pixels.selecting = 0;
- MouseMove(window, x, y);
- }
- else if (button == GLFW_MOUSE_BUTTON_MIDDLE && Edit_Mode && action == GLFW_PRESS && !Edit_Pixels.editing)
- {
- Edit_Pixels.selecting = 1;
- Edit_Pixels.selectPixels = Edit_Pixels.pixels;
- MouseMove(window, x, y);
- }
- else if (button == GLFW_MOUSE_BUTTON_MIDDLE && Edit_Mode && Edit_Pixels.editing && action == GLFW_PRESS)
- {
- InvertMap(Edit_Pixels.pixels.x, Edit_Pixels.pixels.y);
- Global_Edit_Invert_Flag = !Global_Edit_Invert_Flag;
- UpdateContigsFromMapState();
+global_variable
+waypoint_editor *
+Waypoint_Editor;
- Redisplay = 1;
- }
- else if (button == primaryMouse && Waypoint_Edit_Mode && action == GLFW_PRESS)
- {
- AddWayPoint(Tool_Tip_Move.worldCoords);
- MouseMove(window, x, y);
- }
- else if (button == GLFW_MOUSE_BUTTON_MIDDLE && Waypoint_Edit_Mode && action == GLFW_PRESS)
- {
- if (Selected_Waypoint)
- {
- RemoveWayPoint(Selected_Waypoint);
- MouseMove(window, x, y);
- }
- }
- else if (button == primaryMouse && Scaff_Edit_Mode && action == GLFW_PRESS)
- {
- Scaff_Painting_Flag = 1;
- MouseMove(window, x, y);
- }
- else if (button == GLFW_MOUSE_BUTTON_MIDDLE && Scaff_Edit_Mode && action == GLFW_PRESS)
- {
- Scaff_Painting_Flag = 2;
- MouseMove(window, x, y);
- }
- else if ((button == GLFW_MOUSE_BUTTON_MIDDLE || button == primaryMouse) && Scaff_Edit_Mode && action == GLFW_RELEASE)
- {
- Scaff_Painting_Flag = 0;
- Scaff_Painting_Id = 0;
- MouseMove(window, x, y);
- UpdateScaffolds();
- }
- else if (button == primaryMouse && Select_Sort_Area_Mode && action == GLFW_PRESS)
- {
- auto_curation_state.select_mode = 1;
- MouseMove(window, x, y);
- }
- else if (button == primaryMouse && Select_Sort_Area_Mode && action == GLFW_RELEASE)
- {
- auto_curation_state.select_mode = 0;
- MouseMove(window, x, y);
- }
- else if (button == primaryMouse && MetaData_Edit_Mode && action == GLFW_PRESS)
- {
- MetaData_Edit_State = 1;
- MouseMove(window, x, y);
- }
- else if (button == GLFW_MOUSE_BUTTON_MIDDLE && MetaData_Edit_Mode && action == GLFW_PRESS)
- {
- MetaData_Edit_State = 2;
- MouseMove(window, x, y);
- }
- else if ((button == GLFW_MOUSE_BUTTON_MIDDLE || button == primaryMouse) && MetaData_Edit_Mode && action == GLFW_RELEASE)
- {
- MetaData_Edit_State = 0;
- MouseMove(window, x, y);
- }
- else if (button == secondaryMouse)
- {
- if (action == GLFW_PRESS)
- {
- Mouse_Move.x = x;
- Mouse_Move.y = y;
- }
- else
- {
- Mouse_Move.x = Mouse_Move.y = -1.0;
- }
- }
- else if (button == GLFW_MOUSE_BUTTON_MIDDLE && action == GLFW_PRESS)
- {
- UI_On = !UI_On;
- Mouse_Move.x = Mouse_Move.y = -1;
- Redisplay = 1;
- ++NK_Device->lastContextMemory[0];
- }
- }
-}
+global_variable u16 Long_Waypoints_Mode = 0; // mode 0: vertical, mode 1: horizontal, mode 2: both
+#define Waypoint_Select_Distance 8.0f
global_variable
-struct nk_vec2
-NK_Scroll;
+waypoint *
+Selected_Waypoint = 0;
global_function
-void
-Scroll(GLFWwindow* window, f64 x, f64 y)
+waypoint_quadtree_level *
+PushQuadTree(memory_arena *arena, u32 level = 0, point2f lowerBound = {-0.5f, -0.5f}, f32 size = 1.0f)
{
- if (Loading || auto_sort_state)
- {
- return;
- }
-
- if (UI_On)
- {
- NK_Scroll.y = (f32)y;
- NK_Scroll.x = (f32)x;
- }
- else
+ waypoint_quadtree_level *quadtreeLevel = 0;
+
+ if (level < Waypoints_Quadtree_Levels)
{
- if (y != 0.0)
- {
- ZoomCamera(my_Max(my_Min((f32)y, 0.01f), -0.01f));
- Redisplay = 1;
- }
+ quadtreeLevel = PushStructP(arena, waypoint_quadtree_level);
+ quadtreeLevel->size = size;
+ quadtreeLevel->lowerBound = lowerBound;
+ quadtreeLevel->headNode = {};
- if (Edit_Mode || Tool_Tip->on || Waypoint_Edit_Mode)
- {
- f64 mousex, mousey;
- glfwGetCursorPos(window, &mousex, &mousey);
- MouseMove(window, mousex, mousey);
- }
+#ifdef Internal
+ quadtreeLevel->show = 0;
+#endif
+
+ f32 halfSize = size * 0.5f;
+ quadtreeLevel->children[0] = PushQuadTree(arena, level + 1, {lowerBound.x, lowerBound.y}, halfSize);
+ quadtreeLevel->children[1] = PushQuadTree(arena, level + 1, {lowerBound.x, lowerBound.y + halfSize}, halfSize);
+ quadtreeLevel->children[2] = PushQuadTree(arena, level + 1, {lowerBound.x + halfSize, lowerBound.y}, halfSize);
+ quadtreeLevel->children[3] = PushQuadTree(arena, level + 1, {lowerBound.x + halfSize, lowerBound.y + halfSize}, halfSize);
}
+
+ return(quadtreeLevel);
}
-global_variable
-u64
-Total_Genome_Length;
+global_function
+void
+#ifdef Internal
+GetWaypointsWithinRectange(point2f lowerBound, point2f size, waypoint ***bufferPtr, u32 reset = 1);
+#else
+GetWaypointsWithinRectange(point2f lowerBound, point2f size, waypoint ***bufferPtr);
+#endif
global_function
void
-Setup();
+UpdateWayPoint(waypoint *wayp, point2f coords);
global_function
-u32
-SubDivideScaleBar(f32 left, f32 right, f32 middle, f32 bpPerPixel, f32 offset)
+void
+MoveWayPoints(map_edit *edit, u32 undo = 0);
+
+global_function
+void
+AddMapEdit(s32 delta, pointui finalPixels, u32 invert)
{
- u32 result = 0;
+ ++Map_Editor->nEdits;
+ Map_Editor->nUndone = 0;
- if (left < right)
- {
- f32 length = right - left;
- f32 half = length * 0.5f;
- char buff[16];
- stbsp_snprintf(buff, 16, "%$.2f", (f64)(offset + (half * bpPerPixel)));
- f32 width = fonsTextBounds(FontStash_Context, middle, 0.0, buff, 0, NULL);
- f32 halfWidth = 0.5f * width;
+ map_edit *edit = Map_Editor->edits + Map_Editor->editStackPtr++;
- if ((middle + halfWidth) < right && (middle - halfWidth) > left)
- {
- u32 leftResult = SubDivideScaleBar(left, middle - halfWidth, (left + middle) * 0.5f, bpPerPixel, offset);
- u32 rightResult = SubDivideScaleBar(middle + halfWidth, right, (right + middle) * 0.5f, bpPerPixel, offset);
- result = 1 + my_Min(leftResult, rightResult);
- }
+ if (Map_Editor->editStackPtr == Edits_Stack_Size)
+ {
+ Map_Editor->editStackPtr = 0;
}
- return(result);
-}
-
-global_variable
-u32
-File_Loaded = 0;
+ u32 pix1 = (u32)(invert ? my_Max(finalPixels.x, finalPixels.y) : my_Min(finalPixels.x, finalPixels.y));
+ u32 pix2 = (u32)(invert ? my_Min(finalPixels.x, finalPixels.y) : my_Max(finalPixels.x, finalPixels.y));
-global_variable
-nk_color
-Theme_Colour;
+ edit->delta = (s32)delta;
+ edit->finalPix1 = pix1;
+ edit->finalPix2 = pix2;
+}
-#ifdef Internal
global_function
void
-DrawQuadTreeLevel (u32 *ptr, waypoint_quadtree_level *level, vertex *vert, f32 lineWidth, u32 n = 0)
+UpdateScaffolds()
{
- f32 colour[5][4] = {{1.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 1.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f, 1.0f}, {1.0f, 0.0f, 1.0f, 1.0f}, {0.0f, 1.0f, 1.0f, 1.0f}};
- f32 *col = (f32 *)colour[n%5];
-
- glUniform4fv(Flat_Shader->colorLocation, 1, col);
-
- if (level->show)
- {
- vert[0].x = level->lowerBound.x;
- vert[0].y = -level->lowerBound.y;
- vert[1].x = level->lowerBound.x;
- vert[1].y = -level->lowerBound.y - level->size;
- vert[2].x = level->lowerBound.x + lineWidth;
- vert[2].y = -level->lowerBound.y - level->size;
- vert[3].x = level->lowerBound.x + lineWidth;
- vert[3].y = -level->lowerBound.y;
-
- glBindBuffer(GL_ARRAY_BUFFER, QuadTree_Data->vbos[*ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(QuadTree_Data->vaos[(*ptr)++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
-
- vert[0].x = level->lowerBound.x;
- vert[0].y = -level->lowerBound.y - level->size;
- vert[1].x = level->lowerBound.x + level->size;
- vert[1].y = -level->lowerBound.y - level->size;
- vert[2].x = level->lowerBound.x + level->size;
- vert[2].y = -level->lowerBound.y - level->size + lineWidth;
- vert[3].x = level->lowerBound.x;
- vert[3].y = -level->lowerBound.y - level->size + lineWidth;
-
- glBindBuffer(GL_ARRAY_BUFFER, QuadTree_Data->vbos[*ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(QuadTree_Data->vaos[(*ptr)++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
-
- vert[0].x = level->lowerBound.x + level->size - lineWidth;
- vert[0].y = -level->lowerBound.y;
- vert[1].x = level->lowerBound.x + level->size - lineWidth;
- vert[1].y = -level->lowerBound.y - level->size;
- vert[2].x = level->lowerBound.x + level->size;
- vert[2].y = -level->lowerBound.y - level->size;
- vert[3].x = level->lowerBound.x + level->size;
- vert[3].y = -level->lowerBound.y;
+ ForLoop(Number_of_Pixels_1D) Map_State->scaffIds[index] = (Contigs->contigs_arr + Map_State->contigIds[index])->scaffId;
+}
- glBindBuffer(GL_ARRAY_BUFFER, QuadTree_Data->vbos[*ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(QuadTree_Data->vaos[(*ptr)++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+global_function
+void
+UndoMapEdit()
+{
+ if (Map_Editor->nEdits && !Edit_Pixels.editing)
+ {
+ --Map_Editor->nEdits;
+ ++Map_Editor->nUndone;
- vert[0].x = level->lowerBound.x;
- vert[0].y = -level->lowerBound.y;
- vert[1].x = level->lowerBound.x;
- vert[1].y = -level->lowerBound.y - lineWidth;
- vert[2].x = level->lowerBound.x + level->size;
- vert[2].y = -level->lowerBound.y - lineWidth;
- vert[3].x = level->lowerBound.x + level->size;
- vert[3].y = -level->lowerBound.y;
+ if (!Map_Editor->editStackPtr)
+ {
+ Map_Editor->editStackPtr = Edits_Stack_Size + 1;
+ }
- glBindBuffer(GL_ARRAY_BUFFER, QuadTree_Data->vbos[*ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(QuadTree_Data->vaos[(*ptr)++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- }
+ map_edit *edit = Map_Editor->edits + (--Map_Editor->editStackPtr);
- if (level->children[0])
- {
- ForLoop(4)
+ if (edit->finalPix1 > edit->finalPix2)
{
- DrawQuadTreeLevel(ptr, level->children[index], vert, lineWidth, n+1);
+ InvertMap((u32)edit->finalPix1, (u32)edit->finalPix2);
}
- }
-}
-#endif
-global_function
-u32
-FourFloatColorToU32(nk_colorf colour)
-{
- return(glfonsRGBA((u08)(colour.r * 255.0f), (u08)(colour.g * 255.0f),
- (u08)(colour.b * 255.0f), (u08)(colour.a * 255.0f)));
-}
+ u32 start = my_Min(edit->finalPix1, edit->finalPix2);
+ u32 end = my_Max(edit->finalPix1, edit->finalPix2);
-global_function
-u32
-ThreeFloatColorToU32(nk_colorf colour)
-{
- return(glfonsRGBA((u08)(colour.r * 255.0f), (u08)(colour.g * 255.0f),
- (u08)(colour.b * 255.0f), 255));
+ RearrangeMap(start, end, -edit->delta);
+
+ UpdateScaffolds();
+ }
}
global_function
void
-ColourGenerator(u32 index, f32 *rgb)
+RedoMapEdit()
{
-// #define RedFreq 1.666f
-// #define GreenFreq 2.666f
-// #define BlueFreq 3.666f
+ if (Map_Editor->nUndone && !Edit_Pixels.editing)
+ {
+ ++Map_Editor->nEdits;
+ --Map_Editor->nUndone;
-// rgb[0] = 0.5f * (sinf((f32)index * RedFreq) + 1.0f);
-// rgb[1] = 0.5f * (sinf((f32)index * GreenFreq) + 1.0f);
-// rgb[2] = 0.5f * (sinf((f32)index * BlueFreq) + 1.0f);
+ map_edit *edit = Map_Editor->edits + Map_Editor->editStackPtr++;
- f32 RedFreq = meta_dataColors[meta_data_curcolorProfile][0];
- f32 GreenFreq = meta_dataColors[meta_data_curcolorProfile][1];
- f32 BlueFreq = meta_dataColors[meta_data_curcolorProfile][2];
+ if (Map_Editor->editStackPtr == Edits_Stack_Size)
+ {
+ Map_Editor->editStackPtr = 0;
+ }
- rgb[0] = 0.5f * (sinf((f32)index * RedFreq) + 1.0f);
- rgb[1] = 0.5f * (sinf((f32)index * GreenFreq) + 1.0f);
- rgb[2] = 0.5f * (sinf((f32)index * BlueFreq) + 1.0f);
+ u32 start = my_Min(edit->finalPix1, edit->finalPix2);
+ u32 end = my_Max(edit->finalPix1, edit->finalPix2);
+
+ RearrangeMap((u32)((s32)start - edit->delta), (u32)((s32)end - edit->delta), edit->delta);
+
+ if (edit->finalPix1 > edit->finalPix2)
+ {
+ InvertMap((u32)edit->finalPix1, (u32)edit->finalPix2);
+ }
+
+ UpdateScaffolds();
+ }
}
-void DrawOutlinedText(
- FONScontext *FontStash_Context,
- nk_colorf *colour,
- const char *text,
- f32 x,
- f32 y,
- f32 offset = 1.0f,
- bool outline_on = false)
+global_function
+void
+MoveWayPoints(map_edit *edit, u32 undo)
{
-
- nk_colorf outlineColor;
- if (meta_outline->on == 1)
+ pointui tmp;
+ s32 delta;
+ pointui finalPixels;
+ if (undo)
{
- outlineColor = {0.0f, 0.0f, 0.0f, 1.0f}; // black
+ tmp = {(u32)edit->finalPix1, (u32)edit->finalPix2};
+ delta = -(s32)edit->delta;
+ finalPixels = {(u32)((s32)tmp.x + delta), (u32)((s32)tmp.y + delta)};
}
else
{
- outlineColor = {1.0f, 1.0f, 1.0f, 1.0f}; // white
+ tmp = {(u32)((s32)edit->finalPix1 - (s32)edit->delta), (u32)((s32)edit->finalPix2 - (s32)edit->delta)};
+ delta = (s32)edit->delta;
+ finalPixels = {(u32)edit->finalPix1, (u32)edit->finalPix2};
}
- if (outline_on)
- outlineColor = {0.0f, 0.0f, 0.0f, 1.0f}; // black
-
- unsigned int outlineColorU32 = FourFloatColorToU32(outlineColor);
- unsigned int textColorU32 = FourFloatColorToU32(*colour);
+ pointui startPixels = {my_Min(tmp.x, tmp.y), my_Max(tmp.x, tmp.y)};
+ u32 lengthMove = startPixels.y - startPixels.x + 1;
+ pointui editRange;
- if (meta_outline->on > 0 || outline_on)
+ if (delta > 0)
{
- fonsSetColor(FontStash_Context, outlineColorU32);
- fonsDrawText(FontStash_Context, x - offset, y - offset, text, 0);
- fonsDrawText(FontStash_Context, x + offset, y - offset, text, 0);
- fonsDrawText(FontStash_Context, x - offset, y + offset, text, 0);
- fonsDrawText(FontStash_Context, x + offset, y + offset, text, 0);
+ editRange.x = startPixels.x;
+ editRange.y = my_Max(finalPixels.x, finalPixels.y);
+ }
+ else
+ {
+ editRange.x = my_Min(finalPixels.x, finalPixels.y);
+ editRange.y = startPixels.y;
}
- // // Draw the original text on top
- fonsSetColor(FontStash_Context, textColorU32);
- fonsDrawText(FontStash_Context, x, y, text, 0);
-}
+ f32 ooNPixels = (f32)(1.0 / (f64)Number_of_Pixels_1D);
+ point2f editRangeModel = {((f32)editRange.x * ooNPixels) - 0.5f, ((f32)editRange.y * ooNPixels) - 0.5f};
+ f32 dRange = editRangeModel.y - editRangeModel.x;
+ waypoint **searchBuffer = PushArray(Working_Set, waypoint*, Waypoints_Stack_Size);
+ waypoint **bufferEnd = searchBuffer;
-global_variable
-char
-Extension_Magic_Bytes[][4] =
-{
- {'p', 's', 'g', 'h'}
-};
+ GetWaypointsWithinRectange({editRangeModel.x, -0.5f}, {dRange, 0.999f}, &bufferEnd);
+ GetWaypointsWithinRectange({-0.5f, editRangeModel.x}, {0.999f, dRange}, &bufferEnd
+#ifdef Internal
+, 0
+#endif
+ );
+ u32 nWayp = (u32)((my_Max((size_t)bufferEnd, (size_t)searchBuffer) - my_Min((size_t)bufferEnd, (size_t)searchBuffer)) / sizeof(searchBuffer));
+ waypoint **seen = PushArray(Working_Set, waypoint*, nWayp);
+ u32 seenIdx = 0;
+ for ( waypoint **waypPtr = searchBuffer;
+ waypPtr != bufferEnd;
+ ++waypPtr )
+ {
+ waypoint *wayp = *waypPtr;
+ u32 newWayP = 1;
-global_variable
-extension_sentinel
-Extensions = {};
+ ForLoop(seenIdx)
+ {
+ if (wayp == seen[index])
+ {
+ newWayP = 0;
+ break;
+ }
+ }
-global_function
-void
-AddExtension(extension_node *node)
-{
- node->next = 0;
+ if (newWayP)
+ {
+ point2f normCoords = {my_Min(wayp->coords.x, wayp->coords.y), my_Max(wayp->coords.x, wayp->coords.y)};
- if (!Extensions.head)
- {
- Extensions.head = node;
- Extensions.tail = node;
- }
- else
- {
- Extensions.tail->next = node; // append the last to the end
- Extensions.tail = node; // set the last to the new node just appended
- }
-}
+ u32 inXRange = normCoords.x >= editRangeModel.x && normCoords.x < editRangeModel.y;
+ u32 inYRange = normCoords.y >= editRangeModel.x && normCoords.y < editRangeModel.y;
+ u32 inRange = inXRange || inYRange;
-global_function
-void
-Render() {
- // Projection Matrix
- f32 width;
- f32 height;
- {
- glClear(GL_COLOR_BUFFER_BIT);
- // glClearColor(0.2f, 0.6f, 0.4f, 1.0f); // classic background color
- glClearColor(bgcolor[active_bgcolor][0], bgcolor[active_bgcolor][1], bgcolor[active_bgcolor][2], bgcolor[active_bgcolor][3]);
+ if (inRange)
+ {
+ u32 upperTri = wayp->coords.x > wayp->coords.y;
+
+ pointui pix = {(u32)((0.5f + wayp->coords.x) / ooNPixels), (u32)((0.5f + wayp->coords.y) / ooNPixels)};
- s32 viewport[4];
- glGetIntegerv (GL_VIEWPORT, viewport);
- width = (f32)viewport[2];
- height = (f32)viewport[3];
+ if (pix.x >= startPixels.x && pix.x < startPixels.y)
+ {
+ pix.x = (u32)((s32)pix.x + delta);
- f32 mat[16];
- memset(mat, 0, sizeof(mat));
- mat[0] = 2.0f * Camera_Position.z * height / width;
- mat[5] = 2.0f * Camera_Position.z;
- mat[10] = -2.0f;
- mat[12] = -2.0f * height * Camera_Position.x * Camera_Position.z / width;
- mat[13] = -2.0f * Camera_Position.y * Camera_Position.z;
- mat[15] = 1.0f;
+ if (edit->finalPix1 > edit->finalPix2)
+ {
+ pix.x = my_Max(finalPixels.x, finalPixels.y) - pix.x + my_Min(finalPixels.x, finalPixels.y);
+ }
+ }
+ else if (pix.x >= editRange.x && pix.x < editRange.y)
+ {
+ pix.x = delta > 0 ? pix.x - lengthMove : pix.x + lengthMove;
+ }
- /*
- template
- GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> orthoRH_NO(T left, T right, T bottom, T top, T zNear, T zFar)
- {
- mat<4, 4, T, defaultp> Result(1);
- Result[0][0] = static_cast(2) / (right - left); // 0
- Result[1][1] = static_cast(2) / (top - bottom); // 5
- Result[2][2] = - static_cast(2) / (zFar - zNear);// 10
- Result[3][0] = - (right + left) / (right - left); // 12
- Result[3][1] = - (top + bottom) / (top - bottom); // 13
- Result[3][2] = - (zFar + zNear) / (zFar - zNear); // 14
- return Result;
+ if (pix.y >= startPixels.x && pix.y < startPixels.y)
+ {
+ pix.y = (u32)((s32)pix.y + delta);
+
+ if (edit->finalPix1 > edit->finalPix2)
+ {
+ pix.y = my_Max(finalPixels.x, finalPixels.y) - pix.y + my_Min(finalPixels.x, finalPixels.y);
+ }
+ }
+ else if (pix.y >= editRange.x && pix.y < editRange.y)
+ {
+ pix.y = delta > 0 ? pix.y - lengthMove : pix.y + lengthMove;
+ }
+
+ point2f newCoords = {((f32)pix.x * ooNPixels) - 0.5f, ((f32)pix.y * ooNPixels) - 0.5f};
+
+ u32 upperTriNew = newCoords.x > newCoords.y;
+ if (upperTriNew != upperTri)
+ {
+ newCoords = {newCoords.y, newCoords.x};
+ }
+
+ UpdateWayPoint(wayp, newCoords);
+ }
+
+ seen[seenIdx++] = wayp;
}
- glm::mat4 projection_mat = glm::ortho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
- */
+ }
- // apply the transformation
- glUseProgram(Contact_Matrix->shaderProgram);
- glUniformMatrix4fv(Contact_Matrix->matLocation, 1, GL_FALSE, mat);
- glUseProgram(Flat_Shader->shaderProgram);
- glUniformMatrix4fv(Flat_Shader->matLocation, 1, GL_FALSE, mat);
+ FreeLastPush(Working_Set); // searchBuffer
+ FreeLastPush(Working_Set); // seen
+}
- TraverseLinkedList(Extensions.head, extension_node)
+global_function
+void
+GetWaypointsWithinRectange(waypoint_quadtree_level *level, point2f lowerBound, point2f size, waypoint ***bufferPtr)
+{
+ if (level->children[0])
+ {
+ u08 toSearch[4] = {1, 1, 1, 1};
+#define epsilon 0.001f
+ ForLoop(4)
{
- switch (node->type)
+ // bottom left
+ waypoint_quadtree_level *child = level->children[index];
+ point2f insertSize = {lowerBound.x - child->lowerBound.x, lowerBound.y - child->lowerBound.y};
+ if (insertSize.x >= 0 && insertSize.x < child->size && insertSize.y >= 0 && insertSize.y < child->size)
{
- case extension_graph:
- {
- graph *gph = (graph *)node->extension;
- glUseProgram(gph->shader->shaderProgram);
- glUniformMatrix4fv(gph->shader->matLocation, 1, GL_FALSE, mat);
- }
+ point2f recSize = {my_Min(size.x, child->size - insertSize.x - epsilon), my_Min(size.y, child->size - insertSize.y - epsilon)};
+ GetWaypointsWithinRectange(child, lowerBound, recSize, bufferPtr);
+ toSearch[index] = 0;
+ break;
+ }
+ }
+ ForLoop(4)
+ {
+ if (toSearch[index])
+ {
+ // bottom right
+ waypoint_quadtree_level *child = level->children[index];
+ point2f insertSize = {lowerBound.x + size.x - child->lowerBound.x, lowerBound.y - child->lowerBound.y};
+ if (insertSize.x >= 0 && insertSize.x < child->size && insertSize.y >= 0 && insertSize.y < child->size)
+ {
+ point2f recSize = {my_Min(size.x, insertSize.x), my_Min(size.y, child->size - insertSize.y - epsilon)};
+ GetWaypointsWithinRectange(child, {child->lowerBound.x + insertSize.x - recSize.x, lowerBound.y}, recSize, bufferPtr);
+ toSearch[index] = 0;
+ break;
+ }
+ }
+ }
+ ForLoop(4)
+ {
+ if (toSearch[index])
+ {
+ // top left
+ waypoint_quadtree_level *child = level->children[index];
+ point2f insertSize = {lowerBound.x - child->lowerBound.x, lowerBound.y + size.y - child->lowerBound.y};
+ if (insertSize.x >= 0 && insertSize.x < child->size && insertSize.y >= 0 && insertSize.y < child->size)
+ {
+ point2f recSize = {my_Min(size.x, child->size - insertSize.x - epsilon), my_Min(size.y, insertSize.y)};
+ GetWaypointsWithinRectange(child, {lowerBound.x, child->lowerBound.y + insertSize.y - recSize.y}, recSize, bufferPtr);
+ toSearch[index] = 0;
+ break;
+ }
+ }
+ }
+ ForLoop(4)
+ {
+ if (toSearch[index])
+ {
+ // top right
+ waypoint_quadtree_level *child = level->children[index];
+ point2f insertSize = {lowerBound.x + size.x - child->lowerBound.x, lowerBound.y + size.y - child->lowerBound.y};
+ if (insertSize.x >= 0 && insertSize.x < child->size && insertSize.y >= 0 && insertSize.y < child->size)
+ {
+ point2f recSize = {my_Min(size.x, insertSize.x), my_Min(size.y, insertSize.y)};
+ GetWaypointsWithinRectange(child, {child->lowerBound.x + insertSize.x - recSize.x, child->lowerBound.y + insertSize.y - recSize.y}, recSize, bufferPtr);
+#ifdef Internal
+ toSearch[index] = 0;
+#endif
break;
+ }
}
}
+
+#ifdef Internal
+ ForLoop(4)
+ {
+ if (!toSearch[index]) level->children[index]->show = 1;
+ }
+#endif
+
}
-
- // Textures
- if (File_Loaded)
+ else
{
- glUseProgram(Contact_Matrix->shaderProgram);
- glBindTexture(GL_TEXTURE_2D_ARRAY, Contact_Matrix->textures);
- u32 ptr = 0;
- while (ptr < Number_of_Textures_1D * Number_of_Textures_1D)
+ TraverseLinkedList(level->headNode.next, waypoint_quadtree_node)
{
- glBindVertexArray(Contact_Matrix->vaos[ptr++]); // bind the vertices and then draw the quad
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ **bufferPtr = node->wayp;
+ ++(*bufferPtr);
}
}
+}
- #ifdef Internal
- if (File_Loaded && Tiles->on)
+#ifdef Internal
+global_function
+void
+TurnOffDrawingForQuadTreeLevel(waypoint_quadtree_level *level = 0)
+{
+ if (!level) level = Waypoint_Editor->quadtree;
+ level->show = 0;
+ ForLoop(4)
{
- glUseProgram(Flat_Shader->shaderProgram);
- glUniform4fv(Flat_Shader->colorLocation, 1, (GLfloat *)&Tiles->bg);
-
- u32 ptr = 0;
- vertex vert[4];
+ if (level->children[index]) TurnOffDrawingForQuadTreeLevel(level->children[index]);
+ }
+}
+#endif
- f32 lineWidth = 0.001f / sqrtf(Camera_Position.z);
- f32 position = 0.0f;
- f32 spacing = 1.0f / (f32)Number_of_Textures_1D;
+global_function
+void
+GetWaypointsWithinSquare(point2f lowerBound, f32 size, waypoint ***bufferPtr
+#ifdef Internal
+ , u32 reset = 1)
+#else
+ )
+#endif
+{
+#ifdef Internal
+ if (reset) TurnOffDrawingForQuadTreeLevel();
+#endif
+ GetWaypointsWithinRectange(Waypoint_Editor->quadtree, lowerBound, {size, size}, bufferPtr);
+}
- vert[0].x = -0.5f;
- vert[0].y = -0.5f;
- vert[1].x = lineWidth - 0.5f;
- vert[1].y = -0.5f;
- vert[2].x = lineWidth - 0.5f;
- vert[2].y = 0.5f;
- vert[3].x = -0.5f;
- vert[3].y = 0.5f;
+global_function
+void
+GetWaypointsWithinRectange(point2f lowerBound, point2f size, waypoint ***bufferPtr
+#ifdef Internal
+ , u32 reset)
+#else
+ )
+#endif
+{
+#ifdef Internal
+ if (reset) TurnOffDrawingForQuadTreeLevel();
+#endif
+ GetWaypointsWithinRectange(Waypoint_Editor->quadtree, lowerBound, size, bufferPtr);
+}
- glBindBuffer(GL_ARRAY_BUFFER, Texture_Tile_Grid->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Texture_Tile_Grid->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+global_function
+waypoint_quadtree_level *
+GetWaypointQuadTreeLevel(point2f coords)
+{
+ coords = {my_Max(my_Min(coords.x, 0.499f), -0.5f), my_Max(my_Min(coords.y, 0.499f), -0.5f)};
+
+ waypoint_quadtree_level *level = Waypoint_Editor->quadtree;
- f32 x = -0.5f;
- ForLoop(Number_of_Textures_1D - 1)
+ while (level->children[0])
+ {
+#ifdef DEBUG
+ u32 found = 0;
+#endif
+ ForLoop(4)
{
- position += spacing;
- f32 px = x + lineWidth;
- x = position - (0.5f * (lineWidth + 1.0f));
-
- if (x > px)
+ point2f insertSize = {coords.x - level->children[index]->lowerBound.x, coords.y - level->children[index]->lowerBound.y};
+ f32 size = level->children[index]->size;
+ if (insertSize.x >= 0 && insertSize.x < size && insertSize.y >= 0 && insertSize.y < size)
{
- vert[0].x = x;
- vert[0].y = -0.5f;
- vert[1].x = x + lineWidth;
- vert[1].y = -0.5f;
- vert[2].x = x + lineWidth;
- vert[2].y = 0.5f;
- vert[3].x = x;
- vert[3].y = 0.5f;
-
- glBindBuffer(GL_ARRAY_BUFFER, Texture_Tile_Grid->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Texture_Tile_Grid->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ level = level->children[index];
+
+#ifdef DEBUG
+ found = 1;
+#endif
+
+ break;
}
}
- vert[0].x = 0.5f - lineWidth;
- vert[0].y = -0.5f;
- vert[1].x = 0.5f;
- vert[1].y = -0.5f;
- vert[2].x = 0.5f;
- vert[2].y = 0.5f;
- vert[3].x = 0.5f - lineWidth;
- vert[3].y = 0.5f;
+#ifdef DEBUG
+ if (!found)
+ {
+ Assert(found);
+ }
+#endif
- glBindBuffer(GL_ARRAY_BUFFER, Texture_Tile_Grid->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Texture_Tile_Grid->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ }
- position = 0.0f;
+ return(level);
+}
- vert[0].x = -0.5f;
- vert[0].y = 0.5f - lineWidth;
- vert[1].x = 0.5f;
- vert[1].y = 0.5f - lineWidth;
- vert[2].x = 0.5f;
- vert[2].y = 0.5f;
- vert[3].x = -0.5f;
- vert[3].y = 0.5f;
+global_function
+void
+AddWayPoint(point2f coords)
+{
+ u32 nFree = Waypoints_Stack_Size - Waypoint_Editor->nWaypointsActive;
- glBindBuffer(GL_ARRAY_BUFFER, Texture_Tile_Grid->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Texture_Tile_Grid->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ if (nFree)
+ {
+ waypoint *wayp = Waypoint_Editor->freeWaypoints.next;
+ Waypoint_Editor->freeWaypoints.next = wayp->next;
+ if (Waypoint_Editor->freeWaypoints.next) Waypoint_Editor->freeWaypoints.next->prev = &Waypoint_Editor->freeWaypoints;
- f32 y = 0.5f;
- ForLoop(Number_of_Textures_1D - 1)
- {
- position += spacing;
- f32 py = y - lineWidth;
- y = 1.0f - position + (0.5f * (lineWidth - 1.0f));
+ wayp->next = Waypoint_Editor->activeWaypoints.next;
+ if (Waypoint_Editor->activeWaypoints.next) Waypoint_Editor->activeWaypoints.next->prev = wayp;
+ Waypoint_Editor->activeWaypoints.next = wayp;
+ wayp->prev = &Waypoint_Editor->activeWaypoints;
+ wayp->index = wayp->next ? wayp->next->index + 1 : 0;
- if (y < py)
- {
- vert[0].x = -0.5f;
- vert[0].y = y - lineWidth;
- vert[1].x = 0.5f;
- vert[1].y = y - lineWidth;
- vert[2].x = 0.5f;
- vert[2].y = y;
- vert[3].x = -0.5f;
- vert[3].y = y;
+ wayp->coords = coords;
+ wayp->z = Camera_Position.z;
+ ++Waypoint_Editor->nWaypointsActive;
- glBindBuffer(GL_ARRAY_BUFFER, Texture_Tile_Grid->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Texture_Tile_Grid->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- }
- }
+ waypoint_quadtree_level *level = GetWaypointQuadTreeLevel(wayp->coords);
+
+ waypoint_quadtree_node *node = Waypoint_Editor->freeNodes.next;
+ if (node->next) node->next->prev = &Waypoint_Editor->freeNodes;
+ Waypoint_Editor->freeNodes.next = node->next;
- vert[0].x = -0.5f;
- vert[0].y = -0.5f;
- vert[1].x = 0.5f;
- vert[1].y = -0.5f;
- vert[2].x = 0.5f;
- vert[2].y = lineWidth - 0.5f;
- vert[3].x = -0.5f;
- vert[3].y = lineWidth - 0.5f;
+ if (level->headNode.next) level->headNode.next->prev = node;
+ node->next = level->headNode.next;
+ node->prev = &level->headNode;
+ level->headNode.next = node;
- glBindBuffer(GL_ARRAY_BUFFER, Texture_Tile_Grid->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Texture_Tile_Grid->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ wayp->node = node;
+ node->wayp = wayp;
}
+}
- // Quad Trees
- //if (Waypoint_Edit_Mode)
+global_function
+void
+RemoveWayPoint(waypoint *wayp)
+{
+ switch (Waypoint_Editor->nWaypointsActive)
{
- glUseProgram(Flat_Shader->shaderProgram);
- glUniform4fv(Flat_Shader->colorLocation, 1, (GLfloat *)&QuadTrees->bg);
-
- u32 ptr = 0;
- vertex vert[4];
+ case 0:
+ wayp = 0;
+ break;
- f32 lineWidth = 0.001f / sqrtf(Camera_Position.z);
+ case 1:
+ Waypoint_Editor->activeWaypoints.next = 0;
+ Waypoint_Editor->nWaypointsActive = 0;
+ break;
- DrawQuadTreeLevel(&ptr, Waypoint_Editor->quadtree, vert, lineWidth);
+ default:
+ if (wayp->next) wayp->next->prev = wayp->prev;
+ if (wayp->prev) wayp->prev->next = wayp->next;
+ --Waypoint_Editor->nWaypointsActive;
}
- #endif
-
- // Extensions
- u08 graphNamesOn = 0;
- {
- TraverseLinkedList(Extensions.head, extension_node)
- {
- switch (node->type)
- {
- case extension_graph:
- {
- graph *gph = (graph *)node->extension;
-
- if (gph->on)
- {
- if (gph->nameOn) graphNamesOn = 1;
- f32 factor1 = 1.0f / (2.0f * Camera_Position.z);
- f32 factor2 = 2.0f / height;
+ if (wayp)
+ {
+ wayp->next = Waypoint_Editor->freeWaypoints.next;
+ if (Waypoint_Editor->freeWaypoints.next) Waypoint_Editor->freeWaypoints.next->prev = wayp;
+ Waypoint_Editor->freeWaypoints.next = wayp;
+ wayp->prev = &Waypoint_Editor->freeWaypoints;
- f32 wy = (factor1 * (1.0f - (factor2 * (height - gph->base)))) + Camera_Position.y;
+ waypoint_quadtree_node *node = wayp->node;
- glUseProgram(gph->shader->shaderProgram);
- glUniform4fv(gph->shader->colorLocation, 1, (GLfloat *)&gph->colour);
- glUniform1f(gph->shader->yScaleLocation, gph->scale);
- glUniform1f(gph->shader->yTopLocation, wy);
- glUniform1f(gph->shader->lineSizeLocation, gph->lineSize / Camera_Position.z);
+ if (node->next) node->next->prev = node->prev;
+ if (node->prev) node->prev->next = node->next;
+ node->prev = 0;
- glBindBuffer(GL_ARRAY_BUFFER, gph->vbo);
- glBindVertexArray(gph->vao);
- glDrawArrays(GL_LINE_STRIP, 0, (GLsizei)Number_of_Pixels_1D);
- }
- }
- break;
- }
- }
+ if (Waypoint_Editor->freeNodes.next) Waypoint_Editor->freeNodes.next->prev = node;
+ node->next = Waypoint_Editor->freeNodes.next;
+ Waypoint_Editor->freeNodes.next = node;
+ node->prev = &Waypoint_Editor->freeNodes;
}
+}
- // Grid
- if (File_Loaded && Grid->on)
- {
- glUseProgram(Flat_Shader->shaderProgram);
- glUniform4fv(Flat_Shader->colorLocation, 1, (GLfloat *)&Grid->bg);
+global_function
+void
+UpdateWayPoint(waypoint *wayp, point2f coords)
+{
+ waypoint_quadtree_node *node = wayp->node;
- u32 ptr = 0;
- vertex vert[4];
+ if (node->next) node->next->prev = node->prev;
+ if (node->prev) node->prev->next = node->next;
+ node->prev = 0;
- f32 lineWidth = Grid->size / sqrtf(Camera_Position.z);
- f32 position = 0.0f;
+ wayp->coords = coords;
- // left border
- vert[0].x = -0.5f; vert[0].y = -0.5f;
- vert[1].x = lineWidth - 0.5f; vert[1].y = -0.5f;
- vert[2].x = lineWidth - 0.5f; vert[2].y = 0.5f;
- vert[3].x = -0.5f; vert[3].y = 0.5f;
+ waypoint_quadtree_level *level = GetWaypointQuadTreeLevel(wayp->coords);
- glBindBuffer(GL_ARRAY_BUFFER, Grid_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Grid_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ if (level->headNode.next) level->headNode.next->prev = node;
+ node->next = level->headNode.next;
+ node->prev = &level->headNode;
+ level->headNode.next = node;
- f32 x = -0.5f;
- ForLoop(Contigs->numberOfContigs - 1)
- {
- contig *cont = Contigs->contigs_arr + index;
+ wayp->node = node;
+ node->wayp = wayp;
+}
- position += ((f32)cont->length / (f32)Number_of_Pixels_1D);
- f32 px = x + lineWidth;
- x = position - (0.5f * (lineWidth + 1.0f));
+global_function
+void
+MouseMove(GLFWwindow* window, f64 x, f64 y)
+{
+ if (Loading || auto_sort_state || auto_cut_state)
+ {
+ return;
+ }
- if (x > px)
- {
- // contig vertical line
- vert[0].x = x; vert[0].y = -0.5f;
- vert[1].x = x + lineWidth; vert[1].y = -0.5f;
- vert[2].x = x + lineWidth; vert[2].y = 0.5f;
- vert[3].x = x; vert[3].y = 0.5f;
+ (void)window;
- glBindBuffer(GL_ARRAY_BUFFER, Grid_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Grid_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- }
- }
- // right border
- vert[0].x = 0.5f - lineWidth; vert[0].y = -0.5f;
- vert[1].x = 0.5f; vert[1].y = -0.5f;
- vert[2].x = 0.5f; vert[2].y = 0.5f;
- vert[3].x = 0.5f - lineWidth; vert[3].y = 0.5f;
-
- glBindBuffer(GL_ARRAY_BUFFER, Grid_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Grid_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
-
- position = 0.0f;
- // top border
- vert[0].x = -0.5f; vert[0].y = 0.5f - lineWidth;
- vert[1].x = 0.5f; vert[1].y = 0.5f - lineWidth;
- vert[2].x = 0.5f; vert[2].y = 0.5f;
- vert[3].x = -0.5f; vert[3].y = 0.5f;
-
- glBindBuffer(GL_ARRAY_BUFFER, Grid_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Grid_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
-
- f32 y = 0.5f;
- ForLoop(Contigs->numberOfContigs - 1)
- {
- contig *cont = Contigs->contigs_arr + index;
-
- position += ((f32)cont->length / (f32)Number_of_Pixels_1D);
- f32 py = y - lineWidth;
- y = 1.0f - position + (0.5f * (lineWidth - 1.0f));
-
- if (y < py)
- {
- // contig horizontal line
- vert[0].x = -0.5f; vert[0].y = y - lineWidth;
- vert[1].x = 0.5f; vert[1].y = y - lineWidth;
- vert[2].x = 0.5f; vert[2].y = y;
- vert[3].x = -0.5f; vert[3].y = y;
-
- glBindBuffer(GL_ARRAY_BUFFER, Grid_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Grid_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- }
- }
- // bottom border
- vert[0].x = -0.5f; vert[0].y = -0.5f;
- vert[1].x = 0.5f; vert[1].y = -0.5f;
- vert[2].x = 0.5f; vert[2].y = lineWidth - 0.5f;
- vert[3].x = -0.5f; vert[3].y = lineWidth - 0.5f;
+ u32 redisplay = 0;
- glBindBuffer(GL_ARRAY_BUFFER, Grid_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Grid_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ if (UI_On)
+ {
}
-
- // Contig Id Bars
- if (File_Loaded && Contig_Ids->on)
+ else // ui_on == false
{
- glUseProgram(Flat_Shader->shaderProgram);
- glUniform4fv(Flat_Shader->colorLocation, 1, (GLfloat *)&Grid->bg);
-
- u32 ptr = 0;
- vertex vert[4];
-
- f32 barColour[4] = {1.0f, 1.0f, 1.0f, 1.0f};
-
- f32 lineWidth = Contig_Ids->size / sqrtf(Camera_Position.z);
- f32 position = 0.0f;
-
- f32 y = 0.5f;
- ForLoop(Contigs->numberOfContigs)
+ if (Edit_Mode)
{
- contig *cont = Contigs->contigs_arr + index;
-
- position += ((f32)cont->length / (f32)Number_of_Pixels_1D);
- f32 py = y - lineWidth;
- y = 1.0f - position + (0.5f * (lineWidth - 1.0f));
-
- if (y < py)
- {
- u32 invert = IsContigInverted(index);
+ static s32 netDelta = 0;
- vert[0].x = -py; vert[0].y = invert ? y : (py + lineWidth);
- vert[1].x = -py; vert[1].y = invert ? (y - lineWidth) : py;
- vert[2].x = -y; vert[2].y = invert ? (y - lineWidth) : py;
- vert[3].x = -y; vert[3].y = invert ? y : (py + lineWidth);
+ s32 w, h;
+ glfwGetWindowSize(window, &w, &h);
+ f32 height = (f32)h;
+ f32 width = (f32)w;
- ColourGenerator((u32)cont->originalContigId, (f32 *)barColour);
- glUniform4fv(Flat_Shader->colorLocation, 1, (GLfloat *)&barColour);
+ f32 factor1 = 1.0f / (2.0f * Camera_Position.z);
+ f32 factor2 = 2.0f / height;
+ f32 factor3 = width * 0.5f;
- glBindBuffer(GL_ARRAY_BUFFER, Contig_ColourBar_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Contig_ColourBar_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- }
- }
- }
+ f32 wx = (factor1 * factor2 * ((f32)x - factor3)) + Camera_Position.x;
+ f32 wy = (-factor1 * (1.0f - (factor2 * (f32)y))) - Camera_Position.y;
- // Text / UI Rendering
- if (Contig_Name_Labels->on || Scale_Bars->on || Tool_Tip->on || UI_On || Loading || auto_sort_state || Edit_Mode || Waypoint_Edit_Mode || Waypoints_Always_Visible || Scaff_Edit_Mode || Scaffs_Always_Visible || MetaData_Edit_Mode || MetaData_Always_Visible || graphNamesOn)
- {
- f32 textNormalMat[16];
- f32 textRotMat[16];
+ wx = my_Max(-0.5f, my_Min(0.5f, wx));
+ wy = my_Max(-0.5f, my_Min(0.5f, wy));
- f32 w2 = width * 0.5f;
- f32 h2 = height * 0.5f;
- f32 hz = height * Camera_Position.z;
+ u32 nPixels = Number_of_Pixels_1D;
- // coverting model coords (world space) to screen coords
- auto ModelXToScreen = [hz, w2](f32 xin)->f32 {
- return (xin - Camera_Position.x) * hz + w2; };
- auto ModelYToScreen = [hz, h2](f32 yin)->f32 {
- return h2 - (yin - Camera_Position.y) * hz; };
+ u32 pixel1 = (u32)((f64)nPixels * (0.5 + (f64)wx));
+ u32 pixel2 = (u32)((f64)nPixels * (0.5 + (f64)wy));
+
+ // 防止在尾部溢出
+ pixel1 = my_Max(0, my_Min(nPixels - 1, pixel1));
+ pixel2 = my_Max(0, my_Min(nPixels - 1, pixel2));
- // Text Projection Matrix
- {
- memset(textNormalMat, 0, sizeof(textNormalMat));
- textNormalMat[0] = 2.0f / width;
- textNormalMat[5] = -2.0f / height;
- textNormalMat[10] = -1.0f;
- textNormalMat[12] = -1.0f;
- textNormalMat[13] = 1.0f;
- textNormalMat[15] = 1.0f;
+ u32 contig = Map_State->contigIds[pixel1];
- memset(textRotMat, 0, sizeof(textRotMat));
- textRotMat[4] = 2.0f / width;
- textRotMat[1] = 2.0f / height;
- textRotMat[10] = -1.0f;
- textRotMat[12] = -1.0f;
- textRotMat[13] = 1.0f;
- textRotMat[15] = 1.0f;
- }
+ if (!Edit_Pixels.editing && !Edit_Pixels.selecting && Map_State->contigIds[pixel2] != contig)
+ {
+ u32 testPixel = pixel1;
+ u32 testContig = contig;
+ while (testContig == contig) // move testContig to the 1 before the first or 1 after the last pixel of the contig
+ {
- // Extension Labels
- if (graphNamesOn)
- {
- glUseProgram(UI_Shader->shaderProgram);
- glUniformMatrix4fv(UI_Shader->matLocation, 1, GL_FALSE, textNormalMat);
+ if (pixel1 < pixel2)
+ {
+ testPixel ++ ;
+ }
+ else
+ {
+ testPixel -- ;
+ }
- fonsClearState(FontStash_Context);
- fonsSetSize(FontStash_Context, 32.0f * Screen_Scale.x);
- fonsSetAlign(FontStash_Context, FONS_ALIGN_LEFT | FONS_ALIGN_TOP);
- fonsSetFont(FontStash_Context, Font_Bold);
+ testContig = Map_State->contigIds[testPixel];
- f32 x = ModelXToScreen(-0.5f);
- x = my_Max(x, 0.0f) + 10.0f;
+ if (testPixel == 0 || testPixel >= (nPixels - 1)) break;
- f32 h = height + 1.0f;
+ // testContig = pixel1 < pixel2 ? Map_State->contigIds[++testPixel] : Map_State->contigIds[--testPixel];
+ // if (testPixel == 0 || testPixel >= (nPixels - 1)) break;
+ }
+ if (Map_State->contigIds[testPixel] == contig)
+ {
+ pixel2 = testPixel;
+ }
+ else
+ {
+ pixel2 = pixel1 < pixel2 ? testPixel - 1 : testPixel + 1;
+ }
+ }
- TraverseLinkedList(Extensions.head, extension_node)
+
+ if (Edit_Pixels.selecting) // select the contig
{
- switch (node->type)
+ Edit_Pixels.selectPixels.x = my_Max(pixel1, my_Max(Edit_Pixels.selectPixels.x, Edit_Pixels.selectPixels.y)); // used to select multiple contigs with pressing space and dragging the mouse
+ // Edit_Pixels.selectPixels.x = pixel1;
+ while( Edit_Pixels.selectPixels.x < (Number_of_Pixels_1D - 1) &&
+ ((Edit_Pixels.scaffSelecting && Map_State->scaffIds[Edit_Pixels.selectPixels.x] && Map_State->scaffIds[Edit_Pixels.selectPixels.x] == Map_State->scaffIds[1 + Edit_Pixels.selectPixels.x] ) ||
+ Map_State->contigIds[Edit_Pixels.selectPixels.x] == Map_State->contigIds[1 + Edit_Pixels.selectPixels.x]))
{
- case extension_graph:
- {
- graph *gph = (graph *)node->extension;
+ ++Edit_Pixels.selectPixels.x;
+ }
- if (gph->on && gph->nameOn)
- {
- fonsSetColor(FontStash_Context, ThreeFloatColorToU32(gph->colour));
- fonsDrawText(FontStash_Context, x, h - gph->base, (const char *)gph->name, 0);
- }
- }
- break;
+ Edit_Pixels.selectPixels.y = my_Min(pixel1, my_Min(Edit_Pixels.selectPixels.x, Edit_Pixels.selectPixels.y));
+ // Edit_Pixels.selectPixels.y = pixel1;
+ while( Edit_Pixels.selectPixels.y > 0 &&
+ ((Edit_Pixels.scaffSelecting && Map_State->scaffIds[Edit_Pixels.selectPixels.y] && Map_State->scaffIds[Edit_Pixels.selectPixels.y] == Map_State->scaffIds[Edit_Pixels.selectPixels.y - 1]) || Map_State->contigIds[Edit_Pixels.selectPixels.y] == Map_State->contigIds[Edit_Pixels.selectPixels.y - 1]))
+ {
+ --Edit_Pixels.selectPixels.y;
}
+
+ pixel1 = Edit_Pixels.selectPixels.x;
+ pixel2 = Edit_Pixels.selectPixels.y;
}
- }
- if (File_Loaded && Contig_Name_Labels->on) // Contig Labels
- {
- glUseProgram(Flat_Shader->shaderProgram);
- glUniform4fv(Flat_Shader->colorLocation, 1, (GLfloat *)&Contig_Name_Labels->bg);
- glUniformMatrix4fv(Flat_Shader->matLocation, 1, GL_FALSE, textNormalMat);
+ if (Edit_Pixels.editing)
+ {
+ u32 midPixel = (pixel1 + pixel2) >> 1;
+ u32 oldMidPixel = (Edit_Pixels.pixels.x + Edit_Pixels.pixels.y) >> 1;
+ s32 diff = (s32)midPixel - (s32)oldMidPixel;
- glUseProgram(UI_Shader->shaderProgram);
- glUniformMatrix4fv(UI_Shader->matLocation, 1, GL_FALSE, textNormalMat);
+ u32 forward = diff > 0;
+
+ s32 newX = (s32)Edit_Pixels.pixels.x + diff;
+ newX = my_Max(0, my_Min((s32)nPixels - 1, newX));
+ s32 newY = (s32)Edit_Pixels.pixels.y + diff;
+ newY = my_Max(0, my_Min((s32)nPixels - 1, newY));
- u32 ptr = 0;
- vertex vert[4];
+ s32 diffx = newX - (s32)Edit_Pixels.pixels.x;
+ s32 diffy = newY - (s32)Edit_Pixels.pixels.y;
- glViewport(0, 0, (s32)width, (s32)height);
+ diff = forward ? my_Min(diffx, diffy) : my_Max(diffx, diffy);
+
+ //newX = (s32)Edit_Pixels.pixels.x + diff;
+ //newY = (s32)Edit_Pixels.pixels.y + diff;
+
+ diff = RearrangeMap(Edit_Pixels.pixels.x, Edit_Pixels.pixels.y, diff, Edit_Pixels.snap);
+ netDelta += diff;
- f32 lh = 0.0f;
+ newX = (s32)Edit_Pixels.pixels.x + diff;
+ newY = (s32)Edit_Pixels.pixels.y + diff;
+
+ Edit_Pixels.pixels.x = (u32)newX;
+ Edit_Pixels.pixels.y = (u32)newY;
- fonsClearState(FontStash_Context);
- fonsSetSize(FontStash_Context, Contig_Name_Labels->size * Screen_Scale.x);
- fonsSetAlign(FontStash_Context, FONS_ALIGN_CENTER | FONS_ALIGN_TOP);
- fonsSetFont(FontStash_Context, Font_Bold);
- fonsVertMetrics(FontStash_Context, 0, 0, &lh);
- fonsSetColor(FontStash_Context, FourFloatColorToU32(Contig_Name_Labels->fg));
-
- f32 leftPixel = ModelXToScreen(-0.5f);
- f32 totalLength = 0.0f;
- f32 wy0 = ModelYToScreen(0.5f);
-
- ForLoop(Contigs->numberOfContigs)
+ Edit_Pixels.worldCoords.x = (f32)(((f64)((2 * Edit_Pixels.pixels.x) + 1)) / ((f64)(2 * nPixels))) - 0.5f;
+ Edit_Pixels.worldCoords.y = (f32)(((f64)((2 * Edit_Pixels.pixels.y) + 1)) / ((f64)(2 * nPixels))) - 0.5f;
+ }
+ else // edit_pixels.editing == 0
{
- contig *cont = Contigs->contigs_arr + index;
+ if (netDelta || Global_Edit_Invert_Flag)
+ {
+ AddMapEdit(netDelta, Edit_Pixels.pixels, Global_Edit_Invert_Flag);
+ netDelta = 0;
+ }
- totalLength += (f32)((f64)cont->length / (f64)Number_of_Pixels_1D);
+ wx = (f32)(((f64)((2 * pixel1) + 1)) / ((f64)(2 * nPixels))) - 0.5f;
+ wy = (f32)(((f64)((2 * pixel2) + 1)) / ((f64)(2 * nPixels))) - 0.5f;
- f32 rightPixel = ModelXToScreen(totalLength - 0.5f);
+ Edit_Pixels.pixels.x = pixel1;
+ Edit_Pixels.pixels.y = pixel2;
+ Edit_Pixels.worldCoords.x = wx;
+ Edit_Pixels.worldCoords.y = wy;
+
+ Global_Edit_Invert_Flag = 0;
+ }
- if (rightPixel > 0.0f && leftPixel < width)
- {
- const char *name = (const char *)(Original_Contigs + cont->get_original_contig_id())->name;
- f32 x = (rightPixel + leftPixel) * 0.5f;
- f32 y = my_Max(wy0, 0.0f) + 10.0f;
- f32 textWidth = fonsTextBounds(FontStash_Context, x, y, name, 0, NULL);
+ redisplay = 1;
+ }
+ else if (
+ Tool_Tip->on ||
+ Waypoint_Edit_Mode ||
+ Scaff_Edit_Mode ||
+ MetaData_Edit_Mode ||
+ Select_Sort_Area_Mode)
+ {
+ s32 w, h;
+ glfwGetWindowSize(window, &w, &h);
+ f32 height = (f32)h;
+ f32 width = (f32)w;
- if (textWidth < (rightPixel - leftPixel))
- {
- f32 w2t = 0.5f * textWidth;
+ f32 factor1 = 1.0f / (2.0f * Camera_Position.z);
+ f32 factor2 = 2.0f / height;
+ f32 factor3 = width * 0.5f;
- glUseProgram(Flat_Shader->shaderProgram);
+ f32 wx = (factor1 * factor2 * ((f32)x - factor3)) + Camera_Position.x;
+ f32 wy = (-factor1 * (1.0f - (factor2 * (f32)y))) - Camera_Position.y;
- vert[0].x = x - w2t; vert[0].y = y + lh;
- vert[1].x = x + w2t; vert[1].y = y + lh;
- vert[2].x = x + w2t; vert[2].y = y;
- vert[3].x = x - w2t; vert[3].y = y;
+ wx = my_Max(-0.5f, my_Min(0.5f, wx));
+ wy = my_Max(-0.5f, my_Min(0.5f, wy));
- glBindBuffer(GL_ARRAY_BUFFER, Label_Box_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Label_Box_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ u32 nPixels = Number_of_Textures_1D * Texture_Resolution;
- glUseProgram(UI_Shader->shaderProgram);
- fonsDrawText(FontStash_Context, x, y, name, 0);
- }
- }
+ u32 pixel1 = my_Min((u32)((f64)nPixels * (0.5 + (f64)wx)), (nPixels - 1));
+ u32 pixel2 = my_Min((u32)((f64)nPixels * (0.5 + (f64)wy)), (nPixels - 1));
- leftPixel = rightPixel;
- }
+ Tool_Tip_Move.pixels.x = pixel1;
+ Tool_Tip_Move.pixels.y = pixel2;
+ Tool_Tip_Move.worldCoords.x = wx;
+ Tool_Tip_Move.worldCoords.y = wy;
- glUseProgram(Flat_Shader->shaderProgram);
- glUniformMatrix4fv(Flat_Shader->matLocation, 1, GL_FALSE, textRotMat);
+ if (Waypoint_Edit_Mode)
+ {
+ Selected_Waypoint = 0;
+ f32 selectDis = Waypoint_Select_Distance / (height * Camera_Position.z);
+ f32 closestDistanceSq = selectDis * selectDis;
- glUseProgram(UI_Shader->shaderProgram);
- glUniformMatrix4fv(UI_Shader->matLocation, 1, GL_FALSE, textRotMat);
+ waypoint **searchBuffer = PushArray(Working_Set, waypoint*, Waypoints_Stack_Size);
+ waypoint **bufferEnd = searchBuffer;
+ GetWaypointsWithinSquare( // add waypoints within the square to the buffer
+ {Tool_Tip_Move.worldCoords.x - selectDis, Tool_Tip_Move.worldCoords.y - selectDis},
+ 2.0f * selectDis,
+ &bufferEnd);
+ for ( waypoint **waypPtr = searchBuffer;
+ waypPtr != bufferEnd;
+ ++waypPtr ) { // make sure select the closest waypoint to the mouse
+ waypoint *wayp = *waypPtr;
- f32 topPixel = ModelYToScreen(0.5f);
- f32 wx0 = ModelXToScreen(-0.5f);
- totalLength = 0.0f;
+ f32 dx = Tool_Tip_Move.worldCoords.x - wayp->coords.x;
+ f32 dy = Tool_Tip_Move.worldCoords.y - wayp->coords.y;
+ f32 disSq = (dx * dx) + (dy * dy);
- ForLoop(Contigs->numberOfContigs)
- {
- contig *cont = Contigs->contigs_arr + index;
-
- totalLength += (f32)((f64)cont->length / (f64)Number_of_Pixels_1D);
+ if (disSq < closestDistanceSq)
+ {
+ closestDistanceSq = disSq;
+ Selected_Waypoint = wayp;
+ }
+ }
- f32 bottomPixel = ModelYToScreen(0.5f - totalLength);
+ FreeLastPush(Working_Set); // searchBuffer
+ }
+ else if (Scaff_Edit_Mode && Scaff_Painting_Flag)
+ {
+ if (Scaff_Painting_Flag == 1)
+ {
+ if (!Scaff_Painting_Id)
+ {
+ if (Map_State->scaffIds[Tool_Tip_Move.pixels.x])
+ {
+ Scaff_Painting_Id = Map_State->scaffIds[Tool_Tip_Move.pixels.x];
+ }
+ else
+ {
+ u32 max = 0;
+ ForLoop(Number_of_Pixels_1D) max = my_Max(max, Map_State->scaffIds[index]);
+ Scaff_Painting_Id = max + 1;
+ }
+ }
+ }
+ else Scaff_Painting_Id = 0;
- if (topPixel < height && bottomPixel > 0.0f)
+ if (Map_State->scaffIds[Tool_Tip_Move.pixels.x] != Scaff_Painting_Id || (Scaff_FF_Flag & 1))
{
- const char *name = (const char *)(Original_Contigs + cont->get_original_contig_id())->name;
- f32 y = (topPixel + bottomPixel) * 0.5f;
- f32 x = my_Max(wx0, 0.0f) + 10.0f;
- f32 textWidth = fonsTextBounds(FontStash_Context, x, y, name, 0, NULL);
+ u32 pixel = Tool_Tip_Move.pixels.x;
- if (textWidth < (bottomPixel - topPixel))
- {
- f32 tmp = x;
- x = -y;
- y = tmp;
+ u32 currScaffId = Map_State->scaffIds[pixel];
+ u32 contigId = Map_State->contigIds[pixel];
+ Map_State->scaffIds[pixel] = Scaff_Painting_Id;
- f32 w2t = 0.5f * textWidth;
+ // set the pixels with same contig_id into the same scaff
+ u32 testPixel = pixel;
+ while (testPixel && (Map_State->contigIds[testPixel - 1] == contigId)) Map_State->scaffIds[--testPixel] = Scaff_Painting_Id;
+ testPixel = pixel;
+ while ((testPixel < (Number_of_Pixels_1D - 1)) && (Map_State->contigIds[testPixel + 1] == contigId)) Map_State->scaffIds[++testPixel] = Scaff_Painting_Id;
- glUseProgram(Flat_Shader->shaderProgram);
+ if (Scaff_FF_Flag & 1)
+ {
+ ++testPixel;
+ while ((testPixel < Number_of_Pixels_1D) && ((Scaff_FF_Flag & 2) || (Map_State->scaffIds[testPixel] == (Scaff_Painting_Flag == 1 ? 0 : currScaffId)))) Map_State->scaffIds[testPixel++] = Scaff_Painting_Id;
+ }
+ }
- vert[0].x = x - w2t; vert[0].y = y + lh;
- vert[1].x = x + w2t; vert[1].y = y + lh;
- vert[2].x = x + w2t; vert[2].y = y;
- vert[3].x = x - w2t; vert[3].y = y;
+ UpdateContigsFromMapState();
+ }
+ else if (Select_Sort_Area_Mode)
+ {
+ auto_curation_state.update_sort_area(Tool_Tip_Move.pixels.x, Map_State, Number_of_Pixels_1D);
+ }
+ else if (
+ MetaData_Edit_Mode &&
+ MetaData_Edit_State &&
+ strlen((const char *)Meta_Data->tags[MetaData_Active_Tag])
+ )
+ {
+ u32 pixel = Tool_Tip_Move.pixels.x;
+ u32 contigId = Map_State->contigIds[pixel];
- glBindBuffer(GL_ARRAY_BUFFER, Label_Box_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Label_Box_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ if (MetaData_Edit_State == 1)
+ Map_State->metaDataFlags[pixel] |= (1ULL << MetaData_Active_Tag); // set the active tag
+ else
+ Map_State->metaDataFlags[pixel] &= ~(1ULL << MetaData_Active_Tag); // clear the active tag
+
+ u32 testPixel = pixel;
+ while (testPixel && (Map_State->contigIds[testPixel - 1] == contigId))
+ {
+ if (MetaData_Edit_State == 1)
+ Map_State->metaDataFlags[--testPixel] |= (1ULL << MetaData_Active_Tag);
+ else
+ Map_State->metaDataFlags[--testPixel] &= ~(1ULL << MetaData_Active_Tag);
+ }
- glUseProgram(UI_Shader->shaderProgram);
- fonsDrawText(FontStash_Context, x, y, name, 0);
- }
+ testPixel = pixel;
+ while ((testPixel < (Number_of_Pixels_1D - 1)) && (Map_State->contigIds[testPixel + 1] == contigId))
+ {
+ if (MetaData_Edit_State == 1)
+ Map_State->metaDataFlags[++testPixel] |= (1ULL << MetaData_Active_Tag);
+ else
+ Map_State->metaDataFlags[++testPixel] &= ~(1ULL << MetaData_Active_Tag);
}
- topPixel = bottomPixel;
+ UpdateContigsFromMapState();
}
- ChangeSize((s32)width, (s32)height);
+ redisplay = 1;
}
- #define MaxTicksPerScaleBar 128
- if (File_Loaded && Scale_Bars->on) // Scale bars
+ if (Mouse_Move.x >= 0.0)
{
- glUseProgram(Flat_Shader->shaderProgram);
- glUniform4fv(Flat_Shader->colorLocation, 1, (GLfloat *)&Scale_Bars->bg);
- glUniformMatrix4fv(Flat_Shader->matLocation, 1, GL_FALSE, textNormalMat);
-
- glUseProgram(UI_Shader->shaderProgram);
- glUniformMatrix4fv(UI_Shader->matLocation, 1, GL_FALSE, textNormalMat);
-
- u32 ptr = 0;
- vertex vert[4];
-
- glViewport(0, 0, (s32)width, (s32)height);
+ s32 w, h;
+ glfwGetWindowSize(window, &w, &h);
+ f32 height = (f32)h;
- f32 lh = 0.0f;
+ f32 factor = 1.0f / (height * Camera_Position.z);
+ f32 dx = (f32)(Mouse_Move.x - x) * factor;
+ f32 dy = (f32)(y - Mouse_Move.y) * factor;
- fonsClearState(FontStash_Context);
- fonsSetSize(FontStash_Context, Scale_Bars->size * Screen_Scale.x);
- fonsSetAlign(FontStash_Context, FONS_ALIGN_CENTER | FONS_ALIGN_TOP);
- fonsSetFont(FontStash_Context, Font_Normal);
- fonsVertMetrics(FontStash_Context, 0, 0, &lh);
- fonsSetColor(FontStash_Context, FourFloatColorToU32(Scale_Bars->fg));
+ Camera_Position.x += dx;
+ Camera_Position.y += dy;
+ ClampCamera();
- f32 leftPixel = ModelXToScreen(-0.5f);
- f32 rightPixel = ModelXToScreen(0.5f);
- f32 wy0 = ModelYToScreen(0.5);
- f32 offset = 45.0f * Screen_Scale.x;
- f32 y = my_Max(wy0, 0.0f) + offset;
- f32 totalLength = 0.0f;
+ Mouse_Move.x = x;
+ Mouse_Move.y = y;
- f32 bpPerPixel = (f32)((f64)Total_Genome_Length / (f64)(rightPixel - leftPixel));
+ redisplay = 1;
+ }
+ }
- GLfloat *bg = (GLfloat *)&Scale_Bars->bg;
-
- f32 scaleBarWidth = Scale_Bars->size * 4.0f / 20.0f * Screen_Scale.x;
- f32 tickLength = Scale_Bars->size * 3.0f / 20.0f * Screen_Scale.x;
+ if (redisplay)
+ {
+ Redisplay = 1;
+ }
+}
- ForLoop(Contigs->numberOfContigs)
- {
- contig *cont = Contigs->contigs_arr + index;
-
- totalLength += (f32)((f64)cont->length / (f64)Number_of_Pixels_1D);
- rightPixel = ModelXToScreen(totalLength - 0.5f);
- f32 pixelLength = rightPixel - leftPixel;
- f32 startCoord = (f32)((f64)(IsContigInverted(index) ? (cont->startCoord - cont->length) : cont->startCoord) * (f64)Total_Genome_Length / (f64)Number_of_Pixels_1D);
- u32 labelLevels = SubDivideScaleBar(leftPixel, rightPixel, (leftPixel + rightPixel) * 0.5f, bpPerPixel, startCoord);
- u32 labels = 0;
- ForLoop2(labelLevels)
- {
- labels += (labels + 1);
- }
- labels = my_Min(labels, MaxTicksPerScaleBar);
+global_function
+void
+Mouse(GLFWwindow* window, s32 button, s32 action, s32 mods)
+{
+ s32 primaryMouse = user_profile_settings_ptr->invert_mouse ? GLFW_MOUSE_BUTTON_RIGHT : GLFW_MOUSE_BUTTON_LEFT;
+ s32 secondaryMouse = user_profile_settings_ptr->invert_mouse ? GLFW_MOUSE_BUTTON_LEFT : GLFW_MOUSE_BUTTON_RIGHT;
+
+ if (Loading || auto_sort_state)
+ {
+ return;
+ }
+
+ (void)mods;
- if (rightPixel > 0.0f && leftPixel < width)
- {
- if (labels)
- {
- glUseProgram(Flat_Shader->shaderProgram);
- glUniform4fv(Flat_Shader->colorLocation, 1, bg);
+ f64 x, y;
+ glfwGetCursorPos(window, &x, &y);
- vert[0].x = leftPixel + 1.0f; vert[0].y = y + scaleBarWidth + tickLength + 1.0f + lh;
- vert[1].x = rightPixel - 1.0f; vert[1].y = y + scaleBarWidth + tickLength + 1.0f + lh;
- vert[2].x = rightPixel - 1.0f; vert[2].y = y;
- vert[3].x = leftPixel + 1.0f; vert[3].y = y;
+ if (UI_On)
+ {
+ if (button == GLFW_MOUSE_BUTTON_MIDDLE && action == GLFW_PRESS)
+ {
+ Deferred_Close_UI = 1;
+ }
+ }
+ else // UI not on
+ {
+ if (button == primaryMouse && Edit_Mode && action == GLFW_PRESS)
+ {
+ Edit_Pixels.editing = !Edit_Pixels.editing;
+ MouseMove(window, x, y);
+ if (!Edit_Pixels.editing) UpdateScaffolds();
+ }
+ else if (button == GLFW_MOUSE_BUTTON_MIDDLE && Edit_Mode && action == GLFW_RELEASE && !Edit_Pixels.editing)
+ {
+ Edit_Pixels.editing = 1;
+ Edit_Pixels.selecting = 0;
+ MouseMove(window, x, y);
+ }
+ else if (button == GLFW_MOUSE_BUTTON_MIDDLE && Edit_Mode && action == GLFW_PRESS && !Edit_Pixels.editing)
+ {
+ Edit_Pixels.selecting = 1;
+ Edit_Pixels.selectPixels = Edit_Pixels.pixels;
+ MouseMove(window, x, y);
+ }
+ else if (button == GLFW_MOUSE_BUTTON_MIDDLE && Edit_Mode && Edit_Pixels.editing && action == GLFW_PRESS)
+ {
+ InvertMap(Edit_Pixels.pixels.x, Edit_Pixels.pixels.y);
+ Global_Edit_Invert_Flag = !Global_Edit_Invert_Flag;
+ UpdateContigsFromMapState();
- glBindBuffer(GL_ARRAY_BUFFER, Scale_Bar_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Scale_Bar_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ Redisplay = 1;
+ }
+ else if (button == primaryMouse && Waypoint_Edit_Mode && action == GLFW_PRESS)
+ {
+ AddWayPoint(Tool_Tip_Move.worldCoords);
+ MouseMove(window, x, y);
+ }
+ else if (button == GLFW_MOUSE_BUTTON_MIDDLE && Waypoint_Edit_Mode && action == GLFW_PRESS)
+ {
+ if (Selected_Waypoint)
+ {
+ RemoveWayPoint(Selected_Waypoint);
+ MouseMove(window, x, y);
+ }
+ }
+ else if (button == primaryMouse && Scaff_Edit_Mode && action == GLFW_PRESS)
+ {
+ Scaff_Painting_Flag = 1;
+ MouseMove(window, x, y);
+ }
+ else if (button == GLFW_MOUSE_BUTTON_MIDDLE && Scaff_Edit_Mode && action == GLFW_PRESS)
+ {
+ Scaff_Painting_Flag = 2;
+ MouseMove(window, x, y);
+ }
+ else if ((button == GLFW_MOUSE_BUTTON_MIDDLE || button == primaryMouse) && Scaff_Edit_Mode && action == GLFW_RELEASE)
+ {
+ Scaff_Painting_Flag = 0;
+ Scaff_Painting_Id = 0;
+ MouseMove(window, x, y);
+ UpdateScaffolds();
+ }
+ else if (button == primaryMouse && Select_Sort_Area_Mode && action == GLFW_PRESS)
+ {
+ auto_curation_state.select_mode = 1;
+ MouseMove(window, x, y);
+ }
+ else if (button == primaryMouse && Select_Sort_Area_Mode && action == GLFW_RELEASE)
+ {
+ auto_curation_state.select_mode = 0;
+ MouseMove(window, x, y);
+ }
+ else if (button == primaryMouse && MetaData_Edit_Mode && action == GLFW_PRESS)
+ {
+ MetaData_Edit_State = 1;
+ MouseMove(window, x, y);
+ }
+ else if (button == GLFW_MOUSE_BUTTON_MIDDLE && MetaData_Edit_Mode && action == GLFW_PRESS)
+ {
+ MetaData_Edit_State = 2;
+ MouseMove(window, x, y);
+ }
+ else if ((button == GLFW_MOUSE_BUTTON_MIDDLE || button == primaryMouse) && MetaData_Edit_Mode && action == GLFW_RELEASE)
+ {
+ MetaData_Edit_State = 0;
+ MouseMove(window, x, y);
+ }
+ else if (button == secondaryMouse)
+ {
+ if (action == GLFW_PRESS)
+ {
+ Mouse_Move.x = x;
+ Mouse_Move.y = y;
+ }
+ else
+ {
+ Mouse_Move.x = Mouse_Move.y = -1.0;
+ }
+ }
+ else if (button == GLFW_MOUSE_BUTTON_MIDDLE && action == GLFW_PRESS)
+ {
+ UI_On = !UI_On;
+ Mouse_Move.x = Mouse_Move.y = -1;
+ Redisplay = 1;
+ ++NK_Device->lastContextMemory[0];
+ }
+ }
+}
- glUniform4fv(Flat_Shader->colorLocation, 1, (f32 *)&Scale_Bars->fg);
+global_variable
+struct nk_vec2
+NK_Scroll;
- vert[0].x = leftPixel + 1.0f; vert[0].y = y + scaleBarWidth;
- vert[1].x = rightPixel - 1.0f; vert[1].y = y + scaleBarWidth;
- vert[2].x = rightPixel - 1.0f; vert[2].y = y;
- vert[3].x = leftPixel + 1.0f; vert[3].y = y;
+global_function
+void
+Scroll(GLFWwindow* window, f64 x, f64 y)
+{
+ if (Loading || auto_sort_state)
+ {
+ return;
+ }
+
+ if (UI_On)
+ {
+ NK_Scroll.y = (f32)y;
+ NK_Scroll.x = (f32)x;
+ }
+ else
+ {
+ if (y != 0.0)
+ {
+ ZoomCamera(my_Max(my_Min((f32)y, 0.01f), -0.01f));
+ Redisplay = 1;
+ }
- glBindBuffer(GL_ARRAY_BUFFER, Scale_Bar_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Scale_Bar_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ if (Edit_Mode || Tool_Tip->on || Waypoint_Edit_Mode)
+ {
+ f64 mousex, mousey;
+ glfwGetCursorPos(window, &mousex, &mousey);
+ MouseMove(window, mousex, mousey);
+ }
+ }
+}
- f32 fraction = 1.0f / (f32)(labels + 1);
- f32 distance = 0.0f;
- ForLoop2(labels)
- {
- distance += fraction;
- f32 x = (pixelLength * distance) + (f32)leftPixel;
+global_variable
+u64
+Total_Genome_Length;
- glUseProgram(Flat_Shader->shaderProgram);
+global_function
+void
+Setup();
- vert[0].x = x - (0.5f * scaleBarWidth); vert[0].y = y + scaleBarWidth + tickLength;
- vert[1].x = x + (0.5f * scaleBarWidth); vert[1].y = y + scaleBarWidth + tickLength;
- vert[2].x = x + (0.5f * scaleBarWidth); vert[2].y = y + scaleBarWidth;
- vert[3].x = x - (0.5f * scaleBarWidth); vert[3].y = y + scaleBarWidth;
+global_function
+u32
+SubDivideScaleBar(f32 left, f32 right, f32 middle, f32 bpPerPixel, f32 offset)
+{
+ u32 result = 0;
- glBindBuffer(GL_ARRAY_BUFFER, Scale_Bar_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Scale_Bar_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ if (left < right)
+ {
+ f32 length = right - left;
+ f32 half = length * 0.5f;
+ char buff[16];
+ stbsp_snprintf(buff, 16, "%$.2f", (f64)(offset + (half * bpPerPixel)));
+ f32 width = fonsTextBounds(FontStash_Context, middle, 0.0, buff, 0, NULL);
+ f32 halfWidth = 0.5f * width;
- char buff[16];
- stbsp_snprintf(buff, 16, "%$.2f", (f64)(startCoord + (pixelLength * (IsContigInverted(index) ? (1.0f - distance) : distance) * bpPerPixel)));
- glUseProgram(UI_Shader->shaderProgram);
- fonsDrawText(FontStash_Context, x, y + scaleBarWidth + tickLength + 1.0f, buff, 0);
- }
- }
- }
+ if ((middle + halfWidth) < right && (middle - halfWidth) > left)
+ {
+ u32 leftResult = SubDivideScaleBar(left, middle - halfWidth, (left + middle) * 0.5f, bpPerPixel, offset);
+ u32 rightResult = SubDivideScaleBar(middle + halfWidth, right, (right + middle) * 0.5f, bpPerPixel, offset);
+ result = 1 + my_Min(leftResult, rightResult);
+ }
+ }
- leftPixel = rightPixel;
- }
+ return(result);
+}
- ChangeSize((s32)width, (s32)height);
- }
-
- // Finished - add the cross line to the waypoint
- if (File_Loaded && (Waypoint_Edit_Mode || Waypoints_Always_Visible)) // Waypoint Edit Mode
- {
- u32 ptr = 0;
- vertex vert[4];
-
- glUseProgram(Flat_Shader->shaderProgram);
- glUniformMatrix4fv(Flat_Shader->matLocation, 1, GL_FALSE, textNormalMat);
- glUseProgram(UI_Shader->shaderProgram);
- glUniformMatrix4fv(UI_Shader->matLocation, 1, GL_FALSE, textNormalMat);
+global_variable
+u32
+File_Loaded = 0;
- glViewport(0, 0, (s32)width, (s32)height);
-#define DefaultWaypointSize 18.0f
- glUseProgram(Flat_Shader->shaderProgram);
- glUniform4fv(Flat_Shader->colorLocation, 1, (f32 *)&Waypoint_Mode_Data->base);
+global_variable
+nk_color
+Theme_Colour;
- // define the vertical line
- f32 lineWidth = Waypoint_Mode_Data->size / DefaultWaypointSize * 0.7f * Screen_Scale.x;
- f32 lineHeight = Waypoint_Mode_Data->size / DefaultWaypointSize * 8.0f * Screen_Scale.x;
+#ifdef Internal
+global_function
+void
+DrawQuadTreeLevel (u32 *ptr, waypoint_quadtree_level *level, vertex *vert, f32 lineWidth, u32 n = 0)
+{
+ f32 colour[5][4] = {{1.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 1.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f, 1.0f}, {1.0f, 0.0f, 1.0f, 1.0f}, {0.0f, 1.0f, 1.0f, 1.0f}};
+ f32 *col = (f32 *)colour[n%5];
- f32 lh = 0.0f;
+ glUniform4fv(Flat_Shader->colorLocation, 1, col);
+
+ if (level->show)
+ {
+ vert[0].x = level->lowerBound.x;
+ vert[0].y = -level->lowerBound.y;
+ vert[1].x = level->lowerBound.x;
+ vert[1].y = -level->lowerBound.y - level->size;
+ vert[2].x = level->lowerBound.x + lineWidth;
+ vert[2].y = -level->lowerBound.y - level->size;
+ vert[3].x = level->lowerBound.x + lineWidth;
+ vert[3].y = -level->lowerBound.y;
- u32 baseColour = FourFloatColorToU32(Waypoint_Mode_Data->base);
- u32 selectColour = FourFloatColorToU32(Waypoint_Mode_Data->selected);
-
- fonsClearState(FontStash_Context);
- fonsSetSize(FontStash_Context, Waypoint_Mode_Data->size * Screen_Scale.x);
- fonsSetAlign(FontStash_Context, FONS_ALIGN_LEFT | FONS_ALIGN_TOP);
- fonsSetFont(FontStash_Context, Font_Bold);
- fonsVertMetrics(FontStash_Context, 0, 0, &lh);
- fonsSetColor(FontStash_Context, baseColour);
+ glBindBuffer(GL_ARRAY_BUFFER, QuadTree_Data->vbos[*ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(QuadTree_Data->vaos[(*ptr)++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- char buff[4];
-
- // render the waypoints lines
- TraverseLinkedList(Waypoint_Editor->activeWaypoints.next, waypoint)
- {
- point2f screen = {ModelXToScreen(node->coords.x), ModelYToScreen(-node->coords.y)};
- point2f screenYRange = {ModelYToScreen(0.5f), ModelYToScreen(-0.5f)};
- point2f screenXRange = {ModelXToScreen(-0.5f), ModelXToScreen(0.5f)};
+ vert[0].x = level->lowerBound.x;
+ vert[0].y = -level->lowerBound.y - level->size;
+ vert[1].x = level->lowerBound.x + level->size;
+ vert[1].y = -level->lowerBound.y - level->size;
+ vert[2].x = level->lowerBound.x + level->size;
+ vert[2].y = -level->lowerBound.y - level->size + lineWidth;
+ vert[3].x = level->lowerBound.x;
+ vert[3].y = -level->lowerBound.y - level->size + lineWidth;
- glUseProgram(Flat_Shader->shaderProgram);
- if (node == Selected_Waypoint)
- {
- glUniform4fv(Flat_Shader->colorLocation, 1, (f32 *)&Waypoint_Mode_Data->selected);
- }
-
- bool long_horizontal, long_vertical;
- if (Long_Waypoints_Mode == 0) { // vertical line
- long_horizontal = false;
- long_vertical = true;
- } else if (Long_Waypoints_Mode == 1) { // horizontal line
- long_horizontal = true;
- long_vertical = false;
- } else { // cross line
- long_horizontal = true;
- long_vertical = true;
- }
+ glBindBuffer(GL_ARRAY_BUFFER, QuadTree_Data->vbos[*ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(QuadTree_Data->vaos[(*ptr)++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- // draw the vertical line
- vert[0].x = screen.x - lineWidth; vert[0].y = long_vertical ? screenYRange.x : screen.y - lineHeight;
- vert[1].x = screen.x - lineWidth; vert[1].y = long_vertical ? screenYRange.y : screen.y + lineHeight;
- vert[2].x = screen.x + lineWidth; vert[2].y = long_vertical ? screenYRange.y : screen.y + lineHeight;
- vert[3].x = screen.x + lineWidth; vert[3].y = long_vertical ? screenYRange.x : screen.y - lineHeight;
- glBindBuffer(GL_ARRAY_BUFFER, Waypoint_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Waypoint_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ vert[0].x = level->lowerBound.x + level->size - lineWidth;
+ vert[0].y = -level->lowerBound.y;
+ vert[1].x = level->lowerBound.x + level->size - lineWidth;
+ vert[1].y = -level->lowerBound.y - level->size;
+ vert[2].x = level->lowerBound.x + level->size;
+ vert[2].y = -level->lowerBound.y - level->size;
+ vert[3].x = level->lowerBound.x + level->size;
+ vert[3].y = -level->lowerBound.y;
- // draw the horizontal line (originally: the left part, not sure why Ed draw them seperately, if problem arises we can returen here) maybe avoid drawing the cross part twice...
- vert[0].x = long_horizontal ? screenXRange.x : screen.x - lineHeight; vert[0].y = screen.y - lineWidth;
- vert[1].x = long_horizontal ? screenXRange.x : screen.x - lineHeight; vert[1].y = screen.y + lineWidth;
- vert[2].x = long_horizontal ? screenXRange.y : screen.x + lineHeight; vert[2].y = screen.y + lineWidth;// vert[2].x = screen.x - lineWidth;
- vert[3].x = long_horizontal ? screenXRange.y : screen.x + lineHeight; vert[3].y = screen.y - lineWidth;// vert[3].x = screen.x - lineWidth;
- glBindBuffer(GL_ARRAY_BUFFER, Waypoint_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Waypoint_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ glBindBuffer(GL_ARRAY_BUFFER, QuadTree_Data->vbos[*ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(QuadTree_Data->vaos[(*ptr)++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- // draw the horizontal line (originally: the right part, not sure why Ed draw them seperately, if problem arises we can returen here)
- // vert[0].x = screen.x + lineWidth;
- // vert[0].y = screen.y - lineWidth;
- // vert[1].x = screen.x + lineWidth;
- // vert[1].y = screen.y + lineWidth;
- // vert[2].x = screen.x + lineHeight;
- // vert[2].y = screen.y + lineWidth;
- // vert[3].x = screen.x + lineHeight;
- // vert[3].y = screen.y - lineWidth;
- // glBindBuffer(GL_ARRAY_BUFFER, Waypoint_Data->vbos[ptr]);
- // glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- // glBindVertexArray(Waypoint_Data->vaos[ptr++]);
- // glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
-
- if (node == Selected_Waypoint)
- {
- glUniform4fv(Flat_Shader->colorLocation, 1, (f32 *)&Waypoint_Mode_Data->base);
- }
+ vert[0].x = level->lowerBound.x;
+ vert[0].y = -level->lowerBound.y;
+ vert[1].x = level->lowerBound.x;
+ vert[1].y = -level->lowerBound.y - lineWidth;
+ vert[2].x = level->lowerBound.x + level->size;
+ vert[2].y = -level->lowerBound.y - lineWidth;
+ vert[3].x = level->lowerBound.x + level->size;
+ vert[3].y = -level->lowerBound.y;
- glUseProgram(UI_Shader->shaderProgram);
- if (node == Selected_Waypoint)
- {
- fonsSetColor(FontStash_Context, selectColour);
- }
-
- stbsp_snprintf(buff, sizeof(buff), "%d", node->index + 1);
- fonsDrawText(FontStash_Context, screen.x + lineWidth + lineWidth, screen.y - lineWidth - lh, buff, 0);
+ glBindBuffer(GL_ARRAY_BUFFER, QuadTree_Data->vbos[*ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(QuadTree_Data->vaos[(*ptr)++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ }
- if (node == Selected_Waypoint)
- {
- fonsSetColor(FontStash_Context, baseColour);
- }
- }
+ if (level->children[0])
+ {
+ ForLoop(4)
+ {
+ DrawQuadTreeLevel(ptr, level->children[index], vert, lineWidth, n+1);
+ }
+ }
+}
+#endif
- if (Waypoint_Edit_Mode && !UI_On)
- {
- fonsSetSize(FontStash_Context, 24.0f * Screen_Scale.x);
- fonsVertMetrics(FontStash_Context, 0, 0, &lh);
- fonsSetColor(FontStash_Context, FourFloatColorToU32(Waypoint_Mode_Data->text));
+global_function
+u32
+FourFloatColorToU32(nk_colorf colour)
+{
+ return(glfonsRGBA((u08)(colour.r * 255.0f), (u08)(colour.g * 255.0f),
+ (u08)(colour.b * 255.0f), (u08)(colour.a * 255.0f)));
+}
- std::vector helpTexts = {
- (char*)"Waypoint Edit Mode",
- (char*)"W: exit",
- (char*)"Left Click: place",
- (char*)"Middle Click / Spacebar: delete",
- };
- if (Long_Waypoints_Mode == 2) {
- helpTexts.push_back((char*)"L: both directions");
- } else if (Long_Waypoints_Mode == 1) {
- helpTexts.push_back((char*)"L: horizontal");
- } else {
- helpTexts.push_back((char*)"L: vertical");
- }
+global_function
+u32
+ThreeFloatColorToU32(nk_colorf colour)
+{
+ return(glfonsRGBA((u08)(colour.r * 255.0f), (u08)(colour.g * 255.0f),
+ (u08)(colour.b * 255.0f), 255));
+}
- f32 textBoxHeight = lh;
- textBoxHeight *= (f32)helpTexts.size();
- textBoxHeight += (f32)helpTexts.size() - 1.0f;
- f32 spacing = 10.0f; // distance from the edge of the text box
+global_function
+void
+ColourGenerator(u32 index, f32 *rgb)
+{
+// #define RedFreq 1.666f
+// #define GreenFreq 2.666f
+// #define BlueFreq 3.666f
- // f32 textWidth = fonsTextBounds(FontStash_Context, 0, 0, helpText4, 0, NULL);
- f32 textWidth = 0;
- for (auto i : helpTexts){
- textWidth = my_Max(textWidth, fonsTextBounds(FontStash_Context, 0, 0, i, 0, NULL)) + 0.5f * spacing;
- }
+// rgb[0] = 0.5f * (sinf((f32)index * RedFreq) + 1.0f);
+// rgb[1] = 0.5f * (sinf((f32)index * GreenFreq) + 1.0f);
+// rgb[2] = 0.5f * (sinf((f32)index * BlueFreq) + 1.0f);
- glUseProgram(Flat_Shader->shaderProgram);
- glUniform4fv(Flat_Shader->colorLocation, 1, (f32 *)&Waypoint_Mode_Data->bg);
+ f32 RedFreq = meta_dataColors[meta_data_curcolorProfile][0];
+ f32 GreenFreq = meta_dataColors[meta_data_curcolorProfile][1];
+ f32 BlueFreq = meta_dataColors[meta_data_curcolorProfile][2];
- vert[0].x = width - spacing - textWidth; vert[0].y = height - spacing - textBoxHeight;
- vert[1].x = width - spacing - textWidth; vert[1].y = height - spacing;
- vert[2].x = width - spacing; vert[2].y = height - spacing;
- vert[3].x = width - spacing; vert[3].y = height - spacing - textBoxHeight;
+ rgb[0] = 0.5f * (sinf((f32)index * RedFreq) + 1.0f);
+ rgb[1] = 0.5f * (sinf((f32)index * GreenFreq) + 1.0f);
+ rgb[2] = 0.5f * (sinf((f32)index * BlueFreq) + 1.0f);
+}
- glBindBuffer(GL_ARRAY_BUFFER, Waypoint_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Waypoint_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- glUseProgram(UI_Shader->shaderProgram);
+void DrawOutlinedText(
+ FONScontext *FontStash_Context,
+ nk_colorf *colour,
+ const char *text,
+ f32 x,
+ f32 y,
+ f32 offset = 1.0f,
+ bool outline_on = false)
+{
- for (u32 i=0; i< helpTexts.size() ; i++) {
- fonsDrawText(
- FontStash_Context,
- width - spacing - textWidth,
- height - spacing - textBoxHeight + (lh + 1.0f) * i,
- helpTexts[i],
- 0);
- }
- }
- }
-
- // Extension Mode
- if (Extension_Mode && !UI_On)
- {
- u32 ptr = 0;
- vertex vert[4];
- f32 lh = 0.0f;
+ nk_colorf outlineColor;
+ if (meta_outline->on == 1)
+ {
+ outlineColor = {0.0f, 0.0f, 0.0f, 1.0f}; // black
+ }
+ else
+ {
+ outlineColor = {1.0f, 1.0f, 1.0f, 1.0f}; // white
+ }
- glUseProgram(Flat_Shader->shaderProgram);
- glUniformMatrix4fv(Flat_Shader->matLocation, 1, GL_FALSE, textNormalMat);
- glUseProgram(UI_Shader->shaderProgram);
- glUniformMatrix4fv(UI_Shader->matLocation, 1, GL_FALSE, textNormalMat);
+ if (outline_on)
+ outlineColor = {0.0f, 0.0f, 0.0f, 1.0f}; // black
- glViewport(0, 0, (s32)width, (s32)height);
+ unsigned int outlineColorU32 = FourFloatColorToU32(outlineColor);
+ unsigned int textColorU32 = FourFloatColorToU32(*colour);
-#define DefaultExtensionSize 20.0f
- // glUseProgram(Flat_Shader->shaderProgram);
- // glUniform4fv(Flat_Shader->colorLocation, 1, (f32 *)&Waypoint_Mode_Data->base);
+ if (meta_outline->on > 0 || outline_on)
+ {
+ fonsSetColor(FontStash_Context, outlineColorU32);
+ fonsDrawText(FontStash_Context, x - offset, y - offset, text, 0);
+ fonsDrawText(FontStash_Context, x + offset, y - offset, text, 0);
+ fonsDrawText(FontStash_Context, x - offset, y + offset, text, 0);
+ fonsDrawText(FontStash_Context, x + offset, y + offset, text, 0);
+ }
- // f32 lineWidth = Waypoint_Mode_Data->size / DefaultWaypointSize * 0.7f * Screen_Scale.x;
- // f32 lineHeight = Waypoint_Mode_Data->size / DefaultWaypointSize * 8.0f * Screen_Scale.x;
+ // // Draw the original text on top
+ fonsSetColor(FontStash_Context, textColorU32);
+ fonsDrawText(FontStash_Context, x, y, text, 0);
+}
- fonsSetSize(FontStash_Context, 24.0f * Screen_Scale.x);
- fonsVertMetrics(FontStash_Context, 0, 0, &lh);
- fonsSetColor(FontStash_Context, FourFloatColorToU32(Extension_Mode_Data->text));
- f32 textBoxHeight = lh;
- textBoxHeight *= 7.0f;
- textBoxHeight += 6.0f;
- f32 spacing = 10.0f;
+global_variable
+char
+Extension_Magic_Bytes[][4] =
+{
+ {'p', 's', 'g', 'h'}
+};
- // 6 lines in total
- std::vector helpTexts = {
- "Extensions:",
- "X: exit"
- };
- if (Extensions.head)
- {
- TraverseLinkedList(Extensions.head, extension_node)
- {
- switch (node->type)
- {
- case extension_graph:
- {
- graph *gph = (graph *)node->extension;
- if (strstr((char*)gph->name, "coverage"))
- {
- helpTexts.push_back("C: Graph: coverage");
- }
- else if (strstr((char*)gph->name, "gap"))
- {
- helpTexts.push_back("G: Graph: gap");
- }
- else if (strstr((char*)gph->name, "repeat_density"))
- {
- helpTexts.push_back("R: Graph: repeat_density");
- }
- else if (strstr((char*)gph->name, "telomere"))
- {
- helpTexts.push_back("T: Graph: telomere");
- }
- }
- break;
- }
- }
- }
- f32 textWidth = 0.;
- for (auto i : helpTexts)
- {
- textWidth = my_Max(textWidth, fonsTextBounds(FontStash_Context, 0, 0, i.c_str(), 0, NULL)) ;
- }
- textWidth += 0.5f * spacing;
+global_variable
+extension_sentinel
+Extensions = {};
- glUseProgram(Flat_Shader->shaderProgram);
- glUniform4fv(Flat_Shader->colorLocation, 1, (f32 *)&Extension_Mode_Data->bg);
+global_function
+void
+AddExtension(extension_node *node)
+{
+ node->next = 0;
- vert[0].x = width - spacing - textWidth; vert[0].y = height - spacing - textBoxHeight;
- vert[1].x = width - spacing - textWidth; vert[1].y = height - spacing;
- vert[2].x = width - spacing; vert[2].y = height - spacing;
- vert[3].x = width - spacing; vert[3].y = height - spacing - textBoxHeight;
+ if (!Extensions.head)
+ {
+ Extensions.head = node;
+ Extensions.tail = node;
+ }
+ else
+ {
+ Extensions.tail->next = node; // append the last to the end
+ Extensions.tail = node; // set the last to the new node just appended
+ }
+}
- glBindBuffer(GL_ARRAY_BUFFER, Waypoint_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Waypoint_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+global_function
+void
+Render() {
+ // Projection Matrix
+ f32 width;
+ f32 height;
+ {
+ glClear(GL_COLOR_BUFFER_BIT);
+ // glClearColor(0.2f, 0.6f, 0.4f, 1.0f); // classic background color
+ glClearColor(bgcolor[active_bgcolor][0], bgcolor[active_bgcolor][1], bgcolor[active_bgcolor][2], bgcolor[active_bgcolor][3]);
- glUseProgram(UI_Shader->shaderProgram);
- for (u32 i=0; i< helpTexts.size() ; i++)
- {
- fonsDrawText(
- FontStash_Context,
- width - spacing - textWidth,
- height - spacing - textBoxHeight + (lh + 1.0f) * i,
- helpTexts[i].c_str(),
- 0);
- }
+ s32 viewport[4];
+ glGetIntegerv (GL_VIEWPORT, viewport);
+ width = (f32)viewport[2];
+ height = (f32)viewport[3];
+
+ f32 mat[16];
+ memset(mat, 0, sizeof(mat));
+ mat[0] = 2.0f * Camera_Position.z * height / width;
+ mat[5] = 2.0f * Camera_Position.z;
+ mat[10] = -2.0f;
+ mat[12] = -2.0f * height * Camera_Position.x * Camera_Position.z / width;
+ mat[13] = -2.0f * Camera_Position.y * Camera_Position.z;
+ mat[15] = 1.0f;
+
+ /*
+ template
+ GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> orthoRH_NO(T left, T right, T bottom, T top, T zNear, T zFar)
+ {
+ mat<4, 4, T, defaultp> Result(1);
+ Result[0][0] = static_cast(2) / (right - left); // 0
+ Result[1][1] = static_cast(2) / (top - bottom); // 5
+ Result[2][2] = - static_cast(2) / (zFar - zNear);// 10
+ Result[3][0] = - (right + left) / (right - left); // 12
+ Result[3][1] = - (top + bottom) / (top - bottom); // 13
+ Result[3][2] = - (zFar + zNear) / (zFar - zNear); // 14
+ return Result;
}
+ glm::mat4 projection_mat = glm::ortho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
+ */
- // label to show the selected sequence 从 input sequences 里面选中的片段
- if (Selected_Sequence_Cover_Countor.end_time > 0.)
- {
- f64 crt_time = GetTime();
- if (crt_time < Selected_Sequence_Cover_Countor.end_time)
- {
- char buff[128];
- f32 colour[4] = {1.0, 1.0, 1.0, 1.0};
- snprintf(buff, 128, "%s (%u)", (char *)((Original_Contigs+Selected_Sequence_Cover_Countor.original_contig_index)->name), Selected_Sequence_Cover_Countor.idx_within_original_contig+1);
+ // apply the transformation
+ glUseProgram(Contact_Matrix->shaderProgram);
+ glUniformMatrix4fv(Contact_Matrix->matLocation, 1, GL_FALSE, mat);
+ glUseProgram(Flat_Shader->shaderProgram);
+ glUniformMatrix4fv(Flat_Shader->matLocation, 1, GL_FALSE, mat);
- f32 textWidth = fonsTextBounds(FontStash_Context, 0, 0, (char *)buff, 0, NULL);
- ColourGenerator(65, colour);
- // position of text
- f32 textX = ModelXToScreen(
- (f32)Selected_Sequence_Cover_Countor.map_loc / (f32)Number_of_Pixels_1D -0.5f)
- - (0.5f * textWidth);
- f32 textY = ModelYToScreen( 0.5f - (f32)Selected_Sequence_Cover_Countor.map_loc / (f32)Number_of_Pixels_1D);
-
- glUseProgram(UI_Shader->shaderProgram);
- DrawOutlinedText(
- FontStash_Context,
- (nk_colorf *)colour,
- (char *)buff,
- textX,
- textY,
- 3.0f, true);
- Selected_Sequence_Cover_Countor.plotted = true;
- }
- else
+ TraverseLinkedList(Extensions.head, extension_node)
+ {
+ switch (node->type)
{
- Selected_Sequence_Cover_Countor.clear();
- Redisplay = 1;
+ case extension_graph:
+ {
+ graph *gph = (graph *)node->extension;
+ glUseProgram(gph->shader->shaderProgram);
+ glUniformMatrix4fv(gph->shader->matLocation, 1, GL_FALSE, mat);
+ }
+ break;
}
}
+ }
- // Scaff Bars
- if (File_Loaded && (Scaff_Edit_Mode || Scaffs_Always_Visible))
+ // Textures
+ if (File_Loaded)
+ {
+ glUseProgram(Contact_Matrix->shaderProgram);
+ glBindTexture(GL_TEXTURE_2D_ARRAY, Contact_Matrix->textures);
+ u32 ptr = 0;
+ while (ptr < Number_of_Textures_1D * Number_of_Textures_1D)
{
- glUseProgram(Flat_Shader->shaderProgram);
- glUniformMatrix4fv(Flat_Shader->matLocation, 1, GL_FALSE, textNormalMat);
- glUseProgram(UI_Shader->shaderProgram);
- glUniformMatrix4fv(UI_Shader->matLocation, 1, GL_FALSE, textNormalMat);
+ glBindVertexArray(Contact_Matrix->vaos[ptr++]); // bind the vertices and then draw the quad
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ }
+ }
- glViewport(0, 0, (s32)width, (s32)height);
+ #ifdef Internal
+ if (File_Loaded && Tiles->on)
+ {
+ glUseProgram(Flat_Shader->shaderProgram);
+ glUniform4fv(Flat_Shader->colorLocation, 1, (GLfloat *)&Tiles->bg);
- u32 ptr = 0;
- vertex vert[4];
- f32 barColour[4] = {1.0f, 1.0f, 1.0f, 0.5f};
+ u32 ptr = 0;
+ vertex vert[4];
- f32 lh = 0.0f;
- fonsClearState(FontStash_Context);
-#define DefaultScaffSize 40.0f
- fonsSetSize(FontStash_Context, Scaff_Mode_Data->size * Screen_Scale.x);
- fonsSetAlign(FontStash_Context, FONS_ALIGN_MIDDLE | FONS_ALIGN_TOP);
- fonsSetFont(FontStash_Context, Font_Bold);
- fonsVertMetrics(FontStash_Context, 0, 0, &lh);
+ f32 lineWidth = 0.001f / sqrtf(Camera_Position.z);
+ f32 position = 0.0f;
+ f32 spacing = 1.0f / (f32)Number_of_Textures_1D;
- char buff[128];
- f32 position = 0.0f;
- f32 start = 0.0f;
- u32 scaffId = Contigs->contigs_arr->scaffId;
- ForLoop(Contigs->numberOfContigs)
- {
- contig *cont = Contigs->contigs_arr + index;
+ vert[0].x = -0.5f;
+ vert[0].y = -0.5f;
+ vert[1].x = lineWidth - 0.5f;
+ vert[1].y = -0.5f;
+ vert[2].x = lineWidth - 0.5f;
+ vert[2].y = 0.5f;
+ vert[3].x = -0.5f;
+ vert[3].y = 0.5f;
- if (cont->scaffId != scaffId)
- {
- if (scaffId)
- {
- vert[0].x = ModelXToScreen(start - 0.5f); vert[0].y = ModelYToScreen(0.5f - start);
- vert[1].x = ModelXToScreen(start - 0.5f); vert[1].y = ModelYToScreen(0.5f - position);
- vert[2].x = ModelXToScreen(position - 0.5f); vert[2].y = ModelYToScreen(0.5f - position);
- vert[3].x = ModelXToScreen(position - 0.5f); vert[3].y = ModelYToScreen(0.5f - start);
+ glBindBuffer(GL_ARRAY_BUFFER, Texture_Tile_Grid->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Texture_Tile_Grid->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- ColourGenerator((u32)scaffId, (f32 *)barColour);
- u32 colour = ThreeFloatColorToU32(*((nk_colorf *)barColour));
+ f32 x = -0.5f;
+ ForLoop(Number_of_Textures_1D - 1)
+ {
+ position += spacing;
+ f32 px = x + lineWidth;
+ x = position - (0.5f * (lineWidth + 1.0f));
- glUseProgram(Flat_Shader->shaderProgram);
- glUniform4fv(Flat_Shader->colorLocation, 1, (GLfloat *)&barColour);
+ if (x > px)
+ {
+ vert[0].x = x;
+ vert[0].y = -0.5f;
+ vert[1].x = x + lineWidth;
+ vert[1].y = -0.5f;
+ vert[2].x = x + lineWidth;
+ vert[2].y = 0.5f;
+ vert[3].x = x;
+ vert[3].y = 0.5f;
- glBindBuffer(GL_ARRAY_BUFFER, Scaff_Bar_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Scaff_Bar_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ glBindBuffer(GL_ARRAY_BUFFER, Texture_Tile_Grid->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Texture_Tile_Grid->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ }
+ }
- glUseProgram(UI_Shader->shaderProgram);
- fonsSetColor(FontStash_Context, colour);
+ vert[0].x = 0.5f - lineWidth;
+ vert[0].y = -0.5f;
+ vert[1].x = 0.5f;
+ vert[1].y = -0.5f;
+ vert[2].x = 0.5f;
+ vert[2].y = 0.5f;
+ vert[3].x = 0.5f - lineWidth;
+ vert[3].y = 0.5f;
- stbsp_snprintf(buff, sizeof(buff), "Scaffold %u", scaffId);
- f32 textWidth = fonsTextBounds(FontStash_Context, 0, 0, buff, 0, NULL);
- fonsDrawText(FontStash_Context, ModelXToScreen(0.5f * (position + start - 1.0f)) - (0.5f * textWidth), ModelYToScreen(0.5f - start) - lh, buff, 0);
- }
+ glBindBuffer(GL_ARRAY_BUFFER, Texture_Tile_Grid->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Texture_Tile_Grid->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- start = position;
- scaffId = cont->scaffId;
- }
+ position = 0.0f;
- position += ((f32)cont->length / (f32)Number_of_Pixels_1D);
- }
+ vert[0].x = -0.5f;
+ vert[0].y = 0.5f - lineWidth;
+ vert[1].x = 0.5f;
+ vert[1].y = 0.5f - lineWidth;
+ vert[2].x = 0.5f;
+ vert[2].y = 0.5f;
+ vert[3].x = -0.5f;
+ vert[3].y = 0.5f;
- if (scaffId)
- {
- vert[0].x = ModelXToScreen(start - 0.5f); vert[0].y = ModelYToScreen(0.5f - start);
- vert[1].x = ModelXToScreen(start - 0.5f); vert[1].y = ModelYToScreen(0.5f - position);
- vert[2].x = ModelXToScreen(position - 0.5f); vert[2].y = ModelYToScreen(0.5f - position);
- vert[3].x = ModelXToScreen(position - 0.5f); vert[3].y = ModelYToScreen(0.5f - start);
+ glBindBuffer(GL_ARRAY_BUFFER, Texture_Tile_Grid->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Texture_Tile_Grid->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- ColourGenerator((u32)scaffId, (f32 *)barColour);
- u32 colour = FourFloatColorToU32(*((nk_colorf *)barColour));
+ f32 y = 0.5f;
+ ForLoop(Number_of_Textures_1D - 1)
+ {
+ position += spacing;
+ f32 py = y - lineWidth;
+ y = 1.0f - position + (0.5f * (lineWidth - 1.0f));
- glUseProgram(Flat_Shader->shaderProgram);
- glUniform4fv(Flat_Shader->colorLocation, 1, (GLfloat *)&barColour);
+ if (y < py)
+ {
+ vert[0].x = -0.5f;
+ vert[0].y = y - lineWidth;
+ vert[1].x = 0.5f;
+ vert[1].y = y - lineWidth;
+ vert[2].x = 0.5f;
+ vert[2].y = y;
+ vert[3].x = -0.5f;
+ vert[3].y = y;
- glBindBuffer(GL_ARRAY_BUFFER, Scaff_Bar_Data->vbos[ptr]);
+ glBindBuffer(GL_ARRAY_BUFFER, Texture_Tile_Grid->vbos[ptr]);
glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Scaff_Bar_Data->vaos[ptr++]);
+ glBindVertexArray(Texture_Tile_Grid->vaos[ptr++]);
glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ }
+ }
- glUseProgram(UI_Shader->shaderProgram);
- fonsSetColor(FontStash_Context, colour);
+ vert[0].x = -0.5f;
+ vert[0].y = -0.5f;
+ vert[1].x = 0.5f;
+ vert[1].y = -0.5f;
+ vert[2].x = 0.5f;
+ vert[2].y = lineWidth - 0.5f;
+ vert[3].x = -0.5f;
+ vert[3].y = lineWidth - 0.5f;
- stbsp_snprintf(buff, sizeof(buff), "Scaffold %u", scaffId);
- f32 textWidth = fonsTextBounds(FontStash_Context, 0, 0, buff, 0, NULL);
- fonsDrawText(FontStash_Context, ModelXToScreen(0.5f * (position + start - 1.0f)) - (0.5f * textWidth), ModelYToScreen(0.5f - start) - lh, buff, 0);
- }
+ glBindBuffer(GL_ARRAY_BUFFER, Texture_Tile_Grid->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Texture_Tile_Grid->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ }
- if (Scaff_Edit_Mode && !UI_On)
- {
- fonsSetSize(FontStash_Context, 24.0f * Screen_Scale.x);
- fonsVertMetrics(FontStash_Context, 0, 0, &lh);
- fonsSetColor(FontStash_Context, FourFloatColorToU32(Scaff_Mode_Data->text));
+ // Quad Trees
+ //if (Waypoint_Edit_Mode)
+ {
+ glUseProgram(Flat_Shader->shaderProgram);
+ glUniform4fv(Flat_Shader->colorLocation, 1, (GLfloat *)&QuadTrees->bg);
- f32 textBoxHeight = lh;
- textBoxHeight *= 7.0f;
- textBoxHeight += 6.0f;
- f32 spacing = 10.0f;
+ u32 ptr = 0;
+ vertex vert[4];
- std::vector helpTexts = {
- "Scaffold Edit Mode",
- "S: exit",
- "Left Click: place",
- "Middle Click / Spacebar: delete",
- "Shift-D: delete all",
- "A (Hold): flood fill",
- "Shift-A (Hold): flood fill and override"
- };
+ f32 lineWidth = 0.001f / sqrtf(Camera_Position.z);
- f32 textWidth =0.f;
- for (const auto& tmp:helpTexts)
- textWidth = std::max(textWidth, fonsTextBounds(FontStash_Context, 0, 0, tmp.c_str(), 0, NULL));
+ DrawQuadTreeLevel(&ptr, Waypoint_Editor->quadtree, vert, lineWidth);
+ }
+ #endif
+
+ // Extensions
+ u08 graphNamesOn = 0;
+ {
+ TraverseLinkedList(Extensions.head, extension_node)
+ {
+ switch (node->type)
+ {
+ case extension_graph:
+ {
+ graph *gph = (graph *)node->extension;
- glUseProgram(Flat_Shader->shaderProgram);
- glUniform4fv(Flat_Shader->colorLocation, 1, (f32 *)&Scaff_Mode_Data->bg);
+ if (gph->on)
+ {
+ if (gph->nameOn) graphNamesOn = 1;
- vert[0].x = width - spacing - textWidth; vert[0].y = height - spacing - textBoxHeight;
- vert[1].x = width - spacing - textWidth; vert[1].y = height - spacing;
- vert[2].x = width - spacing; vert[2].y = height - spacing;
- vert[3].x = width - spacing; vert[3].y = height - spacing - textBoxHeight;
+ f32 factor1 = 1.0f / (2.0f * Camera_Position.z);
+ f32 factor2 = 2.0f / height;
- glBindBuffer(GL_ARRAY_BUFFER, Waypoint_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Waypoint_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ f32 wy = (factor1 * (1.0f - (factor2 * (height - gph->base)))) + Camera_Position.y;
- glUseProgram(UI_Shader->shaderProgram);
- for (u32 i=0; i< helpTexts.size() ; i++)
- {
- fonsDrawText(
- FontStash_Context,
- width - spacing - textWidth,
- height - spacing - textBoxHeight + (lh + 1.0f) * i,
- helpTexts[i].c_str(),
- 0);
- }
+ glUseProgram(gph->shader->shaderProgram);
+ glUniform4fv(gph->shader->colorLocation, 1, (GLfloat *)&gph->colour);
+ glUniform1f(gph->shader->yScaleLocation, gph->scale);
+ glUniform1f(gph->shader->yTopLocation, wy);
+ glUniform1f(gph->shader->lineSizeLocation, gph->lineSize / Camera_Position.z);
+
+ glBindBuffer(GL_ARRAY_BUFFER, gph->vbo);
+ glBindVertexArray(gph->vao);
+ glDrawArrays(GL_LINE_STRIP, 0, (GLsizei)Number_of_Pixels_1D);
+ }
+ }
+ break;
}
- } // scaff_mode
+ }
+ }
- // draw the screen for select fragments for sorting
- if (File_Loaded && !UI_On && Select_Sort_Area_Mode)
- {
- f32 lh = 0.f;
- f32 start_fraction = (f32)auto_curation_state.get_start()/(f32)Number_of_Pixels_1D;
- f32 end_fraction = (f32)auto_curation_state.get_end() /(f32)Number_of_Pixels_1D;
+ // Grid
+ if (File_Loaded && Grid->on)
+ {
+ glUseProgram(Flat_Shader->shaderProgram);
+ glUniform4fv(Flat_Shader->colorLocation, 1, (GLfloat *)&Grid->bg);
- // selected frags into a string
- SelectArea select_area;
- auto_curation_state.get_selected_fragments(select_area, Map_State, Number_of_Pixels_1D, Contigs);
+ u32 ptr = 0;
+ vertex vert[4];
- { // draw the help text in the bottom right corner
- fonsSetFont(FontStash_Context, Font_Bold);
- fonsSetSize(FontStash_Context, 24.0f * Screen_Scale.x);
- fonsVertMetrics(FontStash_Context, 0, 0, &lh);
- fonsSetColor(FontStash_Context, FourFloatColorToU32(Scaff_Mode_Data->text));
+ f32 lineWidth = Grid->size / sqrtf(Camera_Position.z);
+ f32 position = 0.0f;
- std::vector helpTexts = {
- "Select/Exclude area for sorting",
- "F: exit",
- "S: clear select area",
- "C/Z: cut / cancel cut",
- "Q/W: quit / redo edit",
- "Space: Pixel sort",
- "Left Click: un/select the fragment",
- fmt::format("Up/Down: inc/dec Cut threshold: {:.4f}", auto_curation_state.auto_cut_threshold).c_str(),
- fmt::format("Left/Right: change Sort Mode ({})", auto_curation_state.sort_mode_names[auto_curation_state.sort_mode]),
- // fmt::format("Selected fragments number: {}", select_area.selected_frag_ids.size()),
- // fmt::format("Select pixel range: {} - {}", auto_curation_state.get_start(), auto_curation_state.get_end())
- };
+ // left border
+ vert[0].x = -0.5f; vert[0].y = -0.5f;
+ vert[1].x = lineWidth - 0.5f; vert[1].y = -0.5f;
+ vert[2].x = lineWidth - 0.5f; vert[2].y = 0.5f;
+ vert[3].x = -0.5f; vert[3].y = 0.5f;
- f32 textBoxHeight = (f32)helpTexts.size() * (lh + 1.0f) - 1.0f;
- f32 spacing = 10.0f;
+ glBindBuffer(GL_ARRAY_BUFFER, Grid_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Grid_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- f32 textWidth = 0.f;
- for (const auto& i :helpTexts){
- textWidth = my_Max(textWidth, fonsTextBounds(FontStash_Context, 0, 0, i.c_str(), 0, NULL));
- }
- textWidth = my_Min(textWidth, width - 2 * spacing);
+ f32 x = -0.5f;
+ ForLoop(Contigs->numberOfContigs - 1)
+ {
+ contig *cont = Contigs->contigs_arr + index;
- glUseProgram(Flat_Shader->shaderProgram);
- glUniform4fv(Flat_Shader->colorLocation, 1, (f32 *)&Scaff_Mode_Data->bg);
- point2f vert[4];
- vert[0].x = width - spacing - textWidth; vert[0].y = height - spacing - textBoxHeight;
- vert[1].x = width - spacing - textWidth; vert[1].y = height - spacing;
- vert[2].x = width - spacing; vert[2].y = height - spacing;
- vert[3].x = width - spacing; vert[3].y = height - spacing - textBoxHeight;
-
- u32 ptr = 0;
- glBindBuffer(GL_ARRAY_BUFFER, Edit_Mode_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Edit_Mode_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ position += ((f32)cont->length / (f32)Number_of_Pixels_1D);
+ f32 px = x + lineWidth;
+ x = position - (0.5f * (lineWidth + 1.0f));
- glUseProgram(UI_Shader->shaderProgram);
+ if (x > px)
+ {
+ // contig vertical line
+ vert[0].x = x; vert[0].y = -0.5f;
+ vert[1].x = x + lineWidth; vert[1].y = -0.5f;
+ vert[2].x = x + lineWidth; vert[2].y = 0.5f;
+ vert[3].x = x; vert[3].y = 0.5f;
- for (int i = 0; i < helpTexts.size(); i++)
- {
- fonsDrawText(
- FontStash_Context,
- width - spacing - textWidth,
- height - spacing - textBoxHeight + (i * (lh + 1.0f)),
- helpTexts[i].c_str(),
- 0);
- }
+ glBindBuffer(GL_ARRAY_BUFFER, Grid_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Grid_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
}
+ }
+ // right border
+ vert[0].x = 0.5f - lineWidth; vert[0].y = -0.5f;
+ vert[1].x = 0.5f; vert[1].y = -0.5f;
+ vert[2].x = 0.5f; vert[2].y = 0.5f;
+ vert[3].x = 0.5f - lineWidth; vert[3].y = 0.5f;
- { // paint the selected area
- if (start_fraction >= 0 && end_fraction >= 0 )
- {
- u32 ptr = 0;
- point2f vert[4];
+ glBindBuffer(GL_ARRAY_BUFFER, Grid_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Grid_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- // draw the start & end point
- {
- f32 line_width = 0.002f / Camera_Position.z;
- f32 mask_color[4] = {1.0f, 0.f, 0.f, 0.8f}; // red
- glUseProgram(Flat_Shader->shaderProgram);
- glUniform4fv(Flat_Shader->colorLocation, 1, (GLfloat *)&mask_color);
- for (auto loc_fraction : {start_fraction, end_fraction})
- {
- vert[0].x = ModelXToScreen(loc_fraction - 0.5f - line_width); vert[0].y = ModelYToScreen(0.5f - loc_fraction + line_width);
- vert[1].x = ModelXToScreen(loc_fraction - 0.5f - line_width); vert[1].y = ModelYToScreen(0.5f - loc_fraction - line_width);
- vert[2].x = ModelXToScreen(loc_fraction - 0.5f + line_width); vert[2].y = ModelYToScreen(0.5f - loc_fraction - line_width);
- vert[3].x = ModelXToScreen(loc_fraction - 0.5f + line_width); vert[3].y = ModelYToScreen(0.5f - loc_fraction + line_width);
+ position = 0.0f;
+ // top border
+ vert[0].x = -0.5f; vert[0].y = 0.5f - lineWidth;
+ vert[1].x = 0.5f; vert[1].y = 0.5f - lineWidth;
+ vert[2].x = 0.5f; vert[2].y = 0.5f;
+ vert[3].x = -0.5f; vert[3].y = 0.5f;
- glBindBuffer(GL_ARRAY_BUFFER, Scaff_Bar_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Scaff_Bar_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- }
- }
+ glBindBuffer(GL_ARRAY_BUFFER, Grid_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Grid_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- // draw the cover on selected area
- {
- // f32 mask_color[4] = {0.906f, 0.03921f, 0.949f, 0.5f};
- vert[0].x = ModelXToScreen(start_fraction - 0.5f); vert[0].y = ModelYToScreen(0.5f - start_fraction);
- vert[1].x = ModelXToScreen(start_fraction - 0.5f); vert[1].y = ModelYToScreen(0.5f - end_fraction);
- vert[2].x = ModelXToScreen(end_fraction - 0.5f); vert[2].y = ModelYToScreen(0.5f - end_fraction);
- vert[3].x = ModelXToScreen(end_fraction - 0.5f); vert[3].y = ModelYToScreen(0.5f - start_fraction);
+ f32 y = 0.5f;
+ ForLoop(Contigs->numberOfContigs - 1)
+ {
+ contig *cont = Contigs->contigs_arr + index;
- f32 font_color[4] = {0.f, 0.f, 0.f, 1.f};
- u32 colour = FourFloatColorToU32(*((nk_colorf *)font_color));
+ position += ((f32)cont->length / (f32)Number_of_Pixels_1D);
+ f32 py = y - lineWidth;
+ y = 1.0f - position + (0.5f * (lineWidth - 1.0f));
- glUseProgram(Flat_Shader->shaderProgram);
- glUniform4fv(Flat_Shader->colorLocation, 1, (GLfloat *)&auto_curation_state.mask_color);
+ if (y < py)
+ {
+ // contig horizontal line
+ vert[0].x = -0.5f; vert[0].y = y - lineWidth;
+ vert[1].x = 0.5f; vert[1].y = y - lineWidth;
+ vert[2].x = 0.5f; vert[2].y = y;
+ vert[3].x = -0.5f; vert[3].y = y;
- glBindBuffer(GL_ARRAY_BUFFER, Scaff_Bar_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Scaff_Bar_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ glBindBuffer(GL_ARRAY_BUFFER, Grid_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Grid_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ }
+ }
+ // bottom border
+ vert[0].x = -0.5f; vert[0].y = -0.5f;
+ vert[1].x = 0.5f; vert[1].y = -0.5f;
+ vert[2].x = 0.5f; vert[2].y = lineWidth - 0.5f;
+ vert[3].x = -0.5f; vert[3].y = lineWidth - 0.5f;
- glUseProgram(UI_Shader->shaderProgram);
- fonsSetColor(FontStash_Context, colour);
-
- std::string buff = fmt::format(
- "{}: ({}) pixels, ({}) fragments",
- auto_curation_state.selected_or_exclude==0?"Selected" :"Excluded",
- std::abs(auto_curation_state.get_end() - auto_curation_state.get_start()),
- select_area.selected_frag_ids.size());
+ glBindBuffer(GL_ARRAY_BUFFER, Grid_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Grid_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ }
- f32 lh = 0.0f;
- f32 textWidth = fonsTextBounds(FontStash_Context, 0, 0, buff.c_str(), 0, NULL);
- fonsDrawText(
- FontStash_Context,
- ModelXToScreen( 0.5f * (end_fraction + start_fraction ) - 0.5f) - (0.5f * textWidth),
- ModelYToScreen(0.5f - 0.5f*(start_fraction + end_fraction)) - lh * 0.5f, buff.c_str(), 0);
- }
- }
- }
- } // select_sort_area
+ // Contig Id Bars
+ if (File_Loaded && Contig_Ids->on)
+ {
+ glUseProgram(Flat_Shader->shaderProgram);
+ glUniform4fv(Flat_Shader->colorLocation, 1, (GLfloat *)&Grid->bg);
- // Meta Tags
- if (File_Loaded && (MetaData_Edit_Mode || MetaData_Always_Visible))
- {
- glUseProgram(Flat_Shader->shaderProgram);
- glUniformMatrix4fv(Flat_Shader->matLocation, 1, GL_FALSE, textNormalMat);
- glUseProgram(UI_Shader->shaderProgram);
- glUniformMatrix4fv(UI_Shader->matLocation, 1, GL_FALSE, textNormalMat);
+ u32 ptr = 0;
+ vertex vert[4];
- glViewport(0, 0, (s32)width, (s32)height);
+ f32 barColour[4] = {1.0f, 1.0f, 1.0f, 1.0f};
- f32 colour[4] = {1.0f, 1.0f, 1.0f, 1.0f};
- vertex vert[4];
- u32 ptr = 0;
- f32 barColour[4] = {1.0f, 1.0f, 1.0f, 0.5f};
+ f32 lineWidth = Contig_Ids->size / sqrtf(Camera_Position.z);
+ f32 position = 0.0f;
- f32 lh = 0.0f;
- fonsClearState(FontStash_Context);
-#define DefaultMetaDataSize 20.0f
- fonsSetSize(FontStash_Context, MetaData_Mode_Data->size * Screen_Scale.x);
- fonsSetAlign(FontStash_Context, FONS_ALIGN_MIDDLE | FONS_ALIGN_TOP);
- fonsSetFont(FontStash_Context, Font_Bold);
- fonsVertMetrics(FontStash_Context, 0, 0, &lh);
+ f32 y = 0.5f;
+ ForLoop(Contigs->numberOfContigs)
+ {
+ contig *cont = Contigs->contigs_arr + index;
- f32 end_contig = 0.0f, start_contig = 0.0f;
- u32 scaffId = Contigs->contigs_arr->scaffId;
- ForLoop(Contigs->numberOfContigs)
+ position += ((f32)cont->length / (f32)Number_of_Pixels_1D);
+ f32 py = y - lineWidth;
+ y = 1.0f - position + (0.5f * (lineWidth - 1.0f));
+
+ if (y < py)
{
- contig *cont = Contigs->contigs_arr + index;
- end_contig += ((f32)cont->length / (f32)Number_of_Pixels_1D); // end of the contig
- if (*cont->metaDataFlags)
- {
- u32 tmp = 0; // used to count the number of tags drawn
- bool haplotigTagged = false;
- ForLoop2(ArrayCount(Meta_Data->tags))
- {
- if (*cont->metaDataFlags & ((u64)1 << index2))
- {
- f32 textWidth = fonsTextBounds(FontStash_Context, 0, 0, (char *)Meta_Data->tags[index2], 0, NULL);
- ColourGenerator(index2 + 1, colour);
- // fonsSetColor(FontStash_Context, FourFloatColorToU32(*((nk_colorf *)colour)));
- // fonsDrawText(FontStash_Context, ModelXToScreen(0.5f * (end_contig + start_contig - 1.0f)) - (0.5f * textWidth), ModelYToScreen((0.5f * (1.0f - end_contig - start_contig))) - (lh * (f32)(++tmp)), (char *)Meta_Data->tags[index2], 0);
- if (meta_outline->on)
- {
- // position of text
- f32 textX = ModelXToScreen(0.5f * (end_contig + start_contig - 1.0f)) - (0.5f * textWidth);
- f32 textY = ModelYToScreen((0.5f * (1.0f - end_contig - start_contig))) - (lh * (f32)(++tmp));
+ u32 invert = IsContigInverted(index);
- DrawOutlinedText(FontStash_Context, (nk_colorf *)colour, (char *)Meta_Data->tags[index2], textX, textY);
- }
- else
- {
- fonsSetColor(FontStash_Context, FourFloatColorToU32(*((nk_colorf *)colour)));
- fonsDrawText(
- FontStash_Context,
- ModelXToScreen(0.5f * (end_contig + start_contig - 1.0f)) - (0.5f * textWidth),
- ModelYToScreen((0.5f * (1.0f - end_contig - start_contig))) - (lh * (f32)(++tmp)),
- (char *)Meta_Data->tags[index2],
- 0);
- }
+ vert[0].x = -py; vert[0].y = invert ? y : (py + lineWidth);
+ vert[1].x = -py; vert[1].y = invert ? (y - lineWidth) : py;
+ vert[2].x = -y; vert[2].y = invert ? (y - lineWidth) : py;
+ vert[3].x = -y; vert[3].y = invert ? y : (py + lineWidth);
- // Check if the tag is "Haplotig"
- if (strcmp((char *)Meta_Data->tags[index2], "Haplotig") == 0)
- {
- haplotigTagged = true;
- }
- }
- }
+ ColourGenerator((u32)cont->originalContigId, (f32 *)barColour);
+ glUniform4fv(Flat_Shader->colorLocation, 1, (GLfloat *)&barColour);
- // draw the grey out mask
- std::string grey_out_tag = Grey_Out_Settings->is_grey_out(cont->metaDataFlags, Meta_Data);
- if (!grey_out_tag.empty())
- {
- vert[0].x = ModelXToScreen(start_contig - 0.5f); vert[0].y = ModelYToScreen(0.5f - start_contig);
- vert[1].x = ModelXToScreen(start_contig - 0.5f); vert[1].y = ModelYToScreen(0.5f - end_contig);
- vert[2].x = ModelXToScreen(end_contig - 0.5f); vert[2].y = ModelYToScreen(0.5f - end_contig);
- vert[3].x = ModelXToScreen(end_contig - 0.5f); vert[3].y = ModelYToScreen(0.5f - start_contig);
-
- ColourGenerator((u32)scaffId, (f32 *)barColour);
- u32 colour = FourFloatColorToU32(*((nk_colorf *)barColour));
-
- glUseProgram(Flat_Shader->shaderProgram);
- glUniform4fv(Flat_Shader->colorLocation, 1, (GLfloat *)&barColour);
-
- glBindBuffer(GL_ARRAY_BUFFER, Scaff_Bar_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Scaff_Bar_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
-
- glUseProgram(UI_Shader->shaderProgram);
- fonsSetColor(FontStash_Context, colour);
- }
- }
- start_contig = end_contig;
- scaffId = cont->scaffId;
+ glBindBuffer(GL_ARRAY_BUFFER, Contig_ColourBar_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Contig_ColourBar_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
}
+ }
+ }
- if (MetaData_Edit_Mode && !UI_On)
- {
- u32 ptr = 0;
- vertex vert[4];
+ // Text / UI Rendering
+ if (Contig_Name_Labels->on || Scale_Bars->on || Tool_Tip->on || UI_On || Loading || auto_sort_state || Edit_Mode || Waypoint_Edit_Mode || Waypoints_Always_Visible || Scaff_Edit_Mode || Scaffs_Always_Visible || MetaData_Edit_Mode || MetaData_Always_Visible || graphNamesOn)
+ {
+ f32 textNormalMat[16];
+ f32 textRotMat[16];
- fonsSetSize(FontStash_Context, 24.0f * Screen_Scale.x);
- fonsVertMetrics(FontStash_Context, 0, 0, &lh);
- fonsSetColor(FontStash_Context, FourFloatColorToU32(MetaData_Mode_Data->text));
+ f32 w2 = width * 0.5f;
+ f32 h2 = height * 0.5f;
+ f32 hz = height * Camera_Position.z;
- f32 textBoxHeight = lh;
- textBoxHeight *= 7.0f;
- textBoxHeight += 6.0f;
- f32 spacing = 10.0f;
+ // coverting model coords (world space) to screen coords
+ auto ModelXToScreen = [hz, w2](f32 xin)->f32 {
+ return (xin - Camera_Position.x) * hz + w2; };
+ auto ModelYToScreen = [hz, h2](f32 yin)->f32 {
+ return h2 - (yin - Camera_Position.y) * hz; };
- char helpText7[128];
- const char *activeTag = (const char *)Meta_Data->tags[MetaData_Active_Tag];
- stbsp_snprintf(helpText7, sizeof(helpText7), "Active Tag: %s", strlen(activeTag) ? activeTag : "");
+ // Text Projection Matrix
+ {
+ memset(textNormalMat, 0, sizeof(textNormalMat));
+ textNormalMat[0] = 2.0f / width;
+ textNormalMat[5] = -2.0f / height;
+ textNormalMat[10] = -1.0f;
+ textNormalMat[12] = -1.0f;
+ textNormalMat[13] = 1.0f;
+ textNormalMat[15] = 1.0f;
- std::vector helpTexts = {
- "MetaData Tag Mode",
- "M: exit",
- "Left Click: place",
- "Middle Click / Spacebar: delete",
- "Shift-D: delete all",
- "Arrow Keys: select active tag",
- helpText7
- };
+ memset(textRotMat, 0, sizeof(textRotMat));
+ textRotMat[4] = 2.0f / width;
+ textRotMat[1] = 2.0f / height;
+ textRotMat[10] = -1.0f;
+ textRotMat[12] = -1.0f;
+ textRotMat[13] = 1.0f;
+ textRotMat[15] = 1.0f;
+ }
- f32 textWidth = 0.f;
- for (const auto& tmp:helpTexts)
- textWidth = std::max(textWidth, fonsTextBounds(FontStash_Context, 0, 0, tmp.c_str(), 0, NULL));
+ // Extension Labels
+ if (graphNamesOn)
+ {
+ glUseProgram(UI_Shader->shaderProgram);
+ glUniformMatrix4fv(UI_Shader->matLocation, 1, GL_FALSE, textNormalMat);
- glUseProgram(Flat_Shader->shaderProgram);
- glUniform4fv(Flat_Shader->colorLocation, 1, (f32 *)&MetaData_Mode_Data->bg);
+ fonsClearState(FontStash_Context);
+ fonsSetSize(FontStash_Context, 32.0f * Screen_Scale.x);
+ fonsSetAlign(FontStash_Context, FONS_ALIGN_LEFT | FONS_ALIGN_TOP);
+ fonsSetFont(FontStash_Context, Font_Bold);
- vert[0].x = width - spacing - textWidth; vert[0].y = height - spacing - textBoxHeight;
- vert[1].x = width - spacing - textWidth; vert[1].y = height - spacing;
- vert[2].x = width - spacing; vert[2].y = height - spacing;
- vert[3].x = width - spacing; vert[3].y = height - spacing - textBoxHeight;
+ f32 x = ModelXToScreen(-0.5f);
+ x = my_Max(x, 0.0f) + 10.0f;
- glBindBuffer(GL_ARRAY_BUFFER, Waypoint_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Waypoint_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ f32 h = height + 1.0f;
- glUseProgram(UI_Shader->shaderProgram);
- for (u32 i=0; i< helpTexts.size() ; i++) {
- fonsDrawText(
- FontStash_Context,
- width - spacing - textWidth,
- height - spacing - textBoxHeight + (lh + 1.0f) * i,
- helpTexts[i].c_str(),
- 0);
+ TraverseLinkedList(Extensions.head, extension_node)
+ {
+ switch (node->type)
+ {
+ case extension_graph:
+ {
+ graph *gph = (graph *)node->extension;
+
+ if (gph->on && gph->nameOn)
+ {
+ fonsSetColor(FontStash_Context, ThreeFloatColorToU32(gph->colour));
+ fonsDrawText(FontStash_Context, x, h - gph->base, (const char *)gph->name, 0);
+ }
+ }
+ break;
}
}
}
-
- // Tool Tip
- if (File_Loaded && Tool_Tip->on && !Edit_Mode && !UI_On)
+
+ if (File_Loaded && Contig_Name_Labels->on) // Contig Labels
{
glUseProgram(Flat_Shader->shaderProgram);
- glUniform4fv(Flat_Shader->colorLocation, 1, (GLfloat *)&Tool_Tip->bg);
+ glUniform4fv(Flat_Shader->colorLocation, 1, (GLfloat *)&Contig_Name_Labels->bg);
glUniformMatrix4fv(Flat_Shader->matLocation, 1, GL_FALSE, textNormalMat);
glUseProgram(UI_Shader->shaderProgram);
glUniformMatrix4fv(UI_Shader->matLocation, 1, GL_FALSE, textNormalMat);
+ u32 ptr = 0;
vertex vert[4];
glViewport(0, 0, (s32)width, (s32)height);
@@ -3845,133 +3752,231 @@ Render() {
f32 lh = 0.0f;
fonsClearState(FontStash_Context);
- fonsSetSize(FontStash_Context, Tool_Tip->size * Screen_Scale.x);
- fonsSetAlign(FontStash_Context, FONS_ALIGN_LEFT | FONS_ALIGN_TOP);
- fonsSetFont(FontStash_Context, Font_Normal);
+ fonsSetSize(FontStash_Context, Contig_Name_Labels->size * Screen_Scale.x);
+ fonsSetAlign(FontStash_Context, FONS_ALIGN_CENTER | FONS_ALIGN_TOP);
+ fonsSetFont(FontStash_Context, Font_Bold);
fonsVertMetrics(FontStash_Context, 0, 0, &lh);
- fonsSetColor(FontStash_Context, FourFloatColorToU32(Tool_Tip->fg));
-
- // Extension info, extra lines
- u32 nExtra = 0;
- f32 longestExtraLineLength = 0.0f;
+ fonsSetColor(FontStash_Context, FourFloatColorToU32(Contig_Name_Labels->fg));
+
+ f32 leftPixel = ModelXToScreen(-0.5f);
+ f32 totalLength = 0.0f;
+ f32 wy0 = ModelYToScreen(0.5f);
+
+ ForLoop(Contigs->numberOfContigs)
{
- if (Extensions.head)
+ contig *cont = Contigs->contigs_arr + index;
+
+ totalLength += (f32)((f64)cont->length / (f64)Number_of_Pixels_1D);
+
+ f32 rightPixel = ModelXToScreen(totalLength - 0.5f);
+
+ if (rightPixel > 0.0f && leftPixel < width)
{
- char buff[128];
- TraverseLinkedList(Extensions.head, extension_node)
+ const char *name = (const char *)(Original_Contigs + cont->get_original_contig_id())->name;
+ f32 x = (rightPixel + leftPixel) * 0.5f;
+ f32 y = my_Max(wy0, 0.0f) + 10.0f;
+ f32 textWidth = fonsTextBounds(FontStash_Context, x, y, name, 0, NULL);
+
+ if (textWidth < (rightPixel - leftPixel))
{
- switch (node->type)
- {
- case extension_graph:
- {
- graph *gph = (graph *)node->extension;
- if (gph->on)
- {
- glBindBuffer(GL_TEXTURE_BUFFER, Contact_Matrix->pixelRearrangmentLookupBuffer);
- u32 *buffer = (u32 *)glMapBufferRange(GL_TEXTURE_BUFFER, Tool_Tip_Move.pixels.x * sizeof(u32), sizeof(u32), GL_MAP_READ_BIT);
+ f32 w2t = 0.5f * textWidth;
- stbsp_snprintf(buff, sizeof(buff), "%s: %$d", (char *)gph->name, gph->data[*buffer]);
- ++nExtra;
- longestExtraLineLength = my_Max(longestExtraLineLength, fonsTextBounds(FontStash_Context, 0, 0, buff, 0, NULL));
+ glUseProgram(Flat_Shader->shaderProgram);
- glUnmapBuffer(GL_TEXTURE_BUFFER);
- glBindBuffer(GL_TEXTURE_BUFFER, 0);
- }
- }
- break;
- }
+ vert[0].x = x - w2t; vert[0].y = y + lh;
+ vert[1].x = x + w2t; vert[1].y = y + lh;
+ vert[2].x = x + w2t; vert[2].y = y;
+ vert[3].x = x - w2t; vert[3].y = y;
+
+ glBindBuffer(GL_ARRAY_BUFFER, Label_Box_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Label_Box_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+
+ glUseProgram(UI_Shader->shaderProgram);
+ fonsDrawText(FontStash_Context, x, y, name, 0);
}
}
+
+ leftPixel = rightPixel;
}
- f32 textBoxHeight = lh;
- textBoxHeight *= (3.0f + (f32)nExtra);
- textBoxHeight += (2.0f + (f32)nExtra);
+ glUseProgram(Flat_Shader->shaderProgram);
+ glUniformMatrix4fv(Flat_Shader->matLocation, 1, GL_FALSE, textRotMat);
- u32 id1 = Map_State->get_original_contig_id(Tool_Tip_Move.pixels.x);
- u32 id2 = Map_State->get_original_contig_id(Tool_Tip_Move.pixels.y);
- u32 coord1 = Map_State->contigRelCoords[Tool_Tip_Move.pixels.x];
- u32 coord2 = Map_State->contigRelCoords[Tool_Tip_Move.pixels.y];
-
- f64 bpPerPixel = (f64)Total_Genome_Length / (f64)Number_of_Pixels_1D;
+ glUseProgram(UI_Shader->shaderProgram);
+ glUniformMatrix4fv(UI_Shader->matLocation, 1, GL_FALSE, textRotMat);
- char line1[64];
- char *line2 = (char *)"vs";
- char line3[64];
+ f32 topPixel = ModelYToScreen(0.5f);
+ f32 wx0 = ModelXToScreen(-0.5f);
+ totalLength = 0.0f;
- auto NicePrint = [bpPerPixel](u32 id, u32 coord, char *buffer)
+ ForLoop(Contigs->numberOfContigs)
{
- f64 pos = (f64)coord * bpPerPixel;
- stbsp_snprintf(buffer, 64, "%s %'u %sbp", (Original_Contigs + id)->name, (u32)(pos / (pos > 1000.0 ? 1000.0 : 1.0)), pos > 1000.0 ? "K" : "");
- };
+ contig *cont = Contigs->contigs_arr + index;
+
+ totalLength += (f32)((f64)cont->length / (f64)Number_of_Pixels_1D);
- NicePrint(id1, coord1, line1);
- NicePrint(id2, coord2, line3);
+ f32 bottomPixel = ModelYToScreen(0.5f - totalLength);
- f32 textWidth_1 = fonsTextBounds(FontStash_Context, 0, 0, line1, 0, NULL);
- f32 textWidth_2 = fonsTextBounds(FontStash_Context, 0, 0, line2, 0, NULL);
- f32 textWidth_3 = fonsTextBounds(FontStash_Context, 0, 0, line3, 0, NULL);
- f32 textWidth = my_Max(textWidth_1, textWidth_2);
- textWidth = my_Max(textWidth, textWidth_3);
- textWidth = my_Max(textWidth, longestExtraLineLength);
+ if (topPixel < height && bottomPixel > 0.0f)
+ {
+ const char *name = (const char *)(Original_Contigs + cont->get_original_contig_id())->name;
+ f32 y = (topPixel + bottomPixel) * 0.5f;
+ f32 x = my_Max(wx0, 0.0f) + 10.0f;
+ f32 textWidth = fonsTextBounds(FontStash_Context, x, y, name, 0, NULL);
- f32 spacing = 12.0f;
+ if (textWidth < (bottomPixel - topPixel))
+ {
+ f32 tmp = x;
+ x = -y;
+ y = tmp;
- glUseProgram(Flat_Shader->shaderProgram);
+ f32 w2t = 0.5f * textWidth;
- vert[0].x = ModelXToScreen(Tool_Tip_Move.worldCoords.x) + spacing; vert[0].y = ModelYToScreen(-Tool_Tip_Move.worldCoords.y) + spacing;
- vert[1].x = ModelXToScreen(Tool_Tip_Move.worldCoords.x) + spacing; vert[1].y = ModelYToScreen(-Tool_Tip_Move.worldCoords.y) + spacing + textBoxHeight;
- vert[2].x = ModelXToScreen(Tool_Tip_Move.worldCoords.x) + spacing + textWidth; vert[2].y = ModelYToScreen(-Tool_Tip_Move.worldCoords.y) + spacing + textBoxHeight;
- vert[3].x = ModelXToScreen(Tool_Tip_Move.worldCoords.x) + spacing + textWidth; vert[3].y = ModelYToScreen(-Tool_Tip_Move.worldCoords.y) + spacing;
+ glUseProgram(Flat_Shader->shaderProgram);
- glBindBuffer(GL_ARRAY_BUFFER, Tool_Tip_Data->vbos[0]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Tool_Tip_Data->vaos[0]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ vert[0].x = x - w2t; vert[0].y = y + lh;
+ vert[1].x = x + w2t; vert[1].y = y + lh;
+ vert[2].x = x + w2t; vert[2].y = y;
+ vert[3].x = x - w2t; vert[3].y = y;
+
+ glBindBuffer(GL_ARRAY_BUFFER, Label_Box_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Label_Box_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+
+ glUseProgram(UI_Shader->shaderProgram);
+ fonsDrawText(FontStash_Context, x, y, name, 0);
+ }
+ }
+
+ topPixel = bottomPixel;
+ }
+
+ ChangeSize((s32)width, (s32)height);
+ }
+ #define MaxTicksPerScaleBar 128
+ if (File_Loaded && Scale_Bars->on) // Scale bars
+ {
+ glUseProgram(Flat_Shader->shaderProgram);
+ glUniform4fv(Flat_Shader->colorLocation, 1, (GLfloat *)&Scale_Bars->bg);
+ glUniformMatrix4fv(Flat_Shader->matLocation, 1, GL_FALSE, textNormalMat);
+
glUseProgram(UI_Shader->shaderProgram);
- fonsDrawText(FontStash_Context, ModelXToScreen(Tool_Tip_Move.worldCoords.x) + spacing,
- ModelYToScreen(-Tool_Tip_Move.worldCoords.y) + spacing, line1, 0);
- fonsDrawText(FontStash_Context, ModelXToScreen(Tool_Tip_Move.worldCoords.x) + spacing,
- ModelYToScreen(-Tool_Tip_Move.worldCoords.y) + spacing + lh + 1.0f, line2, 0);
- fonsDrawText(FontStash_Context, ModelXToScreen(Tool_Tip_Move.worldCoords.x) + spacing,
- ModelYToScreen(-Tool_Tip_Move.worldCoords.y) + spacing + (2.0f * lh) + 2.0f, line3, 0);
+ glUniformMatrix4fv(UI_Shader->matLocation, 1, GL_FALSE, textNormalMat);
+
+ u32 ptr = 0;
+ vertex vert[4];
+
+ glViewport(0, 0, (s32)width, (s32)height);
+
+ f32 lh = 0.0f;
+
+ fonsClearState(FontStash_Context);
+ fonsSetSize(FontStash_Context, Scale_Bars->size * Screen_Scale.x);
+ fonsSetAlign(FontStash_Context, FONS_ALIGN_CENTER | FONS_ALIGN_TOP);
+ fonsSetFont(FontStash_Context, Font_Normal);
+ fonsVertMetrics(FontStash_Context, 0, 0, &lh);
+ fonsSetColor(FontStash_Context, FourFloatColorToU32(Scale_Bars->fg));
+
+ f32 leftPixel = ModelXToScreen(-0.5f);
+ f32 rightPixel = ModelXToScreen(0.5f);
+ f32 wy0 = ModelYToScreen(0.5);
+ f32 offset = 45.0f * Screen_Scale.x;
+ f32 y = my_Max(wy0, 0.0f) + offset;
+ f32 totalLength = 0.0f;
+
+ f32 bpPerPixel = (f32)((f64)Total_Genome_Length / (f64)(rightPixel - leftPixel));
+
+ GLfloat *bg = (GLfloat *)&Scale_Bars->bg;
+
+ f32 scaleBarWidth = Scale_Bars->size * 4.0f / 20.0f * Screen_Scale.x;
+ f32 tickLength = Scale_Bars->size * 3.0f / 20.0f * Screen_Scale.x;
+ ForLoop(Contigs->numberOfContigs)
{
- if (Extensions.head)
+ contig *cont = Contigs->contigs_arr + index;
+
+ totalLength += (f32)((f64)cont->length / (f64)Number_of_Pixels_1D);
+ rightPixel = ModelXToScreen(totalLength - 0.5f);
+
+ f32 pixelLength = rightPixel - leftPixel;
+ f32 startCoord = (f32)((f64)(IsContigInverted(index) ? (cont->startCoord - cont->length) : cont->startCoord) * (f64)Total_Genome_Length / (f64)Number_of_Pixels_1D);
+
+ u32 labelLevels = SubDivideScaleBar(leftPixel, rightPixel, (leftPixel + rightPixel) * 0.5f, bpPerPixel, startCoord);
+ u32 labels = 0;
+ ForLoop2(labelLevels)
{
- u32 count = 0;
- char buff[128];
- TraverseLinkedList(Extensions.head, extension_node)
+ labels += (labels + 1);
+ }
+ labels = my_Min(labels, MaxTicksPerScaleBar);
+
+ if (rightPixel > 0.0f && leftPixel < width)
+ {
+ if (labels)
{
- switch (node->type)
+ glUseProgram(Flat_Shader->shaderProgram);
+ glUniform4fv(Flat_Shader->colorLocation, 1, bg);
+
+ vert[0].x = leftPixel + 1.0f; vert[0].y = y + scaleBarWidth + tickLength + 1.0f + lh;
+ vert[1].x = rightPixel - 1.0f; vert[1].y = y + scaleBarWidth + tickLength + 1.0f + lh;
+ vert[2].x = rightPixel - 1.0f; vert[2].y = y;
+ vert[3].x = leftPixel + 1.0f; vert[3].y = y;
+
+ glBindBuffer(GL_ARRAY_BUFFER, Scale_Bar_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Scale_Bar_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+
+ glUniform4fv(Flat_Shader->colorLocation, 1, (f32 *)&Scale_Bars->fg);
+
+ vert[0].x = leftPixel + 1.0f; vert[0].y = y + scaleBarWidth;
+ vert[1].x = rightPixel - 1.0f; vert[1].y = y + scaleBarWidth;
+ vert[2].x = rightPixel - 1.0f; vert[2].y = y;
+ vert[3].x = leftPixel + 1.0f; vert[3].y = y;
+
+ glBindBuffer(GL_ARRAY_BUFFER, Scale_Bar_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Scale_Bar_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+
+ f32 fraction = 1.0f / (f32)(labels + 1);
+ f32 distance = 0.0f;
+ ForLoop2(labels)
{
- case extension_graph:
- {
- graph *gph = (graph *)node->extension;
- if (gph->on)
- {
- glBindBuffer(GL_TEXTURE_BUFFER, Contact_Matrix->pixelRearrangmentLookupBuffer);
- u32 *buffer = (u32 *)glMapBufferRange(GL_TEXTURE_BUFFER, Tool_Tip_Move.pixels.x * sizeof(u32), sizeof(u32), GL_MAP_READ_BIT);
+ distance += fraction;
+ f32 x = (pixelLength * distance) + (f32)leftPixel;
- stbsp_snprintf(buff, sizeof(buff), "%s: %$d", (char *)gph->name, gph->data[*buffer]);
+ glUseProgram(Flat_Shader->shaderProgram);
- fonsDrawText(FontStash_Context, ModelXToScreen(Tool_Tip_Move.worldCoords.x) + spacing,
- ModelYToScreen(-Tool_Tip_Move.worldCoords.y) + spacing + ((2.0f + (f32)(++count)) * (lh + 1.0f)), buff, 0);
+ vert[0].x = x - (0.5f * scaleBarWidth); vert[0].y = y + scaleBarWidth + tickLength;
+ vert[1].x = x + (0.5f * scaleBarWidth); vert[1].y = y + scaleBarWidth + tickLength;
+ vert[2].x = x + (0.5f * scaleBarWidth); vert[2].y = y + scaleBarWidth;
+ vert[3].x = x - (0.5f * scaleBarWidth); vert[3].y = y + scaleBarWidth;
- glUnmapBuffer(GL_TEXTURE_BUFFER);
- glBindBuffer(GL_TEXTURE_BUFFER, 0);
- }
- }
- break;
+ glBindBuffer(GL_ARRAY_BUFFER, Scale_Bar_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Scale_Bar_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+
+ char buff[16];
+ stbsp_snprintf(buff, 16, "%$.2f", (f64)(startCoord + (pixelLength * (IsContigInverted(index) ? (1.0f - distance) : distance) * bpPerPixel)));
+ glUseProgram(UI_Shader->shaderProgram);
+ fonsDrawText(FontStash_Context, x, y + scaleBarWidth + tickLength + 1.0f, buff, 0);
}
}
}
+
+ leftPixel = rightPixel;
}
- }
- // Edit Mode
- if (File_Loaded && Edit_Mode && !UI_On) // Edit Mode
+ ChangeSize((s32)width, (s32)height);
+ }
+
+ // Finished - add the cross line to the waypoint
+ if (File_Loaded && (Waypoint_Edit_Mode || Waypoints_Always_Visible)) // Waypoint Edit Mode
{
u32 ptr = 0;
vertex vert[4];
@@ -3981,4521 +3986,4952 @@ Render() {
glUseProgram(UI_Shader->shaderProgram);
glUniformMatrix4fv(UI_Shader->matLocation, 1, GL_FALSE, textNormalMat);
- glUseProgram(Flat_Shader->shaderProgram);
glViewport(0, 0, (s32)width, (s32)height);
+#define DefaultWaypointSize 18.0f
+ glUseProgram(Flat_Shader->shaderProgram);
+ glUniform4fv(Flat_Shader->colorLocation, 1, (f32 *)&Waypoint_Mode_Data->base);
- f32 color[4];
- f32* source;
- if (Edit_Pixels.editing) // edit color
- {
- if (Global_Edit_Invert_Flag) source = (f32*)&Edit_Mode_Colours->invSelect;
- else source = (f32*)&Edit_Mode_Colours->select;
- }
- else source = (f32*)&Edit_Mode_Colours->preSelect; // pre-edit color
- ForLoop(4)
- {
- color[index] = source[index];
- }
- f32 alpha = color[3];
- color[3] = 1.0f;
+ // define the vertical line
+ f32 lineWidth = Waypoint_Mode_Data->size / DefaultWaypointSize * 0.7f * Screen_Scale.x;
+ f32 lineHeight = Waypoint_Mode_Data->size / DefaultWaypointSize * 8.0f * Screen_Scale.x;
- glUniform4fv(Flat_Shader->colorLocation, 1, color);
+ f32 lh = 0.0f;
- f32 lineWidth = 0.005f / Camera_Position.z;
+ u32 baseColour = FourFloatColorToU32(Waypoint_Mode_Data->base);
+ u32 selectColour = FourFloatColorToU32(Waypoint_Mode_Data->selected);
- { // draw the two squared dots at the beginning and end of the selected fragment
- vert[0].x = ModelXToScreen(Edit_Pixels.worldCoords.x - lineWidth);
- vert[0].y = ModelYToScreen(lineWidth - Edit_Pixels.worldCoords.x);
- vert[1].x = ModelXToScreen(Edit_Pixels.worldCoords.x - lineWidth);
- vert[1].y = ModelYToScreen(-lineWidth - Edit_Pixels.worldCoords.x);
- vert[2].x = ModelXToScreen(Edit_Pixels.worldCoords.x + lineWidth);
- vert[2].y = ModelYToScreen(-lineWidth - Edit_Pixels.worldCoords.x);
- vert[3].x = ModelXToScreen(Edit_Pixels.worldCoords.x + lineWidth);
- vert[3].y = ModelYToScreen(lineWidth - Edit_Pixels.worldCoords.x);
+ fonsClearState(FontStash_Context);
+ fonsSetSize(FontStash_Context, Waypoint_Mode_Data->size * Screen_Scale.x);
+ fonsSetAlign(FontStash_Context, FONS_ALIGN_LEFT | FONS_ALIGN_TOP);
+ fonsSetFont(FontStash_Context, Font_Bold);
+ fonsVertMetrics(FontStash_Context, 0, 0, &lh);
+ fonsSetColor(FontStash_Context, baseColour);
- glBindBuffer(GL_ARRAY_BUFFER, Edit_Mode_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Edit_Mode_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ char buff[4];
+
+ // render the waypoints lines
+ TraverseLinkedList(Waypoint_Editor->activeWaypoints.next, waypoint)
+ {
+ point2f screen = {ModelXToScreen(node->coords.x), ModelYToScreen(-node->coords.y)};
+ point2f screenYRange = {ModelYToScreen(0.5f), ModelYToScreen(-0.5f)};
+ point2f screenXRange = {ModelXToScreen(-0.5f), ModelXToScreen(0.5f)};
- vert[0].x = ModelXToScreen(Edit_Pixels.worldCoords.y - lineWidth);
- vert[0].y = ModelYToScreen(lineWidth - Edit_Pixels.worldCoords.y);
- vert[1].x = ModelXToScreen(Edit_Pixels.worldCoords.y - lineWidth);
- vert[1].y = ModelYToScreen(-lineWidth - Edit_Pixels.worldCoords.y);
- vert[2].x = ModelXToScreen(Edit_Pixels.worldCoords.y + lineWidth);
- vert[2].y = ModelYToScreen(-lineWidth - Edit_Pixels.worldCoords.y);
- vert[3].x = ModelXToScreen(Edit_Pixels.worldCoords.y + lineWidth);
- vert[3].y = ModelYToScreen(lineWidth - Edit_Pixels.worldCoords.y);
+ glUseProgram(Flat_Shader->shaderProgram);
+ if (node == Selected_Waypoint)
+ {
+ glUniform4fv(Flat_Shader->colorLocation, 1, (f32 *)&Waypoint_Mode_Data->selected);
+ }
+
+ bool long_horizontal, long_vertical;
+ if (Long_Waypoints_Mode == 0) { // vertical line
+ long_horizontal = false;
+ long_vertical = true;
+ } else if (Long_Waypoints_Mode == 1) { // horizontal line
+ long_horizontal = true;
+ long_vertical = false;
+ } else { // cross line
+ long_horizontal = true;
+ long_vertical = true;
+ }
- glBindBuffer(GL_ARRAY_BUFFER, Edit_Mode_Data->vbos[ptr]);
+ // draw the vertical line
+ vert[0].x = screen.x - lineWidth; vert[0].y = long_vertical ? screenYRange.x : screen.y - lineHeight;
+ vert[1].x = screen.x - lineWidth; vert[1].y = long_vertical ? screenYRange.y : screen.y + lineHeight;
+ vert[2].x = screen.x + lineWidth; vert[2].y = long_vertical ? screenYRange.y : screen.y + lineHeight;
+ vert[3].x = screen.x + lineWidth; vert[3].y = long_vertical ? screenYRange.x : screen.y - lineHeight;
+ glBindBuffer(GL_ARRAY_BUFFER, Waypoint_Data->vbos[ptr]);
glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Edit_Mode_Data->vaos[ptr++]);
+ glBindVertexArray(Waypoint_Data->vaos[ptr++]);
glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- }
-
- f32 min = my_Min(Edit_Pixels.worldCoords.x, Edit_Pixels.worldCoords.y);
- f32 max = my_Max(Edit_Pixels.worldCoords.x, Edit_Pixels.worldCoords.y);
- if (Global_Edit_Invert_Flag) // draw the two arrows
- {
- f32 spacing = 0.002f / Camera_Position.z;
- f32 arrowWidth = 0.01f / Camera_Position.z;
- f32 arrowHeight = arrowWidth * 0.65f;
- f32 recHeight = arrowHeight * 0.65f;
-
- // draw the the triangle part
- vert[0].x = ModelXToScreen(min + spacing); vert[0].y = ModelYToScreen(arrowHeight + spacing - min);
- vert[1].x = ModelXToScreen(min + spacing + arrowWidth); vert[1].y = ModelYToScreen(spacing - min);
- vert[2].x = ModelXToScreen(min + spacing + arrowWidth); vert[2].y = ModelYToScreen(arrowHeight + spacing - min);
- vert[3].x = ModelXToScreen(min + spacing + arrowWidth); vert[3].y = ModelYToScreen((2.0f * arrowHeight) + spacing - min);
-
- glBindBuffer(GL_ARRAY_BUFFER, Edit_Mode_Data->vbos[ptr]);
+ // draw the horizontal line (originally: the left part, not sure why Ed draw them seperately, if problem arises we can returen here) maybe avoid drawing the cross part twice...
+ vert[0].x = long_horizontal ? screenXRange.x : screen.x - lineHeight; vert[0].y = screen.y - lineWidth;
+ vert[1].x = long_horizontal ? screenXRange.x : screen.x - lineHeight; vert[1].y = screen.y + lineWidth;
+ vert[2].x = long_horizontal ? screenXRange.y : screen.x + lineHeight; vert[2].y = screen.y + lineWidth;// vert[2].x = screen.x - lineWidth;
+ vert[3].x = long_horizontal ? screenXRange.y : screen.x + lineHeight; vert[3].y = screen.y - lineWidth;// vert[3].x = screen.x - lineWidth;
+ glBindBuffer(GL_ARRAY_BUFFER, Waypoint_Data->vbos[ptr]);
glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Edit_Mode_Data->vaos[ptr++]);
+ glBindVertexArray(Waypoint_Data->vaos[ptr++]);
glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- // draw the rectangle part
- vert[0].x = ModelXToScreen(min + spacing + arrowWidth); vert[0].y = ModelYToScreen((arrowHeight + 0.5f * recHeight) + spacing - min);
- vert[1].x = ModelXToScreen(min + spacing + arrowWidth); vert[1].y = ModelYToScreen((arrowHeight - 0.5f * recHeight) + spacing - min);
- vert[2].x = ModelXToScreen(max - spacing); vert[2].y = ModelYToScreen((arrowHeight - 0.5f * recHeight) + spacing - min);
- vert[3].x = ModelXToScreen(max - spacing); vert[3].y = ModelYToScreen((arrowHeight + 0.5f * recHeight) + spacing - min);
- glBindBuffer(GL_ARRAY_BUFFER, Edit_Mode_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Edit_Mode_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- }
+ // draw the horizontal line (originally: the right part, not sure why Ed draw them seperately, if problem arises we can returen here)
+ // vert[0].x = screen.x + lineWidth;
+ // vert[0].y = screen.y - lineWidth;
+ // vert[1].x = screen.x + lineWidth;
+ // vert[1].y = screen.y + lineWidth;
+ // vert[2].x = screen.x + lineHeight;
+ // vert[2].y = screen.y + lineWidth;
+ // vert[3].x = screen.x + lineHeight;
+ // vert[3].y = screen.y - lineWidth;
+ // glBindBuffer(GL_ARRAY_BUFFER, Waypoint_Data->vbos[ptr]);
+ // glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ // glBindVertexArray(Waypoint_Data->vaos[ptr++]);
+ // glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+
+ if (node == Selected_Waypoint)
+ {
+ glUniform4fv(Flat_Shader->colorLocation, 1, (f32 *)&Waypoint_Mode_Data->base);
+ }
- { // draw the interacted area
+ glUseProgram(UI_Shader->shaderProgram);
+ if (node == Selected_Waypoint)
+ {
+ fonsSetColor(FontStash_Context, selectColour);
+ }
- color[3] = alpha;
- glUniform4fv(Flat_Shader->colorLocation, 1, color);
-
- // upper vertical part
- vert[0].x = ModelXToScreen(min); vert[0].y = ModelYToScreen(0.5f);
- vert[1].x = ModelXToScreen(min); vert[1].y = ModelYToScreen(-min);
- vert[2].x = ModelXToScreen(max); vert[2].y = ModelYToScreen(-min);
- vert[3].x = ModelXToScreen(max); vert[3].y = ModelYToScreen(0.5f);
- glBindBuffer(GL_ARRAY_BUFFER, Edit_Mode_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Edit_Mode_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
-
- // left horizontal part
- vert[0].x = ModelXToScreen(-0.5f); vert[0].y = ModelYToScreen(-min);
- vert[1].x = ModelXToScreen(-0.5f); vert[1].y = ModelYToScreen(-max);
- vert[2].x = ModelXToScreen(min); vert[2].y = ModelYToScreen(-max);
- vert[3].x = ModelXToScreen(min); vert[3].y = ModelYToScreen(-min);
- glBindBuffer(GL_ARRAY_BUFFER, Edit_Mode_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Edit_Mode_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
-
- // lower vertical part
- vert[0].x = ModelXToScreen(min); vert[0].y = ModelYToScreen(-max);
- vert[1].x = ModelXToScreen(min); vert[1].y = ModelYToScreen(-0.5f);
- vert[2].x = ModelXToScreen(max); vert[2].y = ModelYToScreen(-0.5f);
- vert[3].x = ModelXToScreen(max); vert[3].y = ModelYToScreen(-max);
- glBindBuffer(GL_ARRAY_BUFFER, Edit_Mode_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Edit_Mode_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
-
- // right horizontal part
- vert[0].x = ModelXToScreen(max); vert[0].y = ModelYToScreen(-min);
- vert[1].x = ModelXToScreen(max); vert[1].y = ModelYToScreen(-max);
- vert[2].x = ModelXToScreen(0.5f); vert[2].y = ModelYToScreen(-max);
- vert[3].x = ModelXToScreen(0.5f); vert[3].y = ModelYToScreen(-min);
- glBindBuffer(GL_ARRAY_BUFFER, Edit_Mode_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Edit_Mode_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ stbsp_snprintf(buff, sizeof(buff), "%d", node->index + 1);
+ fonsDrawText(FontStash_Context, screen.x + lineWidth + lineWidth, screen.y - lineWidth - lh, buff, 0);
- // ceter part
- vert[0].x = ModelXToScreen(min); vert[0].y = ModelYToScreen(-min);
- vert[1].x = ModelXToScreen(min); vert[1].y = ModelYToScreen(-max);
- vert[2].x = ModelXToScreen(max); vert[2].y = ModelYToScreen(-max);
- vert[3].x = ModelXToScreen(max); vert[3].y = ModelYToScreen(-min);
- glBindBuffer(GL_ARRAY_BUFFER, Edit_Mode_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Edit_Mode_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ if (node == Selected_Waypoint)
+ {
+ fonsSetColor(FontStash_Context, baseColour);
+ }
}
- { // draw the text by the selected (pre-select) fragment
- f32 lh = 0.0f;
-
- fonsClearState(FontStash_Context);
- fonsSetSize(FontStash_Context, 18.0f * Screen_Scale.x);
- fonsSetAlign(FontStash_Context, FONS_ALIGN_LEFT | FONS_ALIGN_TOP);
- fonsSetFont(FontStash_Context, Font_Normal);
+ if (Waypoint_Edit_Mode && !UI_On)
+ {
+ fonsSetSize(FontStash_Context, text_box_size.font_size * Screen_Scale.x);
fonsVertMetrics(FontStash_Context, 0, 0, &lh);
- fonsSetColor(FontStash_Context, FourFloatColorToU32(Edit_Mode_Colours->fg));
-
- f32 textBoxHeight = lh;
- textBoxHeight *= Edit_Pixels.editing ? 3.0f : 1.0f;
- textBoxHeight += Edit_Pixels.editing ? 3.0f : 0.0f;
-
- static char line1[64];
- static u32 line1Done = 0;
- char line2[64];
-
- char *midLineNoInv = (char *)"moved to";
- char *midLineInv = (char *)"inverted and moved to";
- char *midLine = Global_Edit_Invert_Flag ? midLineInv : midLineNoInv;
-
- u32 pix1 = my_Min(Edit_Pixels.pixels.x, Edit_Pixels.pixels.y);
- u32 pix2 = my_Max(Edit_Pixels.pixels.x, Edit_Pixels.pixels.y);
+ fonsSetColor(FontStash_Context, FourFloatColorToU32(Waypoint_Mode_Data->text));
- if (Edit_Pixels.editing && line1Done)
- {
- pix1 = pix1 ? pix1 - 1 : (pix2 < (Number_of_Pixels_1D - 1) ? pix2 + 1 : pix2);
+ std::vector helpTexts = {
+ (char*)"Waypoint Edit Mode",
+ (char*)"W: exit",
+ (char*)"Left Click: place",
+ (char*)"Middle Click / Spacebar: delete",
+ };
+ if (Long_Waypoints_Mode == 2) {
+ helpTexts.push_back((char*)"L: both directions");
+ } else if (Long_Waypoints_Mode == 1) {
+ helpTexts.push_back((char*)"L: horizontal");
+ } else {
+ helpTexts.push_back((char*)"L: vertical");
}
- original_contig *cont = Original_Contigs + Map_State->get_original_contig_id(pix1);
-
- u32 nPixels = Number_of_Pixels_1D;
- f64 bpPerPixel = (f64)Total_Genome_Length / (f64)nPixels;
+ f32 textBoxHeight = lh;
+ textBoxHeight *= (f32)helpTexts.size();
+ textBoxHeight += (f32)helpTexts.size() - 1.0f;
+ f32 spacing = 10.0f; // distance from the edge of the text box
- f64 bpStart = bpPerPixel * (f64)Map_State->contigRelCoords[pix1];
-
- if (Edit_Pixels.editing)
- {
- stbsp_snprintf(line2, 64, "%s[%$.2fbp]", cont->name, bpStart);
- }
- else if (line1Done)
- {
- line1Done = 0;
- }
-
- if (!line1Done)
- {
- f64 bpEnd = bpPerPixel * (f64)Map_State->contigRelCoords[pix2];
- original_contig *cont2 = Original_Contigs + Map_State->get_original_contig_id(pix2);
- stbsp_snprintf(line1, 64, "%s[%$.2fbp] to %s[%$.2fbp]", cont->name, bpStart, cont2->name, bpEnd);
- if (Edit_Pixels.editing)
- {
- line1Done = 1;
- }
+ // f32 textWidth = fonsTextBounds(FontStash_Context, 0, 0, helpText4, 0, NULL);
+ f32 textWidth = 0;
+ for (auto i : helpTexts){
+ textWidth = my_Max(textWidth, fonsTextBounds(FontStash_Context, 0, 0, i, 0, NULL)) + 0.5f * spacing;
}
- f32 textWidth_1 = fonsTextBounds(FontStash_Context, 0, 0, line1, 0, NULL);
- f32 textWidth_2 = fonsTextBounds(FontStash_Context, 0, 0, line2, 0, NULL);
- f32 textWidth_3 = fonsTextBounds(FontStash_Context, 0, 0, midLine, 0, NULL);
- f32 textWidth = my_Max(textWidth_1, textWidth_2);
- textWidth = my_Max(textWidth, textWidth_3);
-
- f32 spacing = 3.0f;
-
- glUniform4fv(Flat_Shader->colorLocation, 1, (f32 *)&Edit_Mode_Colours->bg);
+ glUseProgram(Flat_Shader->shaderProgram);
+ glUniform4fv(Flat_Shader->colorLocation, 1, (f32 *)&Waypoint_Mode_Data->bg);
- vert[0].x = ModelXToScreen(min) - spacing - textWidth;
- vert[0].y = ModelYToScreen(-max) + spacing;
- vert[1].x = ModelXToScreen(min) - spacing - textWidth;
- vert[1].y = ModelYToScreen(-max) + spacing + textBoxHeight;
- vert[2].x = ModelXToScreen(min) - spacing;
- vert[2].y = ModelYToScreen(-max) + spacing + textBoxHeight;
- vert[3].x = ModelXToScreen(min) - spacing;
- vert[3].y = ModelYToScreen(-max) + spacing;
+ vert[0].x = width - spacing - textWidth; vert[0].y = height - spacing - textBoxHeight;
+ vert[1].x = width - spacing - textWidth; vert[1].y = height - spacing;
+ vert[2].x = width - spacing; vert[2].y = height - spacing;
+ vert[3].x = width - spacing; vert[3].y = height - spacing - textBoxHeight;
- glBindBuffer(GL_ARRAY_BUFFER, Edit_Mode_Data->vbos[ptr]);
+ glBindBuffer(GL_ARRAY_BUFFER, Waypoint_Data->vbos[ptr]);
glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Edit_Mode_Data->vaos[ptr++]);
+ glBindVertexArray(Waypoint_Data->vaos[ptr++]);
glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
glUseProgram(UI_Shader->shaderProgram);
- fonsDrawText(FontStash_Context, ModelXToScreen(min) - spacing - textWidth, ModelYToScreen(-max) + spacing, line1, 0);
- if (Edit_Pixels.editing)
- {
- fonsDrawText(FontStash_Context, ModelXToScreen(min) - spacing - textWidth, ModelYToScreen(-max) + spacing + lh + 1.0f, midLine, 0);
- fonsDrawText(FontStash_Context, ModelXToScreen(min) - spacing - textWidth, ModelYToScreen(-max) + spacing + (2.0f * (lh + 1.0f)), line2, 0);
+ for (u32 i=0; i< helpTexts.size() ; i++) {
+ fonsDrawText(
+ FontStash_Context,
+ width - spacing - textWidth,
+ height - spacing - textBoxHeight + (lh + 1.0f) * i,
+ helpTexts[i],
+ 0);
}
+ }
+ }
+
+ // Extension Mode
+ if (Extension_Mode && !UI_On)
+ {
+ u32 ptr = 0;
+ vertex vert[4];
+ f32 lh = 0.0f;
- if (Edit_Pixels.snap)
- {
- char *text = (char *)"Snap Mode On";
- textWidth = fonsTextBounds(FontStash_Context, 0, 0, text, 0, NULL);
- glUseProgram(Flat_Shader->shaderProgram);
- vert[0].x = ModelXToScreen(min) - spacing - textWidth; vert[0].y = ModelYToScreen(-min) + spacing;
- vert[1].x = ModelXToScreen(min) - spacing - textWidth; vert[1].y = ModelYToScreen(-min) + spacing + lh;
- vert[2].x = ModelXToScreen(min) - spacing; vert[2].y = ModelYToScreen(-min) + spacing + lh;
- vert[3].x = ModelXToScreen(min) - spacing; vert[3].y = ModelYToScreen(-min) + spacing;
+ glUseProgram(Flat_Shader->shaderProgram);
+ glUniformMatrix4fv(Flat_Shader->matLocation, 1, GL_FALSE, textNormalMat);
+ glUseProgram(UI_Shader->shaderProgram);
+ glUniformMatrix4fv(UI_Shader->matLocation, 1, GL_FALSE, textNormalMat);
- glBindBuffer(GL_ARRAY_BUFFER, Edit_Mode_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Edit_Mode_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
-
- glUseProgram(UI_Shader->shaderProgram);
- fonsDrawText(FontStash_Context, ModelXToScreen(min) - spacing - textWidth, ModelYToScreen(-min) + spacing, text, 0);
- }
+ glViewport(0, 0, (s32)width, (s32)height);
- { // draw the help text in the bottom right corner
- fonsSetFont(FontStash_Context, Font_Bold);
- fonsSetSize(FontStash_Context, 24.0f * Screen_Scale.x);
- fonsVertMetrics(FontStash_Context, 0, 0, &lh);
+#define DefaultExtensionSize 20.0f
+ // glUseProgram(Flat_Shader->shaderProgram);
+ // glUniform4fv(Flat_Shader->colorLocation, 1, (f32 *)&Waypoint_Mode_Data->base);
- std::vector helpTexts = {
- (char *)"Edit Mode",
- (char *)"E: exit, Q: undo, W: redo",
- (char *)"Left Click: pickup, place",
- (char *)"S: toggle snap mode",
- (char *)"Middle Click / Spacebar: pickup whole sequence or (hold Shift): scaffold",
- (char *)"Middle Click / Spacebar (while editing): invert sequence"
- };
+ // f32 lineWidth = Waypoint_Mode_Data->size / DefaultWaypointSize * 0.7f * Screen_Scale.x;
+ // f32 lineHeight = Waypoint_Mode_Data->size / DefaultWaypointSize * 8.0f * Screen_Scale.x;
- textBoxHeight = (f32)helpTexts.size() * (lh + 1.0f) - 1.0f;
- spacing = 10.0f;
+ fonsSetSize(FontStash_Context, text_box_size.font_size * Screen_Scale.x);
+ fonsVertMetrics(FontStash_Context, 0, 0, &lh);
+ fonsSetColor(FontStash_Context, FourFloatColorToU32(Extension_Mode_Data->text));
- textWidth = 0.f;
- for (auto* i :helpTexts){
- textWidth = my_Max(textWidth, fonsTextBounds(FontStash_Context, 0, 0, i, 0, NULL));
- }
+ f32 textBoxHeight = lh;
+ textBoxHeight *= 7.0f;
+ textBoxHeight += 6.0f;
+ f32 spacing = 10.0f;
- glUseProgram(Flat_Shader->shaderProgram);
+ // 6 lines in total
+ std::vector helpTexts = {
+ "Extensions:",
+ "X: exit"
+ };
+ if (Extensions.head)
+ {
+ TraverseLinkedList(Extensions.head, extension_node)
+ {
+ switch (node->type)
+ {
+ case extension_graph:
+ {
+ graph *gph = (graph *)node->extension;
- vert[0].x = width - spacing - textWidth; vert[0].y = height - spacing - textBoxHeight;
- vert[1].x = width - spacing - textWidth; vert[1].y = height - spacing;
- vert[2].x = width - spacing; vert[2].y = height - spacing;
- vert[3].x = width - spacing; vert[3].y = height - spacing - textBoxHeight;
+ if (strstr((char*)gph->name, "coverage"))
+ {
+ helpTexts.push_back("C: Graph: coverage");
+ }
+ else if (strstr((char*)gph->name, "gap"))
+ {
+ helpTexts.push_back("G: Graph: gap");
+ }
+ else if (strstr((char*)gph->name, "repeat_density"))
+ {
+ helpTexts.push_back("R: Graph: repeat_density");
+ }
+ else if (strstr((char*)gph->name, "telomere"))
+ {
+ helpTexts.push_back("T: Graph: telomere");
+ }
+ }
+ break;
+ }
+ }
+ }
- glBindBuffer(GL_ARRAY_BUFFER, Edit_Mode_Data->vbos[ptr]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
- glBindVertexArray(Edit_Mode_Data->vaos[ptr++]);
- glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ f32 textWidth = 0.;
+ for (auto i : helpTexts)
+ {
+ textWidth = my_Max(textWidth, fonsTextBounds(FontStash_Context, 0, 0, i.c_str(), 0, NULL)) ;
+ }
+ textWidth += 0.5f * spacing;
- glUseProgram(UI_Shader->shaderProgram);
+ glUseProgram(Flat_Shader->shaderProgram);
+ glUniform4fv(Flat_Shader->colorLocation, 1, (f32 *)&Extension_Mode_Data->bg);
- for (int i = 0; i < helpTexts.size(); i++)
- {
- fonsDrawText(
- FontStash_Context,
- width - spacing - textWidth,
- height - spacing - textBoxHeight + (i * (lh + 1.0f)),
- helpTexts[i],
- 0);
- }
- }
+ vert[0].x = width - spacing - textWidth; vert[0].y = height - spacing - textBoxHeight;
+ vert[1].x = width - spacing - textWidth; vert[1].y = height - spacing;
+ vert[2].x = width - spacing; vert[2].y = height - spacing;
+ vert[3].x = width - spacing; vert[3].y = height - spacing - textBoxHeight;
+
+ glBindBuffer(GL_ARRAY_BUFFER, Waypoint_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Waypoint_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+
+ glUseProgram(UI_Shader->shaderProgram);
+ for (u32 i=0; i< helpTexts.size() ; i++)
+ {
+ fonsDrawText(
+ FontStash_Context,
+ width - spacing - textWidth,
+ height - spacing - textBoxHeight + (lh + 1.0f) * i,
+ helpTexts[i].c_str(),
+ 0);
}
}
- // NK
- if (UI_On)
- {
- glDisable(GL_CULL_FACE);
- glEnable(GL_SCISSOR_TEST);
+ // label to show the selected sequence 从 input sequences 里面选中的片段
+ if (Selected_Sequence_Cover_Countor.end_time > 0.)
+ {
+ f64 crt_time = GetTime();
+ if (crt_time < Selected_Sequence_Cover_Countor.end_time)
+ {
+ char buff[128];
+ f32 colour[4] = {1.0, 1.0, 1.0, 1.0};
+ snprintf(buff, 128, "%s (%u)", (char *)((Original_Contigs+Selected_Sequence_Cover_Countor.original_contig_index)->name), Selected_Sequence_Cover_Countor.idx_within_original_contig+1);
+
+ f32 textWidth = fonsTextBounds(FontStash_Context, 0, 0, (char *)buff, 0, NULL);
+ ColourGenerator(65, colour);
+ // position of text
+ f32 textX = ModelXToScreen(
+ (f32)Selected_Sequence_Cover_Countor.map_loc / (f32)Number_of_Pixels_1D -0.5f)
+ - (0.5f * textWidth);
+ f32 textY = ModelYToScreen( 0.5f - (f32)Selected_Sequence_Cover_Countor.map_loc / (f32)Number_of_Pixels_1D);
+
+ glUseProgram(UI_Shader->shaderProgram);
+ DrawOutlinedText(
+ FontStash_Context,
+ (nk_colorf *)colour,
+ (char *)buff,
+ textX,
+ textY,
+ 3.0f, true);
+ Selected_Sequence_Cover_Countor.plotted = true;
+ }
+ else
+ {
+ Selected_Sequence_Cover_Countor.clear();
+ Redisplay = 1;
+ }
+ }
+ // Scaff Bars
+ if (File_Loaded && (Scaff_Edit_Mode || Scaffs_Always_Visible))
+ {
+ glUseProgram(Flat_Shader->shaderProgram);
+ glUniformMatrix4fv(Flat_Shader->matLocation, 1, GL_FALSE, textNormalMat);
glUseProgram(UI_Shader->shaderProgram);
glUniformMatrix4fv(UI_Shader->matLocation, 1, GL_FALSE, textNormalMat);
+
glViewport(0, 0, (s32)width, (s32)height);
+ u32 ptr = 0;
+ vertex vert[4];
+ f32 barColour[4] = {1.0f, 1.0f, 1.0f, 0.5f};
+
+ f32 lh = 0.0f;
+ fonsClearState(FontStash_Context);
+#define DefaultScaffSize 40.0f
+ fonsSetSize(FontStash_Context, Scaff_Mode_Data->size * Screen_Scale.x);
+ fonsSetAlign(FontStash_Context, FONS_ALIGN_MIDDLE | FONS_ALIGN_TOP);
+ fonsSetFont(FontStash_Context, Font_Bold);
+ fonsVertMetrics(FontStash_Context, 0, 0, &lh);
+
+ char buff[128];
+ f32 position = 0.0f;
+ f32 start = 0.0f;
+ u32 scaffId = Contigs->contigs_arr->scaffId;
+ ForLoop(Contigs->numberOfContigs)
{
- const struct nk_draw_command *cmd;
- void *vertices, *elements;
- nk_draw_index *offset = 0;
+ contig *cont = Contigs->contigs_arr + index;
- glBindVertexArray(NK_Device->vao);
- glBindBuffer(GL_ARRAY_BUFFER, NK_Device->vbo);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, NK_Device->ebo);
+ if (cont->scaffId != scaffId)
+ {
+ if (scaffId)
+ {
+ vert[0].x = ModelXToScreen(start - 0.5f); vert[0].y = ModelYToScreen(0.5f - start);
+ vert[1].x = ModelXToScreen(start - 0.5f); vert[1].y = ModelYToScreen(0.5f - position);
+ vert[2].x = ModelXToScreen(position - 0.5f); vert[2].y = ModelYToScreen(0.5f - position);
+ vert[3].x = ModelXToScreen(position - 0.5f); vert[3].y = ModelYToScreen(0.5f - start);
-#define MAX_VERTEX_MEMORY KiloByte(512)
-#define MAX_ELEMENT_MEMORY KiloByte(128)
- glBufferData(GL_ARRAY_BUFFER, MAX_VERTEX_MEMORY, NULL, GL_STREAM_DRAW);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_ELEMENT_MEMORY, NULL, GL_STREAM_DRAW);
+ ColourGenerator((u32)scaffId, (f32 *)barColour);
+ u32 colour = ThreeFloatColorToU32(*((nk_colorf *)barColour));
- vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
- elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
+ glUseProgram(Flat_Shader->shaderProgram);
+ glUniform4fv(Flat_Shader->colorLocation, 1, (GLfloat *)&barColour);
- {
- nk_convert_config config;
- static const nk_draw_vertex_layout_element vertex_layout[] = {
- {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(nk_glfw_vertex, position)},
- {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(nk_glfw_vertex, uv)},
- {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(nk_glfw_vertex, col)},
- {NK_VERTEX_LAYOUT_END}
- };
+ glBindBuffer(GL_ARRAY_BUFFER, Scaff_Bar_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Scaff_Bar_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- NK_MEMSET(&config, 0, sizeof(config));
- config.vertex_layout = vertex_layout;
- config.vertex_size = sizeof(nk_glfw_vertex);
- config.vertex_alignment = NK_ALIGNOF(nk_glfw_vertex);
- config.null = NK_Device->null;
- config.circle_segment_count = 22;
- config.curve_segment_count = 22;
- config.arc_segment_count = 22;
- config.global_alpha = 1.0f;
- config.shape_AA = NK_ANTI_ALIASING_ON;
- config.line_AA = NK_ANTI_ALIASING_ON;
+ glUseProgram(UI_Shader->shaderProgram);
+ fonsSetColor(FontStash_Context, colour);
- {
- nk_buffer vbuf, ebuf;
- nk_buffer_init_fixed(&vbuf, vertices, MAX_VERTEX_MEMORY);
- nk_buffer_init_fixed(&ebuf, elements, MAX_ELEMENT_MEMORY);
- nk_convert(NK_Context, &NK_Device->cmds, &vbuf, &ebuf, &config);
+ stbsp_snprintf(buff, sizeof(buff), "Scaffold %u", scaffId);
+ f32 textWidth = fonsTextBounds(FontStash_Context, 0, 0, buff, 0, NULL);
+ fonsDrawText(FontStash_Context, ModelXToScreen(0.5f * (position + start - 1.0f)) - (0.5f * textWidth), ModelYToScreen(0.5f - start) - lh, buff, 0);
}
- }
- glUnmapBuffer(GL_ARRAY_BUFFER);
- glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
- nk_draw_foreach(cmd, NK_Context, &NK_Device->cmds)
- {
- if (!cmd->elem_count) continue;
- glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id);
- glScissor(
- (GLint)(cmd->clip_rect.x),
- (GLint)(height - cmd->clip_rect.y - cmd->clip_rect.h),
- (GLint)(cmd->clip_rect.w),
- (GLint)(cmd->clip_rect.h));
- glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset);
- offset += cmd->elem_count;
+ start = position;
+ scaffId = cont->scaffId;
}
+
+ position += ((f32)cont->length / (f32)Number_of_Pixels_1D);
}
- ChangeSize((s32)width, (s32)height);
- glDisable(GL_SCISSOR_TEST);
- glEnable(GL_CULL_FACE);
+ if (scaffId)
+ {
+ vert[0].x = ModelXToScreen(start - 0.5f); vert[0].y = ModelYToScreen(0.5f - start);
+ vert[1].x = ModelXToScreen(start - 0.5f); vert[1].y = ModelYToScreen(0.5f - position);
+ vert[2].x = ModelXToScreen(position - 0.5f); vert[2].y = ModelYToScreen(0.5f - position);
+ vert[3].x = ModelXToScreen(position - 0.5f); vert[3].y = ModelYToScreen(0.5f - start);
- nk_clear(NK_Context);
- }
+ ColourGenerator((u32)scaffId, (f32 *)barColour);
+ u32 colour = FourFloatColorToU32(*((nk_colorf *)barColour));
- if (Loading)
- {
- u32 colour = glfonsRGBA(Theme_Colour.r, Theme_Colour.g, Theme_Colour.b, Theme_Colour.a);
+ glUseProgram(Flat_Shader->shaderProgram);
+ glUniform4fv(Flat_Shader->colorLocation, 1, (GLfloat *)&barColour);
- fonsClearState(FontStash_Context);
- fonsSetSize(FontStash_Context, 64.0f * Screen_Scale.x);
- fonsSetAlign(FontStash_Context, FONS_ALIGN_CENTER | FONS_ALIGN_MIDDLE);
- fonsSetFont(FontStash_Context, Font_Bold);
- fonsSetColor(FontStash_Context, colour);
+ glBindBuffer(GL_ARRAY_BUFFER, Scaff_Bar_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Scaff_Bar_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- glUseProgram(UI_Shader->shaderProgram);
- glUniformMatrix4fv(Flat_Shader->matLocation, 1, GL_FALSE, textNormalMat);
- glViewport(0, 0, (s32)width, (s32)height);
- fonsDrawText(FontStash_Context, width * 0.5f, height * 0.5f, "Loading...", 0);
+ glUseProgram(UI_Shader->shaderProgram);
+ fonsSetColor(FontStash_Context, colour);
- ChangeSize((s32)width, (s32)height);
- }
+ stbsp_snprintf(buff, sizeof(buff), "Scaffold %u", scaffId);
+ f32 textWidth = fonsTextBounds(FontStash_Context, 0, 0, buff, 0, NULL);
+ fonsDrawText(FontStash_Context, ModelXToScreen(0.5f * (position + start - 1.0f)) - (0.5f * textWidth), ModelYToScreen(0.5f - start) - lh, buff, 0);
+ }
+ if (Scaff_Edit_Mode && !UI_On)
+ {
+ fonsSetSize(FontStash_Context, text_box_size.font_size * Screen_Scale.x);
+ fonsVertMetrics(FontStash_Context, 0, 0, &lh);
+ fonsSetColor(FontStash_Context, FourFloatColorToU32(Scaff_Mode_Data->text));
- if (auto_sort_state)
- {
- u32 colour = glfonsRGBA(Theme_Colour.r, Theme_Colour.g, Theme_Colour.b, Theme_Colour.a);
+ f32 textBoxHeight = lh;
+ textBoxHeight *= 7.0f;
+ textBoxHeight += 6.0f;
+ f32 spacing = 10.0f;
- fonsClearState(FontStash_Context);
- fonsSetSize(FontStash_Context, 64.0f * Screen_Scale.x);
- fonsSetAlign(FontStash_Context, FONS_ALIGN_CENTER | FONS_ALIGN_MIDDLE);
- fonsSetFont(FontStash_Context, Font_Bold);
- fonsSetColor(FontStash_Context, colour);
+ std::vector helpTexts = {
+ "Scaffold Edit Mode",
+ "S: exit",
+ "Left Click: place",
+ "Middle Click / Spacebar: delete",
+ "Shift-D: delete all",
+ "A (Hold): flood fill",
+ "Shift-A (Hold): flood fill and override"
+ };
- glUseProgram(UI_Shader->shaderProgram);
- glUniformMatrix4fv(Flat_Shader->matLocation, 1, GL_FALSE, textNormalMat);
- glViewport(0, 0, (s32)width, (s32)height);
- fonsDrawText(FontStash_Context, width * 0.5f, height * 0.5f, "Pixel Sorting...", 0);
+ f32 textWidth =0.f;
+ for (const auto& tmp:helpTexts)
+ textWidth = std::max(textWidth, fonsTextBounds(FontStash_Context, 0, 0, tmp.c_str(), 0, NULL));
- ChangeSize((s32)width, (s32)height);
- }
+ glUseProgram(Flat_Shader->shaderProgram);
+ glUniform4fv(Flat_Shader->colorLocation, 1, (f32 *)&Scaff_Mode_Data->bg);
- if (auto_cut_state)
- {
- u32 colour = glfonsRGBA(Theme_Colour.r, Theme_Colour.g, Theme_Colour.b, Theme_Colour.a);
+ vert[0].x = width - spacing - textWidth; vert[0].y = height - spacing - textBoxHeight;
+ vert[1].x = width - spacing - textWidth; vert[1].y = height - spacing;
+ vert[2].x = width - spacing; vert[2].y = height - spacing;
+ vert[3].x = width - spacing; vert[3].y = height - spacing - textBoxHeight;
- fonsClearState(FontStash_Context);
- fonsSetSize(FontStash_Context, 64.0f * Screen_Scale.x);
- fonsSetAlign(FontStash_Context, FONS_ALIGN_CENTER | FONS_ALIGN_MIDDLE);
- fonsSetFont(FontStash_Context, Font_Bold);
- fonsSetColor(FontStash_Context, colour);
+ glBindBuffer(GL_ARRAY_BUFFER, Waypoint_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Waypoint_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- glUseProgram(UI_Shader->shaderProgram);
- glUniformMatrix4fv(Flat_Shader->matLocation, 1, GL_FALSE, textNormalMat);
- glViewport(0, 0, (s32)width, (s32)height);
- fonsDrawText(FontStash_Context, width * 0.5f, height * 0.5f, "Pixel cut...", 0);
+ glUseProgram(UI_Shader->shaderProgram);
+ for (u32 i=0; i< helpTexts.size() ; i++)
+ {
+ fonsDrawText(
+ FontStash_Context,
+ width - spacing - textWidth,
+ height - spacing - textBoxHeight + (lh + 1.0f) * i,
+ helpTexts[i].c_str(),
+ 0);
+ }
+ }
+ } // scaff_mode
- ChangeSize((s32)width, (s32)height);
- }
- }
-}
+ // draw the screen for select fragments for sorting
+ if (File_Loaded && !UI_On && Select_Sort_Area_Mode)
+ {
+ f32 lh = 0.f;
+ f32 start_fraction = (f32)auto_curation_state.get_start()/(f32)Number_of_Pixels_1D;
+ f32 end_fraction = (f32)auto_curation_state.get_end() /(f32)Number_of_Pixels_1D;
-global_variable
-file_atlas_entry *
-File_Atlas;
+ { // draw the help text in the bottom right corner
+ fonsSetFont(FontStash_Context, Font_Bold);
+ fonsSetSize(FontStash_Context, text_box_size.font_size * Screen_Scale.x);
+ fonsVertMetrics(FontStash_Context, 0, 0, &lh);
+ fonsSetColor(FontStash_Context, FourFloatColorToU32(Scaff_Mode_Data->text));
-global_function
-void
-LoadTexture(void *in)
-{ //
- GLuint *textureHandle = (GLuint *)in;
+ std::vector helpTexts = {
+ "Select/Exclude area for sorting",
+ "F: exit",
+ "S: clear select area",
+ "C/Z: cut / cancel cut",
+ "Q/W: quit / redo edit",
+ "Space: Pixel sort",
+ "Left Click: un/select the fragment",
+ fmt::format("Up/Down: inc/dec Cut threshold: {:.4f}", auto_curation_state.auto_cut_threshold),
+ fmt::format("Left/Right: change Sort Mode ({})", auto_curation_state.sort_mode_names[auto_curation_state.sort_mode]),
+ fmt::format("Left/Right Shift: Number of Clusters: {}", auto_curation_state.num_clusters),
+ fmt::format("H: Hap_Name_Clustering: {}", auto_curation_state.hap_cluster_flag ? "ON" : "OFF"),
+ fmt::format("O: Cut with gap: {}", auto_curation_state.auto_cut_with_extension? "ON" : "OFF"),
+ };
- texture_buffer *buffer = TakeTextureBufferFromQueue_Wait(Texture_Buffer_Queue); // take a buffer from the queue
- // assign the texture handle to the buffer
- buffer->x = (u16)(*textureHandle >> 16); // the former 16 bits represent the row number
- buffer->y = (u16)(*textureHandle & ((1 << 16) - 1)); // the lower 16 bits represnet the column number
+ f32 textBoxHeight = (f32)helpTexts.size() * (lh + 1.0f) - 1.0f;
+ f32 spacing = 10.0f;
- /*
- rule for linear ordering
- Ordering of the texture boxes
- ========================
- 00 01 02 03 04 ... 30 31
- // 32 33 34 35 ... 61 62
- // // 63 64 65 ... 91 92
- // // // ...
- ========================
- */
- // u32 linearIndex = (buffer->x * (Number_of_Textures_1D - 1)) - ((buffer->x * (buffer->x-1)) >> 1) + buffer->y; // get the index accoding to index in x and y diretion
- u32 linearIndex = texture_id_cal((u32)buffer->x, (u32)buffer->y, (u32)Number_of_Textures_1D);
+ f32 textWidth = 0.f;
+ for (const auto& i :helpTexts){
+ textWidth = my_Max(textWidth, fonsTextBounds(FontStash_Context, 0, 0, i.c_str(), 0, NULL));
+ }
+ textWidth = my_Min(textWidth, width - 2 * spacing);
- file_atlas_entry *entry = File_Atlas + linearIndex; // set a tempory pointer
- u32 nBytes = entry->nBytes; // base is the beginning, nBytes is the size
- fseek(buffer->file, entry->base, SEEK_SET); // move from the begining to the start of this texture numbered as linearIndex
+ glUseProgram(Flat_Shader->shaderProgram);
+ glUniform4fv(Flat_Shader->colorLocation, 1, (f32 *)&Scaff_Mode_Data->bg);
+ point2f vert[4];
+ vert[0].x = width - spacing - textWidth; vert[0].y = height - spacing - textBoxHeight;
+ vert[1].x = width - spacing - textWidth; vert[1].y = height - spacing;
+ vert[2].x = width - spacing; vert[2].y = height - spacing;
+ vert[3].x = width - spacing; vert[3].y = height - spacing - textBoxHeight;
+
+ u32 ptr = 0;
+ glBindBuffer(GL_ARRAY_BUFFER, Edit_Mode_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Edit_Mode_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- fread(buffer->compressionBuffer, 1, nBytes, buffer->file); // read texture to the buffer
+ glUseProgram(UI_Shader->shaderProgram);
- if (
- libdeflate_deflate_decompress(
- buffer->decompressor, // compresser object
- (const void *)buffer->compressionBuffer, // buffer data before decompressing
- nBytes, // size before decompressing
- (void *)buffer->texture, // place to store the data after decompressing
- Bytes_Per_Texture, // size after decompressing
- NULL)
- )
- { // 解压压缩的texture到 buffer->texture
- fprintf(stderr, "Could not decompress texture from disk\n");
- }
+ for (int i = 0; i < helpTexts.size(); i++)
+ {
+ fonsDrawText(
+ FontStash_Context,
+ width - spacing - textWidth,
+ height - spacing - textBoxHeight + (i * (lh + 1.0f)),
+ helpTexts[i].c_str(),
+ 0);
+ }
+ }
- while (true)
- {
- FenceIn(u32 texture_index_tmp = static_cast(Texture_Ptr));
- if (linearIndex == texture_index_tmp) break;
- }
+ { // paint the selected area
+ if (start_fraction >= 0 && end_fraction >= 0 )
+ {
+ u32 ptr = 0;
+ point2f vert[4];
- FenceIn(Current_Loaded_Texture = buffer); // assign buffer to current_loaded_texture
-
-}
+ // draw the start & end point
+ {
+ f32 line_width = 0.002f / Camera_Position.z;
+ f32 mask_color[4] = {1.0f, 0.f, 0.f, 0.8f}; // red
+ glUseProgram(Flat_Shader->shaderProgram);
+ glUniform4fv(Flat_Shader->colorLocation, 1, (GLfloat *)&mask_color);
+ for (auto loc_fraction : {start_fraction, end_fraction})
+ {
+ vert[0].x = ModelXToScreen(loc_fraction - 0.5f - line_width); vert[0].y = ModelYToScreen(0.5f - loc_fraction + line_width);
+ vert[1].x = ModelXToScreen(loc_fraction - 0.5f - line_width); vert[1].y = ModelYToScreen(0.5f - loc_fraction - line_width);
+ vert[2].x = ModelXToScreen(loc_fraction - 0.5f + line_width); vert[2].y = ModelYToScreen(0.5f - loc_fraction - line_width);
+ vert[3].x = ModelXToScreen(loc_fraction - 0.5f + line_width); vert[3].y = ModelYToScreen(0.5f - loc_fraction + line_width);
-global_function
-void
-PopulateTextureLoadQueue(void *in) // 填充已经初始化过的 所有的queue,填充的任务为所有的528个texture的读取任务
-{
- u32 *packedTextureIndexes = (u32 *)in; // 将空指针转化为u32
- u32 ptr = 0;
- ForLoop(Number_of_Textures_1D) // row number
- {
- for (u32 index2 = index; index2 < Number_of_Textures_1D; index2++ ) // column number
- {
- packedTextureIndexes[ptr] = (index << 16) | (index2); // first 16 bits is the raw number and the second 16 bits is the column number, there will be problem if number of texture in one dimension is larger than 2^16, but it is not possible ... just for a reminder
- ThreadPoolAddTask(Thread_Pool, LoadTexture, (void *)(packedTextureIndexes + ptr++)); // 填充当前的任务队列,输入为对应的texture的行、列编号
- }
- }
-}
+ glBindBuffer(GL_ARRAY_BUFFER, Scaff_Bar_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Scaff_Bar_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ }
+ }
+ // draw the cover on selected area
+ {
+ // f32 mask_color[4] = {0.906f, 0.03921f, 0.949f, 0.5f};
+ vert[0].x = ModelXToScreen(start_fraction - 0.5f); vert[0].y = ModelYToScreen(0.5f - start_fraction);
+ vert[1].x = ModelXToScreen(start_fraction - 0.5f); vert[1].y = ModelYToScreen(0.5f - end_fraction);
+ vert[2].x = ModelXToScreen(end_fraction - 0.5f); vert[2].y = ModelYToScreen(0.5f - end_fraction);
+ vert[3].x = ModelXToScreen(end_fraction - 0.5f); vert[3].y = ModelYToScreen(0.5f - start_fraction);
-/*
-adjust the gamma thus adjust the contrast
-*/
-global_function
-void
-AdjustColorMap(s32 dir)
-{
- f32 unit = 0.05f;
- f32 delta = unit * (dir > 0 ? 1.0f : -1.0f);
+ f32 font_color[4] = {0.f, 0.f, 0.f, 1.f};
+ u32 colour = FourFloatColorToU32(*((nk_colorf *)font_color));
- Color_Maps->controlPoints[1] = my_Max(
- my_Min(Color_Maps->controlPoints[1] + delta, Color_Maps->controlPoints[2]),
- Color_Maps->controlPoints[0]
- );
+ glUseProgram(Flat_Shader->shaderProgram);
+ glUniform4fv(Flat_Shader->colorLocation, 1, (GLfloat *)&auto_curation_state.mask_color);
- glUseProgram(Contact_Matrix->shaderProgram);
- glUniform3fv( Color_Maps->cpLocation, 1, Color_Maps->controlPoints);
-}
+ glBindBuffer(GL_ARRAY_BUFFER, Scaff_Bar_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Scaff_Bar_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ glUseProgram(UI_Shader->shaderProgram);
+ fonsSetColor(FontStash_Context, colour);
+
+ // selected frags into a string
+ s32 selected_fragment_size = 1, last_contig = Map_State->contigIds[auto_curation_state.get_start()];
+ for (s32 i = auto_curation_state.get_start()+1; i < auto_curation_state.get_end(); i++)
+ {
+ if (last_contig!=Map_State->contigIds[i])
+ {
+ selected_fragment_size ++ ;
+ last_contig = Map_State->contigIds[i];
+ }
+ }
+ std::string buff = fmt::format(
+ "{}: ({}) pixels, ({}) fragments",
+ auto_curation_state.selected_or_exclude==0?"Selected" :"Excluded",
+ std::abs(auto_curation_state.get_end() - auto_curation_state.get_start()),
+ selected_fragment_size);
-/*
-change to the last or next color map
-*/
-global_function
-void
-NextColorMap(s32 dir)
-{
- glActiveTexture(GL_TEXTURE1);
-
- if (useCustomOrder)
- {
- // Find the current index in the custom order
- u32 currentIndex = 0;
- for (u32 i = 0; i < userColourMapOrder.nMaps; i++)
- {
- if (userColourMapOrder.order[i] == Color_Maps->currMap)
- {
- currentIndex = i;
- break;
+ f32 lh = 0.0f;
+ f32 textWidth = fonsTextBounds(FontStash_Context, 0, 0, buff.c_str(), 0, NULL);
+ fonsDrawText(
+ FontStash_Context,
+ ModelXToScreen( 0.5f * (end_fraction + start_fraction ) - 0.5f) - (0.5f * textWidth),
+ ModelYToScreen(0.5f - 0.5f*(start_fraction + end_fraction)) - lh * 0.5f, buff.c_str(), 0);
+ }
+ }
}
- }
-
- // Calculate the next index in the custom order
- u32 nextIndex = dir > 0 ? (currentIndex == (userColourMapOrder.nMaps - 1) ? 0 : currentIndex + 1) : (currentIndex == 0 ? userColourMapOrder.nMaps - 1 : currentIndex - 1);
-
- Color_Maps->currMap = userColourMapOrder.order[nextIndex];
- }
- else
- {
- Color_Maps->currMap = dir > 0 ? (Color_Maps->currMap == (Color_Maps->nMaps - 1) ? 0 : Color_Maps->currMap + 1) : (Color_Maps->currMap == 0 ? Color_Maps->nMaps - 1 : Color_Maps->currMap - 1);
- }
-
- glBindTexture(GL_TEXTURE_BUFFER, Color_Maps->maps[Color_Maps->currMap]);
-
- glActiveTexture(GL_TEXTURE0);
-}
-
-
-global_function
-u32
-GetOrderedColorMapIndex(u32 displayIndex)
-{
- if (displayIndex < userColourMapOrder.nMaps)
- {
- return userColourMapOrder.order[displayIndex];
- }
- return displayIndex;
-}
-
+ } // select_sort_area
-global_function void
-InitializeColorMapOrder()
-{
- userColourMapOrder.nMaps = Color_Maps->nMaps;
- for (u32 i = 0; i < userColourMapOrder.nMaps; i++)
- {
- userColourMapOrder.order[i] = i;
- }
-}
+ // Meta Tags
+ if (File_Loaded && (MetaData_Edit_Mode || MetaData_Always_Visible))
+ {
+ glUseProgram(Flat_Shader->shaderProgram);
+ glUniformMatrix4fv(Flat_Shader->matLocation, 1, GL_FALSE, textNormalMat);
+ glUseProgram(UI_Shader->shaderProgram);
+ glUniformMatrix4fv(UI_Shader->matLocation, 1, GL_FALSE, textNormalMat);
+ glViewport(0, 0, (s32)width, (s32)height);
-global_variable
-GLuint
-Quad_EBO;
+ f32 colour[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ vertex vert[4];
+ u32 ptr = 0;
+ f32 barColour[4] = {1.0f, 1.0f, 1.0f, 0.5f};
-enum
-load_file_result
-{
- ok,
- fileErr,
- decompErr,
-};
+ f32 lh = 0.0f;
+ fonsClearState(FontStash_Context);
+#define DefaultMetaDataSize 20.0f
+ fonsSetSize(FontStash_Context, MetaData_Mode_Data->size * Screen_Scale.x);
+ fonsSetAlign(FontStash_Context, FONS_ALIGN_MIDDLE | FONS_ALIGN_TOP);
+ fonsSetFont(FontStash_Context, Font_Bold);
+ fonsVertMetrics(FontStash_Context, 0, 0, &lh);
-global_variable
-libdeflate_decompressor *
-Decompressor;
+ f32 end_contig = 0.0f, start_contig = 0.0f;
+ u32 scaffId = Contigs->contigs_arr->scaffId;
+ ForLoop(Contigs->numberOfContigs)
+ {
+ contig *cont = Contigs->contigs_arr + index;
+ end_contig += ((f32)cont->length / (f32)Number_of_Pixels_1D); // end of the contig
+ if (*cont->metaDataFlags)
+ {
+ u32 tmp = 0; // used to count the number of tags drawn
+ ForLoop2(ArrayCount(Meta_Data->tags))
+ {
+ if (*cont->metaDataFlags & ((u64)1 << index2))
+ {
+ f32 textWidth = fonsTextBounds(FontStash_Context, 0, 0, (char *)Meta_Data->tags[index2], 0, NULL);
+ ColourGenerator(index2 + 1, colour);
+ // fonsSetColor(FontStash_Context, FourFloatColorToU32(*((nk_colorf *)colour)));
+ // fonsDrawText(FontStash_Context, ModelXToScreen(0.5f * (end_contig + start_contig - 1.0f)) - (0.5f * textWidth), ModelYToScreen((0.5f * (1.0f - end_contig - start_contig))) - (lh * (f32)(++tmp)), (char *)Meta_Data->tags[index2], 0);
+ if (meta_outline->on)
+ {
+ // position of text
+ f32 textX = ModelXToScreen(0.5f * (end_contig + start_contig - 1.0f)) - (0.5f * textWidth);
+ f32 textY = ModelYToScreen((0.5f * (1.0f - end_contig - start_contig))) - (lh * (f32)(++tmp));
-global_variable
-libdeflate_compressor *
-Compressor;
+ DrawOutlinedText(FontStash_Context, (nk_colorf *)colour, (char *)Meta_Data->tags[index2], textX, textY);
+ }
+ else
+ {
+ fonsSetColor(FontStash_Context, FourFloatColorToU32(*((nk_colorf *)colour)));
+ fonsDrawText(
+ FontStash_Context,
+ ModelXToScreen(0.5f * (end_contig + start_contig - 1.0f)) - (0.5f * textWidth),
+ ModelYToScreen((0.5f * (1.0f - end_contig - start_contig))) - (lh * (f32)(++tmp)),
+ (char *)Meta_Data->tags[index2],
+ 0);
+ }
+ }
+ }
-global_variable
-u08 Magic[] = {'p', 's', 't', 'm'};
+ // draw the grey out mask
+ auto paint_func = [&](const void* vert_) {
+ ColourGenerator((u32)0, (f32 *)barColour);
+ u32 colour = FourFloatColorToU32(*((nk_colorf *)barColour));
-global_function
-FILE *
-TestFile(const char *fileName, u64 *fileSize = 0)
-{
- FILE *file=0;
- {
- file = fopen(fileName, "rb");
- if (!file)
- {
-#ifdef DEBUG
- fprintf(stderr, "The file is not available: \'%s\' [errno %d] \n", fileName, errno);
- exit(errno);
-#endif
- }
- else
- {
- if (fileSize)
- {
- fseek(file, 0, SEEK_END);
- *fileSize = (u64)ftell(file);
- fseek(file, 0, SEEK_SET);
- }
+ glUseProgram(Flat_Shader->shaderProgram);
+ glUniform4fv(Flat_Shader->colorLocation, 1, (GLfloat *)&barColour);
- u08 magicTest[sizeof(Magic)];
+ glBindBuffer(GL_ARRAY_BUFFER, Scaff_Bar_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert_);
+ glBindVertexArray(Scaff_Bar_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- u32 bytesRead = (u32)fread(magicTest, 1, sizeof(magicTest), file);
- if (bytesRead == sizeof(magicTest))
- {
- ForLoop(sizeof(Magic)) // #define ForLoop(n) for (u32 index=0; indexshaderProgram);
+ fonsSetColor(FontStash_Context, colour);
+ };
+ std::string grey_out_tag = Grey_Out_Settings->is_grey_out(cont->metaDataFlags, Meta_Data);
+ if (!grey_out_tag.empty())
{
- fclose(file);
- file = 0;
- break;
+ vert[0].x = ModelXToScreen(start_contig - 0.5f); vert[0].y = ModelYToScreen(0.5f - start_contig);
+ vert[1].x = ModelXToScreen(start_contig - 0.5f); vert[1].y = ModelYToScreen(0.5f - end_contig);
+ vert[2].x = ModelXToScreen(end_contig - 0.5f); vert[2].y = ModelYToScreen(0.5f - end_contig);
+ vert[3].x = ModelXToScreen(end_contig - 0.5f); vert[3].y = ModelYToScreen(0.5f - start_contig);
+ paint_func(vert);
+ }
+ else{
+
+ int is_vert_horiz_grey_out = Grey_Out_Settings->is_vert_horiz_grey_out(cont->metaDataFlags, Meta_Data);
+ if (is_vert_horiz_grey_out != 0) {
+ // draw the vertical or horizontal grey out mask
+ vert[0].x = ModelXToScreen(start_contig - 0.5f); vert[0].y = ModelYToScreen(0.5f - start_contig);
+ vert[1].x = ModelXToScreen(start_contig - 0.5f); vert[1].y = ModelYToScreen(0.5f - end_contig);
+ vert[2].x = ModelXToScreen(end_contig - 0.5f); vert[2].y = ModelYToScreen(0.5f - end_contig);
+ vert[3].x = ModelXToScreen(end_contig - 0.5f); vert[3].y = ModelYToScreen(0.5f - start_contig);
+
+ if (is_vert_horiz_grey_out == 1) { // vertical
+ vert[0].y = ModelYToScreen( 0.5f);
+ vert[1].y = ModelYToScreen(-0.5f);
+ vert[2].y = ModelYToScreen(-0.5f);
+ vert[3].y = ModelYToScreen( 0.5f);
+ paint_func(vert);
+ }
+ else if (is_vert_horiz_grey_out == 2) { // horizontal
+ vert[0].x = ModelXToScreen(-0.5f);
+ vert[1].x = ModelXToScreen(-0.5f);
+ vert[2].x = ModelXToScreen( 0.5f);
+ vert[3].x = ModelXToScreen( 0.5f);
+ paint_func(vert);
+ }
+ else if (is_vert_horiz_grey_out == 3) { // corss
+ // paint the hrizontal
+ vert[0].x = ModelXToScreen(-0.5f);
+ vert[1].x = ModelXToScreen(-0.5f);
+ vert[2].x = ModelXToScreen( 0.5f);
+ vert[3].x = ModelXToScreen( 0.5f);
+ paint_func(vert);
+
+ // paint the vertical uppon
+ vertex vert_v0[4];
+ vert_v0[0].x = ModelXToScreen(start_contig - 0.5f); vert_v0[0].y = ModelYToScreen(0.5f);
+ vert_v0[1].x = ModelXToScreen(start_contig - 0.5f); vert_v0[1].y = ModelYToScreen(0.5f - start_contig);
+ vert_v0[2].x = ModelXToScreen(end_contig - 0.5f); vert_v0[2].y = ModelYToScreen(0.5f - start_contig);
+ vert_v0[3].x = ModelXToScreen(end_contig - 0.5f); vert_v0[3].y = ModelYToScreen(0.5f);
+ paint_func(vert_v0);
+
+ // paint the vertical bottom
+ vertex vert_v1[4];
+ vert_v1[0].x = ModelXToScreen(start_contig - 0.5f); vert_v1[0].y = ModelYToScreen(0.5f - end_contig);
+ vert_v1[1].x = ModelXToScreen(start_contig - 0.5f); vert_v1[1].y = ModelYToScreen(-0.5f);
+ vert_v1[2].x = ModelXToScreen(end_contig - 0.5f); vert_v1[2].y = ModelYToScreen(-0.5f);
+ vert_v1[3].x = ModelXToScreen(end_contig - 0.5f); vert_v1[3].y = ModelYToScreen(0.5f - end_contig);
+ paint_func(vert_v1);
+ }
+ }
+ else { // not grey out vertically, horizontally or crossly.
+ // throw std::runtime_error(fmt::format("This part is unreachable! File: {}, line: {}\n", __FILE__, __LINE__));
+ }
}
+
}
+ start_contig = end_contig;
+ scaffId = cont->scaffId;
}
- else
+
+ if (MetaData_Edit_Mode && !UI_On)
{
- fclose(file);
- file = 0;
- }
- }
- }
- return(file); // 仅仅返回正确的file指针,否则返回空指针
-}
+ u32 ptr = 0;
+ vertex vert[4];
+ fonsSetSize(FontStash_Context, text_box_size.font_size * Screen_Scale.x);
+ fonsVertMetrics(FontStash_Context, 0, 0, &lh);
+ fonsSetColor(FontStash_Context, FourFloatColorToU32(MetaData_Mode_Data->text));
+ f32 textBoxHeight = lh;
+ textBoxHeight *= 7.0f;
+ textBoxHeight += 6.0f;
+ f32 spacing = 10.0f;
-global_function
-void
-add_graph_to_extensions(
- memory_arena *arena,
- const u32* graph_name,
- const u32* graph_data)
-{
-
- graph *gph = PushStructP(arena, graph); // create the size to store the extension data
- extension_node *node = PushStructP(arena, extension_node);
- u08 *dataPlusName = PushArrayP(arena, u08, ((sizeof(u32) * Number_of_Pixels_1D) + sizeof(gph->name) ));
- gph->data = (u32 *)(dataPlusName + sizeof(gph->name));
- u32 *namePtr = (u32 *)graph_name;
- for (u32 i = 0; i < ArrayCount(gph->name); i++ ) // get the graph name
- {
- gph->name[i] = *(namePtr + i);
- }
- for (u32 i = 0; i < Number_of_Pixels_1D; i++) // get the graph data
- {
- gph->data[i] = *(graph_data + i);
- }
- node->type = extension_graph; // assign the gph to node
- node->extension = gph;
- AddExtension(node); // add node to extension
-
- return ;
-}
+ char helpText7[128];
+ const char *activeTag = (const char *)Meta_Data->tags[MetaData_Active_Tag];
+ stbsp_snprintf(helpText7, sizeof(helpText7), "Active Tag: %s", strlen(activeTag) ? activeTag : "");
+ std::vector helpTexts = {
+ "MetaData Tag Mode",
+ "M: exit",
+ "Left Click: place",
+ "Middle Click / Spacebar: delete",
+ "Shift-D: delete all",
+ "Arrow Keys: select active tag",
+ helpText7
+ };
+ f32 textWidth = 0.f;
+ for (const auto& tmp:helpTexts)
+ textWidth = std::max(textWidth, fonsTextBounds(FontStash_Context, 0, 0, tmp.c_str(), 0, NULL));
-global_function
-void
-push_extensions_to_opengl(memory_arena *arena, u32 added_index = 0, f32 scale=-1.f)
-{
- u32 exIndex = 0;
- // TraverseLinkedList(Extensions.head, extension_node)
+ glUseProgram(Flat_Shader->shaderProgram);
+ glUniform4fv(Flat_Shader->colorLocation, 1, (f32 *)&MetaData_Mode_Data->bg);
- extension_node* node = Extensions.head ;
- while (added_index--)
- {
- node = node->next; // 移动到最后一个节点
- exIndex ++ ;
- }
- for ( ; node; node = node->next) {
+ vert[0].x = width - spacing - textWidth; vert[0].y = height - spacing - textBoxHeight;
+ vert[1].x = width - spacing - textWidth; vert[1].y = height - spacing;
+ vert[2].x = width - spacing; vert[2].y = height - spacing;
+ vert[3].x = width - spacing; vert[3].y = height - spacing - textBoxHeight;
+
+ glBindBuffer(GL_ARRAY_BUFFER, Waypoint_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Waypoint_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+
+ glUseProgram(UI_Shader->shaderProgram);
+ for (u32 i=0; i< helpTexts.size() ; i++) {
+ fonsDrawText(
+ FontStash_Context,
+ width - spacing - textWidth,
+ height - spacing - textBoxHeight + (lh + 1.0f) * i,
+ helpTexts[i].c_str(),
+ 0);
+ }
+ }
+ }
- switch (node->type)
+ // Tool Tip
+ if (File_Loaded && Tool_Tip->on && !Edit_Mode && !UI_On)
{
- case extension_graph:
- {
- graph *gph = (graph *)node->extension; // get the graph ptr and assigned to gph
-#define DefaultGraphScale 0.2f
-#define DefaultGraphBase 32.0f
-#define DefaultGraphLineSize 1.0f
-#define DefaultGraphColour {0.1f, 0.8f, 0.7f, 1.0f}
- gph->scale = scale>0.f? scale : DefaultGraphScale;
- gph->base = DefaultGraphBase;
- gph->lineSize = DefaultGraphLineSize;
- gph->colour = DefaultGraphColour;
- gph->on = 0;
+ glUseProgram(Flat_Shader->shaderProgram);
+ glUniform4fv(Flat_Shader->colorLocation, 1, (GLfloat *)&Tool_Tip->bg);
+ glUniformMatrix4fv(Flat_Shader->matLocation, 1, GL_FALSE, textNormalMat);
- gph->shader = PushStructP(arena, editable_plot_shader);
- gph->shader->shaderProgram = CreateShader(FragmentSource_EditablePlot.c_str(), VertexSource_EditablePlot.c_str(), GeometrySource_EditablePlot.c_str());
+ glUseProgram(UI_Shader->shaderProgram);
+ glUniformMatrix4fv(UI_Shader->matLocation, 1, GL_FALSE, textNormalMat);
- glUseProgram(gph->shader->shaderProgram);
- glBindFragDataLocation(gph->shader->shaderProgram, 0, "outColor");
- gph->shader->matLocation = glGetUniformLocation(gph->shader->shaderProgram, "matrix");
- gph->shader->colorLocation = glGetUniformLocation(gph->shader->shaderProgram, "color");
- gph->shader->yScaleLocation = glGetUniformLocation(gph->shader->shaderProgram, "yscale");
- gph->shader->yTopLocation = glGetUniformLocation(gph->shader->shaderProgram, "ytop");
- gph->shader->lineSizeLocation = glGetUniformLocation(gph->shader->shaderProgram, "linewidth");
+ vertex vert[4];
- glUniform1i(glGetUniformLocation(gph->shader->shaderProgram, "pixrearrangelookup"), 3);
- glUniform1i(glGetUniformLocation(gph->shader->shaderProgram, "yvalues"), 4 + (s32)exIndex);
+ glViewport(0, 0, (s32)width, (s32)height);
- u32 nValues = Number_of_Pixels_1D;
- auto* xValues = new f32[nValues]; // allocate memory for xValues, actually, x is the coordinate of the pixel
- auto* yValues = new f32[nValues];
-
- u32 max = 0;
- ForLoop(Number_of_Pixels_1D)
- {
- max = my_Max(max, gph->data[index]);
- }
+ f32 lh = 0.0f;
- ForLoop(Number_of_Pixels_1D)
+ fonsClearState(FontStash_Context);
+ fonsSetSize(FontStash_Context, Tool_Tip->size * Screen_Scale.x);
+ fonsSetAlign(FontStash_Context, FONS_ALIGN_LEFT | FONS_ALIGN_TOP);
+ fonsSetFont(FontStash_Context, Font_Normal);
+ fonsVertMetrics(FontStash_Context, 0, 0, &lh);
+ fonsSetColor(FontStash_Context, FourFloatColorToU32(Tool_Tip->fg));
+
+ // Extension info, extra lines
+ u32 nExtra = 0;
+ f32 longestExtraLineLength = 0.0f;
+ {
+ if (Extensions.head)
+ {
+ char buff[128];
+ TraverseLinkedList(Extensions.head, extension_node)
{
- xValues[index] = (f32)index;
- yValues[index] = (f32)gph->data[index] / (f32)max ; // normalise the data
- }
+ switch (node->type)
+ {
+ case extension_graph:
+ {
+ graph *gph = (graph *)node->extension;
+ if (gph->on)
+ {
+ glBindBuffer(GL_TEXTURE_BUFFER, Contact_Matrix->pixelRearrangmentLookupBuffer);
+ u32 *buffer = (u32 *)glMapBufferRange(GL_TEXTURE_BUFFER, Tool_Tip_Move.pixels.x * sizeof(u32), sizeof(u32), GL_MAP_READ_BIT);
- glActiveTexture(GL_TEXTURE4 + exIndex++);
+ stbsp_snprintf(buff, sizeof(buff), "%s: %$d", (char *)gph->name, gph->data[*buffer]);
+ ++nExtra;
+ longestExtraLineLength = my_Max(longestExtraLineLength, fonsTextBounds(FontStash_Context, 0, 0, buff, 0, NULL));
- GLuint yVal, yValTex;
+ glUnmapBuffer(GL_TEXTURE_BUFFER);
+ glBindBuffer(GL_TEXTURE_BUFFER, 0);
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
- // generate a buffer object named yVal and save data to yVal
- glGenBuffers(1, &yVal);
- glBindBuffer(GL_TEXTURE_BUFFER, yVal);
- glBufferData(GL_TEXTURE_BUFFER, sizeof(f32) * nValues, yValues, GL_STATIC_DRAW);
+ f32 textBoxHeight = lh;
+ textBoxHeight *= (3.0f + (f32)nExtra);
+ textBoxHeight += (2.0f + (f32)nExtra);
- // add texture and link to the buffer object
- glGenTextures(1, &yValTex);
- glBindTexture(GL_TEXTURE_BUFFER, yValTex);
- glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, yVal);
+ u32 id1 = Map_State->get_original_contig_id(Tool_Tip_Move.pixels.x);
+ u32 id2 = Map_State->get_original_contig_id(Tool_Tip_Move.pixels.y);
+ u32 coord1 = Map_State->contigRelCoords[Tool_Tip_Move.pixels.x];
+ u32 coord2 = Map_State->contigRelCoords[Tool_Tip_Move.pixels.y];
+
+ f64 bpPerPixel = (f64)Total_Genome_Length / (f64)Number_of_Pixels_1D;
- gph->shader->yValuesBuffer = yVal;
- gph->shader->yValuesBufferTex = yValTex;
-
- // add the vertext data into buffer
- glGenBuffers(1, &gph->vbo);
- glBindBuffer(GL_ARRAY_BUFFER, gph->vbo);
- glBufferData(GL_ARRAY_BUFFER, sizeof(f32) * nValues, xValues, GL_STATIC_DRAW);
+ char line1[64];
+ char *line2 = (char *)"vs";
+ char line3[64];
- // gen the vertex array object
- glGenVertexArrays(1, &gph->vao);
- glBindVertexArray(gph->vao);
+ auto NicePrint = [bpPerPixel](u32 id, u32 coord, char *buffer)
+ {
+ f64 pos = (f64)coord * bpPerPixel;
+ stbsp_snprintf(buffer, 64, "%s %'u %sbp", (Original_Contigs + id)->name, (u32)(pos / (pos > 1000.0 ? 1000.0 : 1.0)), pos > 1000.0 ? "K" : "");
+ };
- GLuint posAttrib = (GLuint)glGetAttribLocation(gph->shader->shaderProgram, "position");
- glEnableVertexAttribArray(posAttrib);
- glVertexAttribPointer(posAttrib, 1, GL_FLOAT, GL_FALSE, 0, 0);
+ NicePrint(id1, coord1, line1);
+ NicePrint(id2, coord2, line3);
- delete[] xValues;
- delete[] yValues;
+ f32 textWidth_1 = fonsTextBounds(FontStash_Context, 0, 0, line1, 0, NULL);
+ f32 textWidth_2 = fonsTextBounds(FontStash_Context, 0, 0, line2, 0, NULL);
+ f32 textWidth_3 = fonsTextBounds(FontStash_Context, 0, 0, line3, 0, NULL);
+ f32 textWidth = my_Max(textWidth_1, textWidth_2);
+ textWidth = my_Max(textWidth, textWidth_3);
+ textWidth = my_Max(textWidth, longestExtraLineLength);
- glActiveTexture(GL_TEXTURE0);
- }
- break;
- }
- }
+ f32 spacing = 12.0f;
- return ;
-}
+ glUseProgram(Flat_Shader->shaderProgram);
+ vert[0].x = ModelXToScreen(Tool_Tip_Move.worldCoords.x) + spacing; vert[0].y = ModelYToScreen(-Tool_Tip_Move.worldCoords.y) + spacing;
+ vert[1].x = ModelXToScreen(Tool_Tip_Move.worldCoords.x) + spacing; vert[1].y = ModelYToScreen(-Tool_Tip_Move.worldCoords.y) + spacing + textBoxHeight;
+ vert[2].x = ModelXToScreen(Tool_Tip_Move.worldCoords.x) + spacing + textWidth; vert[2].y = ModelYToScreen(-Tool_Tip_Move.worldCoords.y) + spacing + textBoxHeight;
+ vert[3].x = ModelXToScreen(Tool_Tip_Move.worldCoords.x) + spacing + textWidth; vert[3].y = ModelYToScreen(-Tool_Tip_Move.worldCoords.y) + spacing;
+ glBindBuffer(GL_ARRAY_BUFFER, Tool_Tip_Data->vbos[0]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Tool_Tip_Data->vaos[0]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
-global_function
-u08
-LoadState(u64 headerHash, char *path = 0);
+ glUseProgram(UI_Shader->shaderProgram);
+ fonsDrawText(FontStash_Context, ModelXToScreen(Tool_Tip_Move.worldCoords.x) + spacing,
+ ModelYToScreen(-Tool_Tip_Move.worldCoords.y) + spacing, line1, 0);
+ fonsDrawText(FontStash_Context, ModelXToScreen(Tool_Tip_Move.worldCoords.x) + spacing,
+ ModelYToScreen(-Tool_Tip_Move.worldCoords.y) + spacing + lh + 1.0f, line2, 0);
+ fonsDrawText(FontStash_Context, ModelXToScreen(Tool_Tip_Move.worldCoords.x) + spacing,
+ ModelYToScreen(-Tool_Tip_Move.worldCoords.y) + spacing + (2.0f * lh) + 2.0f, line3, 0);
-global_function
-load_file_result
-LoadFile(const char *filePath, memory_arena *arena, char **fileName, u64 *headerHash)
-{
- u64 fileSize = 0;
+ {
+ if (Extensions.head)
+ {
+ u32 count = 0;
+ char buff[128];
+ TraverseLinkedList(Extensions.head, extension_node)
+ {
+ switch (node->type)
+ {
+ case extension_graph:
+ {
+ graph *gph = (graph *)node->extension;
+ if (gph->on)
+ {
+ glBindBuffer(GL_TEXTURE_BUFFER, Contact_Matrix->pixelRearrangmentLookupBuffer);
+ u32 *buffer = (u32 *)glMapBufferRange(GL_TEXTURE_BUFFER, Tool_Tip_Move.pixels.x * sizeof(u32), sizeof(u32), GL_MAP_READ_BIT);
- FILE *file = TestFile(filePath, &fileSize); // 检查前4个字节读取到的数据, 如果为 u08 Magic[] = {'p', 's', 't', 'm'} 则通过验证,否则将指针file设置为空指针
- if (!file) // 如果为空指针, 返回读取错误fileErr
- {
- return(fileErr);
- }
-
- FenceIn(File_Loaded = 0);
+ stbsp_snprintf(buff, sizeof(buff), "%s: %$d", (char *)gph->name, gph->data[*buffer]);
- static u32 reload = 0;
-
- if (!reload)
- {
- reload = 1;
- }
- else // clear all the memory, in gl and the arena
- {
- glDeleteTextures(1, &Contact_Matrix->textures);
+ fonsDrawText(FontStash_Context, ModelXToScreen(Tool_Tip_Move.worldCoords.x) + spacing,
+ ModelYToScreen(-Tool_Tip_Move.worldCoords.y) + spacing + ((2.0f + (f32)(++count)) * (lh + 1.0f)), buff, 0);
- glDeleteVertexArrays((GLsizei)(Number_of_Textures_1D * Number_of_Textures_1D), Contact_Matrix->vaos);
- glDeleteBuffers((GLsizei)(Number_of_Textures_1D * Number_of_Textures_1D), Contact_Matrix->vbos);
+ glUnmapBuffer(GL_TEXTURE_BUFFER);
+ glBindBuffer(GL_TEXTURE_BUFFER, 0);
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
- glDeleteBuffers(1, &Contact_Matrix->pixelStartLookupBuffer);
- glDeleteTextures(1, &Contact_Matrix->pixelStartLookupBufferTex);
+ // Edit Mode
+ if (File_Loaded && Edit_Mode && !UI_On) // Edit Mode
+ {
+ u32 ptr = 0;
+ vertex vert[4];
- glDeleteBuffers(1, &Contact_Matrix->pixelRearrangmentLookupBuffer);
- glDeleteTextures(1, &Contact_Matrix->pixelRearrangmentLookupBufferTex);
+ glUseProgram(Flat_Shader->shaderProgram);
+ glUniformMatrix4fv(Flat_Shader->matLocation, 1, GL_FALSE, textNormalMat);
+ glUseProgram(UI_Shader->shaderProgram);
+ glUniformMatrix4fv(UI_Shader->matLocation, 1, GL_FALSE, textNormalMat);
- glDeleteVertexArrays((GLsizei)Grid_Data->nBuffers, Grid_Data->vaos);
- glDeleteBuffers((GLsizei)Grid_Data->nBuffers, Grid_Data->vbos);
+ glUseProgram(Flat_Shader->shaderProgram);
+ glViewport(0, 0, (s32)width, (s32)height);
- glDeleteVertexArrays((GLsizei)Label_Box_Data->nBuffers, Label_Box_Data->vaos);
- glDeleteBuffers((GLsizei)Label_Box_Data->nBuffers, Label_Box_Data->vbos);
+ f32 color[4];
+ f32* source;
+ if (Edit_Pixels.editing) // edit color
+ {
+ if (Global_Edit_Invert_Flag) source = (f32*)&Edit_Mode_Colours->invSelect;
+ else source = (f32*)&Edit_Mode_Colours->select;
+ }
+ else source = (f32*)&Edit_Mode_Colours->preSelect; // pre-edit color
+ ForLoop(4)
+ {
+ color[index] = source[index];
+ }
+ f32 alpha = color[3];
+ color[3] = 1.0f;
- glDeleteVertexArrays((GLsizei)Scale_Bar_Data->nBuffers, Scale_Bar_Data->vaos);
- glDeleteBuffers((GLsizei)Scale_Bar_Data->nBuffers, Scale_Bar_Data->vbos);
+ glUniform4fv(Flat_Shader->colorLocation, 1, color);
- glDeleteVertexArrays((GLsizei)Contig_ColourBar_Data->nBuffers, Contig_ColourBar_Data->vaos);
- glDeleteBuffers((GLsizei)Contig_ColourBar_Data->nBuffers, Contig_ColourBar_Data->vbos);
+ f32 lineWidth = 0.005f / Camera_Position.z;
+
+ { // draw the two squared dots at the beginning and end of the selected fragment
+ vert[0].x = ModelXToScreen(Edit_Pixels.worldCoords.x - lineWidth);
+ vert[0].y = ModelYToScreen(lineWidth - Edit_Pixels.worldCoords.x);
+ vert[1].x = ModelXToScreen(Edit_Pixels.worldCoords.x - lineWidth);
+ vert[1].y = ModelYToScreen(-lineWidth - Edit_Pixels.worldCoords.x);
+ vert[2].x = ModelXToScreen(Edit_Pixels.worldCoords.x + lineWidth);
+ vert[2].y = ModelYToScreen(-lineWidth - Edit_Pixels.worldCoords.x);
+ vert[3].x = ModelXToScreen(Edit_Pixels.worldCoords.x + lineWidth);
+ vert[3].y = ModelYToScreen(lineWidth - Edit_Pixels.worldCoords.x);
- glDeleteVertexArrays((GLsizei)Scaff_Bar_Data->nBuffers, Scaff_Bar_Data->vaos);
- glDeleteBuffers((GLsizei)Scaff_Bar_Data->nBuffers, Scaff_Bar_Data->vbos);
+ glBindBuffer(GL_ARRAY_BUFFER, Edit_Mode_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Edit_Mode_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- TraverseLinkedList(Extensions.head, extension_node)
- {
- switch (node->type)
- {
- case extension_graph:
- {
- graph *gph = (graph *)node->extension;
- glDeleteVertexArrays(1, &gph->vao);
- glDeleteBuffers(1, &gph->vbo);
- glDeleteBuffers(1, &gph->shader->yValuesBuffer);
- glDeleteTextures(1, &gph->shader->yValuesBufferTex);
- }
- break;
+ vert[0].x = ModelXToScreen(Edit_Pixels.worldCoords.y - lineWidth);
+ vert[0].y = ModelYToScreen(lineWidth - Edit_Pixels.worldCoords.y);
+ vert[1].x = ModelXToScreen(Edit_Pixels.worldCoords.y - lineWidth);
+ vert[1].y = ModelYToScreen(-lineWidth - Edit_Pixels.worldCoords.y);
+ vert[2].x = ModelXToScreen(Edit_Pixels.worldCoords.y + lineWidth);
+ vert[2].y = ModelYToScreen(-lineWidth - Edit_Pixels.worldCoords.y);
+ vert[3].x = ModelXToScreen(Edit_Pixels.worldCoords.y + lineWidth);
+ vert[3].y = ModelYToScreen(lineWidth - Edit_Pixels.worldCoords.y);
+
+ glBindBuffer(GL_ARRAY_BUFFER, Edit_Mode_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Edit_Mode_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
}
- }
+
+ f32 min = my_Min(Edit_Pixels.worldCoords.x, Edit_Pixels.worldCoords.y);
+ f32 max = my_Max(Edit_Pixels.worldCoords.x, Edit_Pixels.worldCoords.y);
- Current_Loaded_Texture = 0;
- Texture_Ptr = 0;
-
- Mouse_Move.x = -1.0;
- Mouse_Move.y = -1.0;
+ if (Global_Edit_Invert_Flag) // draw the two arrows
+ {
+ f32 spacing = 0.002f / Camera_Position.z;
+ f32 arrowWidth = 0.01f / Camera_Position.z;
+ f32 arrowHeight = arrowWidth * 0.65f;
+ f32 recHeight = arrowHeight * 0.65f;
- Camera_Position.x = 0.0f;
- Camera_Position.y = 0.0f;
- Camera_Position.z = 1.0f;
-
- Edit_Pixels.editing = 0;
- Global_Mode = mode_normal;
+ // draw the the triangle part
+ vert[0].x = ModelXToScreen(min + spacing); vert[0].y = ModelYToScreen(arrowHeight + spacing - min);
+ vert[1].x = ModelXToScreen(min + spacing + arrowWidth); vert[1].y = ModelYToScreen(spacing - min);
+ vert[2].x = ModelXToScreen(min + spacing + arrowWidth); vert[2].y = ModelYToScreen(arrowHeight + spacing - min);
+ vert[3].x = ModelXToScreen(min + spacing + arrowWidth); vert[3].y = ModelYToScreen((2.0f * arrowHeight) + spacing - min);
+
+ glBindBuffer(GL_ARRAY_BUFFER, Edit_Mode_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Edit_Mode_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- Extensions = {};
+ // draw the rectangle part
+ vert[0].x = ModelXToScreen(min + spacing + arrowWidth); vert[0].y = ModelYToScreen((arrowHeight + 0.5f * recHeight) + spacing - min);
+ vert[1].x = ModelXToScreen(min + spacing + arrowWidth); vert[1].y = ModelYToScreen((arrowHeight - 0.5f * recHeight) + spacing - min);
+ vert[2].x = ModelXToScreen(max - spacing); vert[2].y = ModelYToScreen((arrowHeight - 0.5f * recHeight) + spacing - min);
+ vert[3].x = ModelXToScreen(max - spacing); vert[3].y = ModelYToScreen((arrowHeight + 0.5f * recHeight) + spacing - min);
+ glBindBuffer(GL_ARRAY_BUFFER, Edit_Mode_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Edit_Mode_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ }
- // delete the memory collected by new
- if (Contact_Matrix->vaos)
- {
- delete[] Contact_Matrix->vaos;
- Contact_Matrix->vaos = nullptr;
- }
- if (Contact_Matrix->vbos)
- {
- delete[] Contact_Matrix->vbos;
- Contact_Matrix->vbos = nullptr;
- }
- if (pixel_density_extension)
- {
- delete pixel_density_extension;
- pixel_density_extension = nullptr;
- }
- if (frag_cut_cal_ptr)
- {
- delete frag_cut_cal_ptr;
- frag_cut_cal_ptr = nullptr;
- }
- ResetMemoryArenaP(arena); // release all the memory allocated, avoid memory leak
- auto_curation_state.clear();
- }
+ { // draw the interacted area
+
+ color[3] = alpha;
+ glUniform4fv(Flat_Shader->colorLocation, 1, color);
- // File Contents
- {
- char *tmp = (char *)filePath;
-#ifdef _WIN32
- char sep = '\\';
-#else
- char sep = '/';
-#endif
+ // upper vertical part
+ vert[0].x = ModelXToScreen(min); vert[0].y = ModelYToScreen(0.5f);
+ vert[1].x = ModelXToScreen(min); vert[1].y = ModelYToScreen(-min);
+ vert[2].x = ModelXToScreen(max); vert[2].y = ModelYToScreen(-min);
+ vert[3].x = ModelXToScreen(max); vert[3].y = ModelYToScreen(0.5f);
+ glBindBuffer(GL_ARRAY_BUFFER, Edit_Mode_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Edit_Mode_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- while (*++tmp) {}
- while ((*--tmp != sep) && *tmp) {}
+ // left horizontal part
+ vert[0].x = ModelXToScreen(-0.5f); vert[0].y = ModelYToScreen(-min);
+ vert[1].x = ModelXToScreen(-0.5f); vert[1].y = ModelYToScreen(-max);
+ vert[2].x = ModelXToScreen(min); vert[2].y = ModelYToScreen(-max);
+ vert[3].x = ModelXToScreen(min); vert[3].y = ModelYToScreen(-min);
+ glBindBuffer(GL_ARRAY_BUFFER, Edit_Mode_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Edit_Mode_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- *fileName = tmp + 1;
+ // lower vertical part
+ vert[0].x = ModelXToScreen(min); vert[0].y = ModelYToScreen(-max);
+ vert[1].x = ModelXToScreen(min); vert[1].y = ModelYToScreen(-0.5f);
+ vert[2].x = ModelXToScreen(max); vert[2].y = ModelYToScreen(-0.5f);
+ vert[3].x = ModelXToScreen(max); vert[3].y = ModelYToScreen(-max);
+ glBindBuffer(GL_ARRAY_BUFFER, Edit_Mode_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Edit_Mode_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- u32 intBuff[16];
- PushStringIntoIntArray(intBuff, ArrayCount(intBuff), (u08 *)(*fileName)); // 将字符穿转移到intbuff数组中
+ // right horizontal part
+ vert[0].x = ModelXToScreen(max); vert[0].y = ModelYToScreen(-min);
+ vert[1].x = ModelXToScreen(max); vert[1].y = ModelYToScreen(-max);
+ vert[2].x = ModelXToScreen(0.5f); vert[2].y = ModelYToScreen(-max);
+ vert[3].x = ModelXToScreen(0.5f); vert[3].y = ModelYToScreen(-min);
+ glBindBuffer(GL_ARRAY_BUFFER, Edit_Mode_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Edit_Mode_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- /*
- 这段代码假设文件中的数据是以 4 字节整数的形式存储的,并且依次存储了
- nBytesHeaderComp 和 nBytesHeader 两个值。通常情况下,
- 这种操作用于读取文件中存储的数据头部信息或者其他固定格式的数据。
- */
- u32 nBytesHeaderComp; // 压缩后数据大小
- u32 nBytesHeader; // 解压后数据大小
- fread(&nBytesHeaderComp, 1, 4, file); // 从文件中读取 4 个字节的数据,并将其存储在 nBytesHeaderComp 变量中
- fread(&nBytesHeader, 1, 4, file);
+ // ceter part
+ vert[0].x = ModelXToScreen(min); vert[0].y = ModelYToScreen(-min);
+ vert[1].x = ModelXToScreen(min); vert[1].y = ModelYToScreen(-max);
+ vert[2].x = ModelXToScreen(max); vert[2].y = ModelYToScreen(-max);
+ vert[3].x = ModelXToScreen(max); vert[3].y = ModelYToScreen(-min);
+ glBindBuffer(GL_ARRAY_BUFFER, Edit_Mode_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Edit_Mode_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+ }
- u08 *header = PushArrayP(arena, u08, nBytesHeader); // 从内存池中分配u08 数组,大小为 nBytesHeader
- u08 *compressionBuffer = PushArrayP(arena, u08, nBytesHeaderComp); // 从内存池中分配u08 数组,大小为 nBytesHeaderComp
+ { // draw the text by the selected (pre-select) fragment
+ f32 lh = 0.0f;
+
+ fonsClearState(FontStash_Context);
+ fonsSetSize(FontStash_Context, 18.0f * Screen_Scale.x);
+ fonsSetAlign(FontStash_Context, FONS_ALIGN_LEFT | FONS_ALIGN_TOP);
+ fonsSetFont(FontStash_Context, Font_Normal);
+ fonsVertMetrics(FontStash_Context, 0, 0, &lh);
+ fonsSetColor(FontStash_Context, FourFloatColorToU32(Edit_Mode_Colours->fg));
+
+ f32 textBoxHeight = lh;
+ textBoxHeight *= Edit_Pixels.editing ? 3.0f : 1.0f;
+ textBoxHeight += Edit_Pixels.editing ? 3.0f : 0.0f;
- fread(compressionBuffer, 1, nBytesHeaderComp, file); // nBytesHeaderComp个字节的压缩数据,存储到compressionBuffer
- *headerHash = FastHash64( // head的地址采用fasthash加密,作为存储文件的文件名。 compressionBuffer所指向的值进行hash得到一个名字,作为存储文件的文件名
- compressionBuffer,
- nBytesHeaderComp,
- FastHash64(intBuff, sizeof(intBuff), 0xbafd06832de619c2)
- );
- // fprintf(stdout, "The headerHash is calculated accordig to the compressed head, the hash number is (%llu) and the cache file name is (%s)\n", *headerHash, (u08*) headerHash);
- if (
- libdeflate_deflate_decompress(
- Decompressor, // 指向 解压缩器
- (const void *)compressionBuffer, // 指向 即将解压的数据,(const void *)强制转换为不可修改的内存块
- nBytesHeaderComp, // 解压缩的字节数
- (void *)header, // 指向 解压缩后存储的位置,转换为通用内存块
- nBytesHeader, // 解压后预计大小
- NULL) // 表示不传递其他参数给压缩函数
- )
- {
- return(decompErr); // decompress err
- }
- FreeLastPushP(arena); // comp buffer 释放内存池(arena)中最近一次通过 PushArrayP 宏分配的内存空间
- // 遍历内存池链表,找到最后一个内存池,并释放其最近一次分配的内存空间。防止内存泄漏
+ static char line1[64];
+ static u32 line1Done = 0;
+ char line2[64];
- /*
- header的格式
- ==========================
- nBytes Contents
- --------------------------
- 8 Total_Genome_Length
- 4 Number_of_Original_Contigs
- -------------------
- Number_of_Original_Contigs 个 contigs 的存储规则
- -------------------
- 4 contig fracs
- 64 name
- ------------------
- 1 textureRes
- 1 nTextRes
- 1 mipMapLevels
+ char *midLineNoInv = (char *)"moved to";
+ char *midLineInv = (char *)"inverted and moved to";
+ char *midLine = Global_Edit_Invert_Flag ? midLineInv : midLineNoInv;
- */
+ u32 pix1 = my_Min(Edit_Pixels.pixels.x, Edit_Pixels.pixels.y);
+ u32 pix2 = my_Max(Edit_Pixels.pixels.x, Edit_Pixels.pixels.y);
- u64 val64;
- u08 *ptr = (u08 *)&val64; // 获取val64存储的 八位无符号整型(u08)的指针
- ForLoop(8)
- {
- *ptr++ = *header++; // 指针赋值给到val64的大小 -> 整个基因的长度
- }
- Total_Genome_Length = val64;
+ if (Edit_Pixels.editing && line1Done)
+ {
+ pix1 = pix1 ? pix1 - 1 : (pix2 < (Number_of_Pixels_1D - 1) ? pix2 + 1 : pix2);
+ }
- u32 val32;
- ptr = (u08 *)&val32;
- ForLoop(4)
- {
- *ptr++ = *header++;
- }
- Number_of_Original_Contigs = val32; // 指针赋值给到val32的值 -> contigs的数目
+ original_contig *cont = Original_Contigs + Map_State->get_original_contig_id(pix1);
- // 从内存池中分配存储原始 contig 的数组内存,类型为 original_contig,数组长度为 Number_of_Original_Contigs
- Original_Contigs = PushArrayP(arena, original_contig, Number_of_Original_Contigs);
- // 分配一个存储浮点数的数组
- f32 *contigFracs = PushArrayP(arena, f32, Number_of_Original_Contigs);
- ForLoop(Number_of_Original_Contigs) // 读取 contigs fraction (f32) and name
- {
+ u32 nPixels = Number_of_Pixels_1D;
+ f64 bpPerPixel = (f64)Total_Genome_Length / (f64)nPixels;
- f32 frac;
- u32 name[16];
+ f64 bpStart = bpPerPixel * (f64)Map_State->contigRelCoords[pix1];
+
+ if (Edit_Pixels.editing)
+ {
+ stbsp_snprintf(line2, 64, "%s[%$.2fbp]", cont->name, bpStart);
+ }
+ else if (line1Done)
+ {
+ line1Done = 0;
+ }
+
+ if (!line1Done)
+ {
+ f64 bpEnd = bpPerPixel * (f64)Map_State->contigRelCoords[pix2];
+ original_contig *cont2 = Original_Contigs + Map_State->get_original_contig_id(pix2);
+ stbsp_snprintf(line1, 64, "%s[%$.2fbp] to %s[%$.2fbp]", cont->name, bpStart, cont2->name, bpEnd);
+ if (Edit_Pixels.editing)
+ {
+ line1Done = 1;
+ }
+ }
- // 读取每个contig 对应的一个f32
- ptr = (u08 *)&frac;
- ForLoop2(4) // 从header中读取4个字节的数据存储到frac中
- {
- *ptr++ = *header++;
- }
- contigFracs[index] = frac; // 将这个f32 存储到 contigFracs[index] 中
-
- // 读取contig的名字
- ptr = (u08 *)name;
- ForLoop2(64)
- {
- *ptr++ = *header++;
- }
- // contig name赋值
- ForLoop2(16)
- {
- // ?? 一个contig 的name为什么是一个长度为u32的数组
- Original_Contigs[index].name[index2] = name[index2]; // 将 u32 name[16] 给到每一个contig 的name
- }
-
- (Original_Contigs + index)->contigMapPixels = PushArrayP(arena, u32, Number_of_Pixels_1D); // 为每个contig 的 mapPixels 变量 申请内存
- (Original_Contigs + index)->nContigs = 0;
- }
+ f32 textWidth_1 = fonsTextBounds(FontStash_Context, 0, 0, line1, 0, NULL);
+ f32 textWidth_2 = fonsTextBounds(FontStash_Context, 0, 0, line2, 0, NULL);
+ f32 textWidth_3 = fonsTextBounds(FontStash_Context, 0, 0, midLine, 0, NULL);
+ f32 textWidth = my_Max(textWidth_1, textWidth_2);
+ textWidth = my_Max(textWidth, textWidth_3);
- u08 textureRes = *header++; // 分辨率
- u08 nTextRes = *header++; // 纹理数目
- u08 mipMapLevels = *header; // ??
+ f32 spacing = 3.0f;
- Texture_Resolution = Pow2(textureRes); // 纹理分辨率 当前显示的像素点个数,1024
- Number_of_Textures_1D = Pow2(nTextRes); // 一维纹理数目 可以放大的次数,每一个像素点可以放大32次,
- Number_of_MipMaps = mipMapLevels;
+ glUniform4fv(Flat_Shader->colorLocation, 1, (f32 *)&Edit_Mode_Colours->bg);
- Number_of_Pixels_1D = Number_of_Textures_1D * Texture_Resolution; // 更新一维数据的长度
+ vert[0].x = ModelXToScreen(min) - spacing - textWidth;
+ vert[0].y = ModelYToScreen(-max) + spacing;
+ vert[1].x = ModelXToScreen(min) - spacing - textWidth;
+ vert[1].y = ModelYToScreen(-max) + spacing + textBoxHeight;
+ vert[2].x = ModelXToScreen(min) - spacing;
+ vert[2].y = ModelYToScreen(-max) + spacing + textBoxHeight;
+ vert[3].x = ModelXToScreen(min) - spacing;
+ vert[3].y = ModelYToScreen(-max) + spacing;
- Map_State = PushStructP(arena, map_state); // 从内存池中分配一个包含 map_state 结构的内存块,并返回指向该结构的指针, 存储contigs map到图像中的数据
- Map_State->contigIds = PushArrayP(arena, u32, Number_of_Pixels_1D); // 从内存池中分配存储 contigIds 的数组,数组长度为 Number_of_Pixels_1D
- Map_State->originalContigIds = PushArrayP(arena, u32, Number_of_Pixels_1D); //
- Map_State->contigRelCoords = PushArrayP(arena, u32, Number_of_Pixels_1D); // 像素坐标
- Map_State->scaffIds = PushArrayP(arena, u32, Number_of_Pixels_1D); // scaffID
- Map_State->metaDataFlags = PushArrayP(arena, u64, Number_of_Pixels_1D); // 标记
- memset(Map_State->scaffIds, 0, Number_of_Pixels_1D * sizeof(u32)); // 将scaffID和metaDataFlags初始化为0
- memset(Map_State->metaDataFlags, 0, Number_of_Pixels_1D * sizeof(u64));
- f32 total = 0.0f; // 所有contig的一个浮点数的累积, finally should approximately be 1.0
- u32 lastPixel = 0;
- u32 relCoord = 0;
+ glBindBuffer(GL_ARRAY_BUFFER, Edit_Mode_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Edit_Mode_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
- ForLoop(Number_of_Original_Contigs) // 初始设定每个contig的每个像素点的id和局部坐标
- {
- total += contigFracs[index]; // 当前所有contig对应的浮点数的累积,包括当前contig
- u32 pixel = (u32)((f64)Number_of_Pixels_1D * (f64)total); // 每行像素点数 * 当前占比
-
- relCoord = 0;
-#ifdef RevCoords
- u32 tmp = pixel - lastPixel - 1;
-#endif
- while (lastPixel < pixel)
- {
- Map_State->originalContigIds[lastPixel] = index; // 每一个像素点对应的都是当前contig的编号
- Map_State->contigRelCoords[lastPixel++] = // 每一个像素点对应的在当前contig中的局部坐标
-#ifdef RevCoords
- tmp - relCoord++;
-#else
- relCoord++;
-#endif
- }
- }
- while (lastPixel < Number_of_Pixels_1D) // 处理数值计算导致的lastPixel小于Number_of_Pixels_1D的问题
- {
- Map_State->originalContigIds[lastPixel] = (u32)(Number_of_Original_Contigs - 1); //假设其为最后一个contig的像素点
- Map_State->contigRelCoords[lastPixel++] = relCoord++;
- }
+ glUseProgram(UI_Shader->shaderProgram);
+ fonsDrawText(FontStash_Context, ModelXToScreen(min) - spacing - textWidth, ModelYToScreen(-max) + spacing, line1, 0);
- Contigs = PushStructP(arena, contigs); // 声明一个存储contigs的内存块, 其返回Contigs作为这个块的指针,实际上此处为整个genome的信息
- Contigs->contigs_arr = PushArrayP(arena, contig, Max_Number_of_Contigs); // 每一个Contigs中会有contigs (片段),一共有Max_Number_of_Contigs多个片段,最多存放4096个contigs
- Contigs->contigInvertFlags = PushArrayP(arena, u08, (Max_Number_of_Contigs + 7) >> 3); // (4096 + 7 ) >> 3 = 512, 声明512个u08的存储空间
+ if (Edit_Pixels.editing)
+ {
+ fonsDrawText(FontStash_Context, ModelXToScreen(min) - spacing - textWidth, ModelYToScreen(-max) + spacing + lh + 1.0f, midLine, 0);
+ fonsDrawText(FontStash_Context, ModelXToScreen(min) - spacing - textWidth, ModelYToScreen(-max) + spacing + (2.0f * (lh + 1.0f)), line2, 0);
+ }
- UpdateContigsFromMapState(); // 根据mapstate 跟新当前的contigs, 并且更新original_contigs里面的每个contig所包含的片段的个数和片段的中点
+ if (Edit_Pixels.snap)
+ {
+ char *text = (char *)"Snap Mode On";
+ textWidth = fonsTextBounds(FontStash_Context, 0, 0, text, 0, NULL);
+ glUseProgram(Flat_Shader->shaderProgram);
+ vert[0].x = ModelXToScreen(min) - spacing - textWidth; vert[0].y = ModelYToScreen(-min) + spacing;
+ vert[1].x = ModelXToScreen(min) - spacing - textWidth; vert[1].y = ModelYToScreen(-min) + spacing + lh;
+ vert[2].x = ModelXToScreen(min) - spacing; vert[2].y = ModelYToScreen(-min) + spacing + lh;
+ vert[3].x = ModelXToScreen(min) - spacing; vert[3].y = ModelYToScreen(-min) + spacing;
- u32 nBytesPerText = 0; // 程序将一整张图分成了32*32个小格子,每一个格子被称作texture
- ForLoop(Number_of_MipMaps)
- {
- nBytesPerText += Pow2((2 * textureRes--)); // sum([2**(2*i) for i in range(10, 10-Number_of_MipMaps, -1)])/2
- }
- nBytesPerText >>= 1; // 除以 2 因为数据是经过压缩的
- Bytes_Per_Texture = nBytesPerText; // 一个texture 对应的字节数目
+ glBindBuffer(GL_ARRAY_BUFFER, Edit_Mode_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Edit_Mode_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+
+ glUseProgram(UI_Shader->shaderProgram);
+ fonsDrawText(FontStash_Context, ModelXToScreen(min) - spacing - textWidth, ModelYToScreen(-min) + spacing, text, 0);
+ }
- File_Atlas = PushArrayP(arena, file_atlas_entry, (Number_of_Textures_1D + 1) * (Number_of_Textures_1D >> 1)); // variable to store the data entry
+ { // draw the help text in the bottom right corner
+ fonsSetFont(FontStash_Context, Font_Bold);
+ fonsSetSize(FontStash_Context, text_box_size.font_size * Screen_Scale.x);
+ fonsVertMetrics(FontStash_Context, 0, 0, &lh);
- u32 currLocation = sizeof(Magic) + 8 + nBytesHeaderComp; // current localtion of the pointer = magic_check + (u32 compressed head length) + (u32 decompressed head length) + compressed header length
-
- // locating the pointers to data of entries
- ForLoop((Number_of_Textures_1D + 1) * (Number_of_Textures_1D >> 1)) // loop through total number of the textures
- {
- /*
- 数据结构:
- - magic (4 bytes)
- - 8 bytes
- - headercomp (nBytesHeaderComp bytes)
- - a block of entry:
- - number of bytes in u32
- - data
+ std::vector helpTexts = {
+ (char *)"Edit Mode",
+ (char *)"E: exit, Q: undo, W: redo",
+ (char *)"Left Click: pickup, place",
+ (char *)"S: toggle snap mode",
+ (char *)"Middle Click / Spacebar: pickup whole sequence or (hold Shift): scaffold",
+ (char *)"Middle Click / Spacebar (while editing): invert sequence"
+ };
- */
- file_atlas_entry *entry = File_Atlas + index; // get the temprory pointer of the entry
- u32 nBytes; // define a u32 to save the data
- fread(&nBytes, 1, 4, file); // 读取四个字节, 前四个字节存储一个u32表示大小,后面的数据存储
- fseek(file, nBytes, SEEK_CUR); // 文件指针会向前移动 nBytes 个字节,SEEK_CUR在c标准库中被定义为1, after the loop, pointer file is moved to the end of the reading file
- currLocation += 4; // 每移动一次,currLocation 增加 4
+ textBoxHeight = (f32)helpTexts.size() * (lh + 1.0f) - 1.0f;
+ spacing = 10.0f;
- entry->base = currLocation; // asign the current location to File_Atlas + index
- entry->nBytes = nBytes; // asign the size to File_Atlas + index
+ textWidth = 0.f;
+ for (auto* i :helpTexts){
+ textWidth = my_Max(textWidth, fonsTextBounds(FontStash_Context, 0, 0, i, 0, NULL));
+ }
- currLocation += nBytes;
- }
+ glUseProgram(Flat_Shader->shaderProgram);
- // Extensions
- {
- u08 magicTest[sizeof(Extension_Magic_Bytes[0])]; // define a u08 array, to check the end of the file, use this to read the extensions
+ vert[0].x = width - spacing - textWidth; vert[0].y = height - spacing - textBoxHeight;
+ vert[1].x = width - spacing - textWidth; vert[1].y = height - spacing;
+ vert[2].x = width - spacing; vert[2].y = height - spacing;
+ vert[3].x = width - spacing; vert[3].y = height - spacing - textBoxHeight;
- while ((u64)(currLocation + sizeof(magicTest)) < fileSize)
- {
- u32 bytesRead = (u32)fread(magicTest, 1, sizeof(magicTest), file); // reading 4 bytes from the file
- currLocation += bytesRead;
- if (bytesRead == sizeof(magicTest))
- {
- ForLoop(ArrayCount(Extension_Magic_Bytes))
+ glBindBuffer(GL_ARRAY_BUFFER, Edit_Mode_Data->vbos[ptr]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(vertex), vert);
+ glBindVertexArray(Edit_Mode_Data->vaos[ptr++]);
+ glDrawRangeElements(GL_TRIANGLES, 0, 3, 6, GL_UNSIGNED_SHORT, NULL);
+
+ glUseProgram(UI_Shader->shaderProgram);
+
+ for (int i = 0; i < helpTexts.size(); i++)
{
- u08 foundExtension = 1;
- u08 *magic = (u08 *)Extension_Magic_Bytes[index];
- ForLoop2(sizeof(magicTest))
- {
- if (magic[index2] != magicTest[index2]) // magicTest is from the file, magic is from the definition // if magic this isn't the same, means no extensions found
- {
- foundExtension = 0;
- break;
- }
- }
+ fonsDrawText(
+ FontStash_Context,
+ width - spacing - textWidth,
+ height - spacing - textBoxHeight + (i * (lh + 1.0f)),
+ helpTexts[i],
+ 0);
+ }
+ }
+ }
+ }
- if (foundExtension) // if extension is found
- {
- extension_type type = (extension_type)index; // get the type of the extension
- u32 extensionSize = 0;
- switch (type)
- {
- case extension_graph:
- {
- u32 compSize;
- fread(&compSize, 1, sizeof(u32), file); // get the size of the extension data
- graph *gph = PushStructP(arena, graph); // create the size to store the extension data
- extension_node *node = PushStructP(arena, extension_node);
- u08 *dataPlusName = PushArrayP(arena, u08, ((sizeof(u32) * Number_of_Pixels_1D) + sizeof(gph->name) )); // there are 1024 * 32 u32 numbers. Every single one of them represents the data on a pixel.
-#pragma clang diagnostic push
-#pragma GCC diagnostic ignored "-Wcast-align"
- gph->data = (u32 *)(dataPlusName + sizeof(gph->name)); // the first 16 u32 are the name of the extention, which can include 16*32/8=64 u08 (char).
-#pragma clang diagnostic pop
- extensionSize += (compSize + sizeof(u32));
- u08 *compBuffer = PushArrayP(arena, u08, compSize);
- fread(compBuffer, 1, compSize, file); // read the extension data from the file pointer
- if (libdeflate_deflate_decompress(Decompressor, (const void *)compBuffer, compSize, (void *)dataPlusName, (sizeof(u32) * Number_of_Pixels_1D) + sizeof(gph->name), NULL)) // decompress compBuffer to dataPlusName
- /* code from the libdeflate.h
- enum libdeflate_result {
- // Decompression was successful.
- LIBDEFLATE_SUCCESS = 0,
+ // NK
+ if (UI_On)
+ {
+ glDisable(GL_CULL_FACE);
+ glEnable(GL_SCISSOR_TEST);
- // Decompression failed because the compressed data was invalid,
- * corrupt, or otherwise unsupported.
- LIBDEFLATE_BAD_DATA = 1,
+ glUseProgram(UI_Shader->shaderProgram);
+ glUniformMatrix4fv(UI_Shader->matLocation, 1, GL_FALSE, textNormalMat);
+ glViewport(0, 0, (s32)width, (s32)height);
- // A NULL 'actual_out_nbytes_ret' was provided, but the data would have
- * decompressed to fewer than 'out_nbytes_avail' bytes.
- LIBDEFLATE_SHORT_OUTPUT = 2,
+ {
+ const struct nk_draw_command *cmd;
+ void *vertices, *elements;
+ nk_draw_index *offset = 0;
- // The data would have decompressed to more than 'out_nbytes_avail'
- * bytes.
- LIBDEFLATE_INSUFFICIENT_SPACE = 3,
- };
- */
- { // unsuccessful decompress
- FreeLastPushP(arena); // data
- FreeLastPushP(arena); // graph
- FreeLastPushP(arena); // node
- }
- else
- { // successful decompress
-#pragma clang diagnostic push
-#pragma GCC diagnostic ignored "-Wcast-align"
- u32 *namePtr = (u32 *)dataPlusName; // get a temp pointer,将原来的u08指针切换为u32指针,所指向的位置相同,只是不同的解释方式
-#pragma clang diagnostic pop
- ForLoop2(ArrayCount(gph->name)) // get the graph name
- {
- gph->name[index2] = *(namePtr + index2);
- }
+ glBindVertexArray(NK_Device->vao);
+ glBindBuffer(GL_ARRAY_BUFFER, NK_Device->vbo);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, NK_Device->ebo);
- node->type = type; // assign the gph to node
- node->extension = gph;
- AddExtension(node); // add node to extension
- }
- FreeLastPushP(arena); // compBuffer
- }
- break;
- }
- currLocation += extensionSize;
- }
+#define MAX_VERTEX_MEMORY KiloByte(512)
+#define MAX_ELEMENT_MEMORY KiloByte(128)
+ glBufferData(GL_ARRAY_BUFFER, MAX_VERTEX_MEMORY, NULL, GL_STREAM_DRAW);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_ELEMENT_MEMORY, NULL, GL_STREAM_DRAW);
+
+ vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
+ elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
+
+ {
+ nk_convert_config config;
+ static const nk_draw_vertex_layout_element vertex_layout[] = {
+ {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(nk_glfw_vertex, position)},
+ {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(nk_glfw_vertex, uv)},
+ {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(nk_glfw_vertex, col)},
+ {NK_VERTEX_LAYOUT_END}
+ };
+
+ NK_MEMSET(&config, 0, sizeof(config));
+ config.vertex_layout = vertex_layout;
+ config.vertex_size = sizeof(nk_glfw_vertex);
+ config.vertex_alignment = NK_ALIGNOF(nk_glfw_vertex);
+ config.null = NK_Device->null;
+ config.circle_segment_count = 22;
+ config.curve_segment_count = 22;
+ config.arc_segment_count = 22;
+ config.global_alpha = 1.0f;
+ config.shape_AA = NK_ANTI_ALIASING_ON;
+ config.line_AA = NK_ANTI_ALIASING_ON;
+
+ {
+ nk_buffer vbuf, ebuf;
+ nk_buffer_init_fixed(&vbuf, vertices, MAX_VERTEX_MEMORY);
+ nk_buffer_init_fixed(&ebuf, elements, MAX_ELEMENT_MEMORY);
+ nk_convert(NK_Context, &NK_Device->cmds, &vbuf, &ebuf, &config);
}
}
- else
+ glUnmapBuffer(GL_ARRAY_BUFFER);
+ glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
+
+ nk_draw_foreach(cmd, NK_Context, &NK_Device->cmds)
{
- break;
+ if (!cmd->elem_count) continue;
+ glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id);
+ glScissor(
+ (GLint)(cmd->clip_rect.x),
+ (GLint)(height - cmd->clip_rect.y - cmd->clip_rect.h),
+ (GLint)(cmd->clip_rect.w),
+ (GLint)(cmd->clip_rect.h));
+ glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset);
+ offset += cmd->elem_count;
}
}
+
+ ChangeSize((s32)width, (s32)height);
+ glDisable(GL_SCISSOR_TEST);
+ glEnable(GL_CULL_FACE);
+
+ nk_clear(NK_Context);
}
-
- fclose(file); // the positions and file pointers will be saved to texture_buffer_queue, which can be read in multi-thread mode
- }
- // Load Textures: reading from file and pushing into glTexture with index Contact_Matrix->textures
- {
- InitialiseTextureBufferQueue(arena, Texture_Buffer_Queue, Bytes_Per_Texture, filePath); // 初始化所有的queue texture_buffer_queue, 一共有8个queue,每个queue有8个buffer
+ if (Loading)
+ {
+ u32 colour = glfonsRGBA(Theme_Colour.r, Theme_Colour.g, Theme_Colour.b, Theme_Colour.a);
- u32 nTextures = (Number_of_Textures_1D + 1) * (Number_of_Textures_1D >> 1); // number of textures (528)
- // u32 *packedTextureIndexes = PushArrayP(arena, u32, nTextures); // using a pointer of sequences of u32 as the texture index
- u32* packedTextureIndexes = new u32[nTextures]; // (u32*) malloc(sizeof(u32) * nTextures); // this is released so new is ok
- ThreadPoolAddTask(Thread_Pool, PopulateTextureLoadQueue, packedTextureIndexes); // multi-thread for loading the texture entries
+ fonsClearState(FontStash_Context);
+ fonsSetSize(FontStash_Context, 64.0f * Screen_Scale.x);
+ fonsSetAlign(FontStash_Context, FONS_ALIGN_CENTER | FONS_ALIGN_MIDDLE);
+ fonsSetFont(FontStash_Context, Font_Bold);
+ fonsSetColor(FontStash_Context, colour);
- glActiveTexture(GL_TEXTURE0); // 所有的子图加载在 texture 0
- glGenTextures(1, &Contact_Matrix->textures); // 获取一个texture 存到
- glBindTexture(GL_TEXTURE_2D_ARRAY, Contact_Matrix->textures); // 绑定到当前的texture
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 0);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, (GLint)Number_of_MipMaps - 1);
+ glUseProgram(UI_Shader->shaderProgram);
+ glUniformMatrix4fv(Flat_Shader->matLocation, 1, GL_FALSE, textNormalMat);
+ glViewport(0, 0, (s32)width, (s32)height);
+ fonsDrawText(FontStash_Context, width * 0.5f, height * 0.5f, "Loading...", 0);
- u32 resolution = Texture_Resolution;
- ForLoop(Number_of_MipMaps) // 初始一个texture的一个维度有1024个像素点,放大后一个texture的一个维度只有32(1024 / 2**5)个像素点
- { // 初始化所有层级mipmap level的 gl_texture_2d_array
- glCompressedTexImage3D (
- GL_TEXTURE_2D_ARRAY, // 指定纹理目标 例如GL_TEXTURE_3D
- (GLint)index, // 指定纹理层级
- GL_COMPRESSED_RED_RGTC1, // texture数据的压缩格式 Unsigned normalized 1-component only.
- (GLsizei)resolution, (GLsizei)resolution, (GLsizei)nTextures, // 纹理宽度, 高度, 深度
- 0, // border
- (GLsizei)((resolution >> 1) * resolution * nTextures), // 每一个texture 的数据大小 (bytes),注意此处初始化了全部的 nTextures 个texture
- 0); // 指向数据的指针
- resolution >>= 1;
+ ChangeSize((s32)width, (s32)height);
}
-
- u32 ptr = 0;
- printf("Loading textures...\n");
- ForLoop(Number_of_Textures_1D)
- {
- ForLoop2(Number_of_Textures_1D - index)
- {
- volatile texture_buffer *loadedTexture = 0; // 使用volatile锁放弃存取优化。如果优化(不使用volatile),该值存取会被优化,可能会存放在寄存器中,而不是每次访问该值都会从内存中读取
- while (!loadedTexture)
- {
- #ifndef _WIN32 // unix
- __atomic_load(&Current_Loaded_Texture, &loadedTexture, __ATOMIC_SEQ_CST);
- #else // windows
- // loadedTexture = InterlockedCompareExchangePointer(&Current_Loaded_Texture, nullptr, nullptr);
- loadedTexture = (texture_buffer*)InterlockedCompareExchangePointer(
- (PVOID volatile*)&Current_Loaded_Texture,
- NULL,
- NULL);
- #endif // __WIN32
- }
- u08 *texture = loadedTexture->texture; // 获取loadedtexture的texture的指针
-
- // push the texture data (number_of_mipmaps) to the gl_texture_2d_array
- resolution = Texture_Resolution;
- for ( GLint level = 0;
- level < (GLint)Number_of_MipMaps;
- ++level )
- {
- GLsizei nBytes = (GLsizei)(resolution * (resolution >> 1)); // 为什么每一个mipmap存储的像素点个数是 resolution ** 2 / 2 ,不应该是resolution**2吗
- // 此处将texture的数据压入到gl中,存储为gl_texture_2d_array的对象
- glCompressedTexSubImage3D(
- GL_TEXTURE_2D_ARRAY, // target texture. Must be GL_TEXTURE_3D or GL_TEXTURE_2D_ARRAY.
- level, // level-of-detail number. Level 0 is the base image level. Level n is the nth mipmap reduction image.
- 0, 0, (GLint)Texture_Ptr, // Texture_Ptr is the index of Current_loaded_texture
- (GLsizei)resolution, (GLsizei)resolution, 1, // Specifies the width, height, depth of the texture subimage.
- GL_COMPRESSED_RED_RGTC1, // 压缩数据的格式,这就是为什么只用了一半的 (nBytes) bytes 的数据表示了 resolution * resolution 的图片
- nBytes, // the number of unsigned bytes of image data starting at the address specified by data.
- texture // a pointer to the compressed image data in memory.
- ); // 是否此处将texture给到 GL_TEXTURE_2D_ARRAY, check the doc on https://registry.khronos.org/OpenGL-Refpages/es3.0/html/glCompressedTexSubImage3D.xhtml
-
- resolution >>= 1;
- texture += nBytes;
- }
- printf("\r%3d/%3d (%1.2f%%) textures loaded from disk...", Texture_Ptr + 1, nTextures, 100.0 * (f64)((f32)(Texture_Ptr + 1) / (f32)((Number_of_Textures_1D >> 1) * (Number_of_Textures_1D + 1)))); // echo out 读取到了第Texture_Ptr个texture
- fflush(stdout);
- AddTextureBufferToQueue(Texture_Buffer_Queue, (texture_buffer *)loadedTexture); // texture_buffer_queue 是全部的读取任务队列,读取后的buffer重新添加到队列中,供下一次读取。解决了从队列中弹出任务后任务队列空了的疑问。读取文件的任务队列在别的地方还会被调用吗?
- FenceIn(Current_Loaded_Texture = 0); // 将临时变量置空,重新读取到current_loaded_texture后会跳出上面的循环
- __atomic_fetch_add(&Texture_Ptr, 1, 0); // 更新全局的 texture_ptr
- ptr ++ ;
- }
- }
-
- printf("\n");
- CloseTextureBufferQueueFiles(Texture_Buffer_Queue); // 关闭所有的buffer_texture中的文件流指针file,并且释放解压器内存
- delete[] packedTextureIndexes; // packedTextureIndexes 返回
- glBindTexture(GL_TEXTURE_2D_ARRAY, 0); // 给之前已经压入的GL_TEXTURE_2D_ARRAY解除绑定
- }
-
-
- { // Define Contact Matrix Vertex Data (vao, vbo)
- glUseProgram(Contact_Matrix->shaderProgram);
-
- // Contact_Matrix->vaos = PushArrayP(arena, GLuint, Number_of_Textures_1D * Number_of_Textures_1D); //
- // Contact_Matrix->vbos = PushArrayP(arena, GLuint, Number_of_Textures_1D * Number_of_Textures_1D); //
- Contact_Matrix->vaos = new GLuint[ Number_of_Textures_1D * Number_of_Textures_1D]; // (GLuint*) malloc(sizeof(GLuint) * Number_of_Textures_1D * Number_of_Textures_1D ); // TODO make sure the memory is freed before the re-allocation
- Contact_Matrix->vbos = new GLuint[ Number_of_Textures_1D * Number_of_Textures_1D]; // (GLuint*) malloc(sizeof(GLuint) * Number_of_Textures_1D * Number_of_Textures_1D );
-
- setContactMatrixVertexArray(Contact_Matrix, false, false); // set the vertex data of the contact matrix
-
- }
+ if (auto_sort_state)
+ {
+ u32 colour = glfonsRGBA(Theme_Colour.r, Theme_Colour.g, Theme_Colour.b, Theme_Colour.a);
- // Texture Pixel Lookups texture像素查找
- {
- GLuint pixStart, pixStartTex, pixRearrage, pixRearrageTex;
-
- u32 nTex = (Number_of_Textures_1D + 1) * (Number_of_Textures_1D >> 1); // (32 + 1) * 32 / 2 = 528
- u32 nPix1D = Number_of_Textures_1D * Texture_Resolution; // 32 * 1024
+ fonsClearState(FontStash_Context);
+ fonsSetSize(FontStash_Context, 64.0f * Screen_Scale.x);
+ fonsSetAlign(FontStash_Context, FONS_ALIGN_CENTER | FONS_ALIGN_MIDDLE);
+ fonsSetFont(FontStash_Context, Font_Bold);
+ fonsSetColor(FontStash_Context, colour);
- glActiveTexture(GL_TEXTURE2); // 调用 glActiveTexture 函数,可以选择当前活动的纹理单元,并且后续的纹理操作都会影响到该纹理单元
+ glUseProgram(UI_Shader->shaderProgram);
+ glUniformMatrix4fv(Flat_Shader->matLocation, 1, GL_FALSE, textNormalMat);
+ glViewport(0, 0, (s32)width, (s32)height);
+ fonsDrawText(FontStash_Context, width * 0.5f, height * 0.5f, "Pixel Sorting...", 0);
- u32 *pixStartLookup = PushArrayP(arena, u32, 2 * nTex); // 申请空间 2 * 528 个 u32
- u32 ptr = 0;
- for (u32 i = 0; i < Number_of_Textures_1D; i ++ ) // 遍历每一个texture
- {
- for (u32 j = i ; j < Number_of_Textures_1D; j ++ )
- {
- pixStartLookup[ptr++] = (u32)(j * Texture_Resolution); // 列 * 1024 双数索引是列,单数是行
- pixStartLookup[ptr++] = (u32)(i * Texture_Resolution); // 行 * 1024
- }
+ ChangeSize((s32)width, (s32)height);
}
- glGenBuffers(1, &pixStart); // 生成一个缓冲区对象,并将其标识符存储到 pixStart 变量中。这样,pixStart 变量就可以用于引用这个生成的缓冲区对象
- glBindBuffer(GL_TEXTURE_BUFFER, pixStart); // 缓冲区对象 pixStart 就会被绑定到当前的纹理缓冲区上,后续的操作会影响这个缓冲区对象
- glBufferData(GL_TEXTURE_BUFFER, sizeof(u32) * 2 * nTex, pixStartLookup, GL_STATIC_DRAW); // 将数据从 pixStartLookup 指向的内存区域拷贝到绑定到 GL_TEXTURE_BUFFER 目标的缓冲区对象中,大小为 sizeof(u32) * 2 * nTex 字节,并且告诉 OpenGL 这些数据是静态的,不会频繁地变化
+ if (auto_cut_state)
+ {
+ u32 colour = glfonsRGBA(Theme_Colour.r, Theme_Colour.g, Theme_Colour.b, Theme_Colour.a);
- glGenTextures(1, &pixStartTex); // 生成一个纹理对象,并将其标识符存储到 pixStartTex 变量中
- glBindTexture(GL_TEXTURE_BUFFER, pixStartTex); // 纹理对象 pixStartTex 就会被绑定到当前的纹理缓冲区上,后续的纹理操作(比如使用 glTexBuffer 函数将其与纹理缓冲区对象关联)将会影响到这个纹理对象
- glTexBuffer( // 纹理缓冲区对象与缓冲区对象关联的函数
- GL_TEXTURE_BUFFER, // 要关联到缓冲区的纹理目标,这里是 GL_TEXTURE_BUFFER,表示纹理缓冲区。
- GL_RG32UI, // 纹理缓冲区数据的格式, GL_RG32UI表示每个像素由两个u32组成,一个红色分量和一个绿色分量
- pixStart); // 缓冲区对象的标识符,这个缓冲区会与纹理缓冲区关联
+ fonsClearState(FontStash_Context);
+ fonsSetSize(FontStash_Context, 64.0f * Screen_Scale.x);
+ fonsSetAlign(FontStash_Context, FONS_ALIGN_CENTER | FONS_ALIGN_MIDDLE);
+ fonsSetFont(FontStash_Context, Font_Bold);
+ fonsSetColor(FontStash_Context, colour);
- Contact_Matrix->pixelStartLookupBuffer = pixStart; // 缓冲区对象标识符
- Contact_Matrix->pixelStartLookupBufferTex = pixStartTex; // 纹理对象标识符
+ glUseProgram(UI_Shader->shaderProgram);
+ glUniformMatrix4fv(Flat_Shader->matLocation, 1, GL_FALSE, textNormalMat);
+ glViewport(0, 0, (s32)width, (s32)height);
+ fonsDrawText(FontStash_Context, width * 0.5f, height * 0.5f, "Pixel cut...", 0);
- FreeLastPushP(arena); // pixStartLookup 释放存放像素点开始的空间
+ ChangeSize((s32)width, (s32)height);
+ }
+ }
+}
- glActiveTexture(GL_TEXTURE3); // 激活第三个texture,以下代码会影响第三个texture
- u32 *pixRearrageLookup = PushArrayP(arena, u32, nPix1D); // allocte 1024 * 32 u32 memory
- for (u32 i = 0 ; i < nPix1D; i ++ )
- {
- pixRearrageLookup[i] = (u32)i; // assign the index to the pixRearrageLookup
- }
+global_variable
+file_atlas_entry *
+File_Atlas;
- glGenBuffers(1, &pixRearrage); // generate a buffer object
- glBindBuffer(GL_TEXTURE_BUFFER, pixRearrage); // bind as a texture buffer for the current buffer
- glBufferData(GL_TEXTURE_BUFFER, sizeof(u32) * nPix1D, pixRearrageLookup, GL_DYNAMIC_DRAW); // copy the data from pixRearrageLookup to the buffer object, and tell OpenGL that the data is dynamic and will change frequently
+global_function
+void
+LoadTexture(void *in)
+{ //
+ GLuint *textureHandle = (GLuint *)in;
- glGenTextures(1, &pixRearrageTex);
- glBindTexture(GL_TEXTURE_BUFFER, pixRearrageTex);
- glTexBuffer(GL_TEXTURE_BUFFER, GL_R32UI, pixRearrage);
+ texture_buffer *buffer = TakeTextureBufferFromQueue_Wait(Texture_Buffer_Queue); // take a buffer from the queue
+ // assign the texture handle to the buffer
+ buffer->x = (u16)(*textureHandle >> 16); // the former 16 bits represent the row number
+ buffer->y = (u16)(*textureHandle & ((1 << 16) - 1)); // the lower 16 bits represnet the column number
- Contact_Matrix->pixelRearrangmentLookupBuffer = pixRearrage; // 32 * 1024 u32, this is a ascending order of 0 to 1024 * 32
- Contact_Matrix->pixelRearrangmentLookupBufferTex = pixRearrageTex; // texture 的索引
+ /*
+ rule for linear ordering
+ Ordering of the texture boxes
+ ========================
+ 00 01 02 03 04 ... 30 31
+ // 32 33 34 35 ... 61 62
+ // // 63 64 65 ... 91 92
+ // // // ...
+ ========================
+ */
+ // u32 linearIndex = (buffer->x * (Number_of_Textures_1D - 1)) - ((buffer->x * (buffer->x-1)) >> 1) + buffer->y; // get the index accoding to index in x and y diretion
+ u32 linearIndex = texture_id_cal((u32)buffer->x, (u32)buffer->y, (u32)Number_of_Textures_1D);
- FreeLastPushP(arena); // free pixRearrageLookup as it has already been copied to the buffer object with index pixRearrage
+ file_atlas_entry *entry = File_Atlas + linearIndex; // set a tempory pointer
+ u32 nBytes = entry->nBytes; // base is the beginning, nBytes is the size
+ fseek(buffer->file, entry->base, SEEK_SET); // move from the begining to the start of this texture numbered as linearIndex
- glUniform1ui(glGetUniformLocation(Contact_Matrix->shaderProgram, "pixpertex"), Texture_Resolution); // 将1024传递给 pixpertex,每个texture有多少个像素点
- glUniform1f(glGetUniformLocation(Contact_Matrix->shaderProgram, "oopixpertex"), 1.0f / (f32)Texture_Resolution); // 将 1 / 1024 传递给 oopixpertex
- glUniform1ui(glGetUniformLocation(Contact_Matrix->shaderProgram, "ntex1dm1"), Number_of_Textures_1D - 1); // 将31传递给 ntex1dm1
+ fread(buffer->compressionBuffer, 1, nBytes, buffer->file); // read texture to the buffer
- glActiveTexture(GL_TEXTURE0); // 关闭激活的texture 3
+ if (
+ libdeflate_deflate_decompress(
+ buffer->decompressor, // compresser object
+ (const void *)buffer->compressionBuffer, // buffer data before decompressing
+ nBytes, // size before decompressing
+ (void *)buffer->texture, // place to store the data after decompressing
+ Bytes_Per_Texture, // size after decompressing
+ NULL)
+ )
+ { // 解压压缩的texture到 buffer->texture
+ fprintf(stderr, "Could not decompress texture from disk\n");
}
- GLuint posAttribFlatShader = (GLuint)glGetAttribLocation(Flat_Shader->shaderProgram, "position");
- u32 pad = 0;
- auto PushGenericBuffer = [posAttribFlatShader, pad, arena] (quad_data **quadData, u32 numberOfBuffers)
+ while (true)
{
- (void)pad;
+ FenceIn(u32 texture_index_tmp = static_cast(Texture_Ptr));
+ if (linearIndex == texture_index_tmp) break;
+ }
- *quadData = PushStructP(arena, quad_data);
+ FenceIn(Current_Loaded_Texture = buffer); // assign buffer to current_loaded_texture
+
+}
- (*quadData)->vaos = PushArrayP(arena, GLuint, numberOfBuffers);
- (*quadData)->vbos = PushArrayP(arena, GLuint, numberOfBuffers);
- (*quadData)->nBuffers = numberOfBuffers;
+global_function
+void
+PopulateTextureLoadQueue(void *in) // 填充已经初始化过的 所有的queue,填充的任务为所有的528个texture的读取任务
+{
+ u32 *packedTextureIndexes = (u32 *)in; // 将空指针转化为u32
+ u32 ptr = 0;
+ ForLoop(Number_of_Textures_1D) // row number
+ {
+ for (u32 index2 = index; index2 < Number_of_Textures_1D; index2++ ) // column number
+ {
+ packedTextureIndexes[ptr] = (index << 16) | (index2); // first 16 bits is the raw number and the second 16 bits is the column number, there will be problem if number of texture in one dimension is larger than 2^16, but it is not possible ... just for a reminder
+ ThreadPoolAddTask(Thread_Pool, LoadTexture, (void *)(packedTextureIndexes + ptr++)); // 填充当前的任务队列,输入为对应的texture的行、列编号
+ }
+ }
+}
- glUseProgram(Flat_Shader->shaderProgram);
- ForLoop(numberOfBuffers)
- {
- glGenVertexArrays(1, (*quadData)->vaos + index);
- glBindVertexArray((*quadData)->vaos[index]);
+/*
+adjust the gamma thus adjust the contrast
+*/
+global_function
+void
+AdjustColorMap(s32 dir)
+{
+ f32 unit = 0.05f;
+ f32 delta = unit * (dir > 0 ? 1.0f : -1.0f);
- glGenBuffers(1, (*quadData)->vbos + index);
- glBindBuffer(GL_ARRAY_BUFFER, (*quadData)->vbos[index]);
- glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(vertex), NULL, GL_DYNAMIC_DRAW);
+ Color_Maps->controlPoints[1] = my_Max(
+ my_Min(Color_Maps->controlPoints[1] + delta, Color_Maps->controlPoints[2]),
+ Color_Maps->controlPoints[0]
+ );
- glEnableVertexAttribArray(posAttribFlatShader);
- glVertexAttribPointer(posAttribFlatShader, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), 0);
+ glUseProgram(Contact_Matrix->shaderProgram);
+ glUniform3fv( Color_Maps->cpLocation, 1, Color_Maps->controlPoints);
+}
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Quad_EBO);
- }
- };
- // Grid Data
+/*
+change to the last or next color map
+*/
+global_function
+void
+NextColorMap(s32 dir)
+{
+ glActiveTexture(GL_TEXTURE1);
+
+ if (useCustomOrder)
{
- PushGenericBuffer(&Grid_Data, 2 * (Max_Number_of_Contigs + 1));
- }
+ // Find the current index in the custom order
+ u32 currentIndex = 0;
+ for (u32 i = 0; i < userColourMapOrder.nMaps; i++)
+ {
+ if (userColourMapOrder.order[i] == Color_Maps->currMap)
+ {
+ currentIndex = i;
+ break;
+ }
+ }
- // Label Box Data
- {
- PushGenericBuffer(&Label_Box_Data, 2 * Max_Number_of_Contigs);
- }
+ // Calculate the next index in the custom order
+ u32 nextIndex = dir > 0 ? (currentIndex == (userColourMapOrder.nMaps - 1) ? 0 : currentIndex + 1) : (currentIndex == 0 ? userColourMapOrder.nMaps - 1 : currentIndex - 1);
- //Scale Bar Data
- {
- PushGenericBuffer(&Scale_Bar_Data, 4 * (2 + MaxTicksPerScaleBar));
+ Color_Maps->currMap = userColourMapOrder.order[nextIndex];
}
-
- //Contig Colour Bars
+ else
{
- PushGenericBuffer(&Contig_ColourBar_Data, Max_Number_of_Contigs);
+ Color_Maps->currMap = dir > 0 ? (Color_Maps->currMap == (Color_Maps->nMaps - 1) ? 0 : Color_Maps->currMap + 1) : (Color_Maps->currMap == 0 ? Color_Maps->nMaps - 1 : Color_Maps->currMap - 1);
}
+
+ glBindTexture(GL_TEXTURE_BUFFER, Color_Maps->maps[Color_Maps->currMap]);
+
+ glActiveTexture(GL_TEXTURE0);
+}
- //Scaff Bars
- {
- PushGenericBuffer(&Scaff_Bar_Data, Max_Number_of_Contigs);
- }
- // Extensions
+global_function
+u32
+GetOrderedColorMapIndex(u32 displayIndex)
+{
+ if (displayIndex < userColourMapOrder.nMaps)
{
- push_extensions_to_opengl(arena, 0);
+ return userColourMapOrder.order[displayIndex];
}
+ return displayIndex;
+}
-#ifdef Internal
- {
- PushGenericBuffer(&Texture_Tile_Grid, 2 * (Number_of_Textures_1D + 1));
- PushGenericBuffer(&QuadTree_Data, 1 << (2 * (Waypoints_Quadtree_Levels + 1)));
- }
-#endif
-
- // Map Editor
+
+global_function void
+InitializeColorMapOrder()
+{
+ userColourMapOrder.nMaps = Color_Maps->nMaps;
+ for (u32 i = 0; i < userColourMapOrder.nMaps; i++)
{
- Map_Editor = PushStructP(arena, map_editor);
- Map_Editor->nEdits = 0;
- Map_Editor->editStackPtr = 0;
- Map_Editor->nUndone = 0;
- Map_Editor->edits = PushArrayP(arena, map_edit, Edits_Stack_Size);
+ userColourMapOrder.order[i] = i;
}
+}
- // Waypoint Editor
- {
- Waypoint_Editor = PushStructP(arena, waypoint_editor);
- Waypoint_Editor->nWaypointsActive = 0;
- Waypoint_Editor->freeWaypoints = {};
- Waypoint_Editor->activeWaypoints = {};
- Waypoint_Editor->freeWaypoints.next = PushArrayP(arena, waypoint, Waypoints_Stack_Size);
- Waypoint_Editor->quadtree = PushQuadTree(arena);
- Waypoint_Editor->freeNodes = {};
- Waypoint_Editor->freeNodes.next = PushArrayP(arena, waypoint_quadtree_node, Waypoints_Stack_Size);
+global_variable
+GLuint
+Quad_EBO;
- Waypoint_Editor->freeWaypoints.next->prev = &Waypoint_Editor->freeWaypoints;
- Waypoint_Editor->freeNodes.next->prev = &Waypoint_Editor->freeNodes;
- ForLoop(Waypoints_Stack_Size - 1)
- {
- waypoint *wayp = Waypoint_Editor->freeWaypoints.next + index;
- wayp->next = (wayp + 1);
- (wayp + 1)->prev = wayp;
- (wayp + 1)->next = 0;
+enum
+load_file_result
+{
+ ok,
+ fileErr,
+ decompErr,
+};
- waypoint_quadtree_node *node = Waypoint_Editor->freeNodes.next + index;
- node->next = (node + 1);
- (node + 1)->prev = node;
- (node + 1)->next = 0;
- }
- }
+global_variable
+libdeflate_decompressor *
+Decompressor;
- // 为添加的功能初始化指针
- {
- // 给pixel_density_extension分配内存
- // pixel_density_extension = new Extension_Graph_Data(Number_of_Pixels_1D);
-
- // 为 copy textures to cpu 分配内存
- if (textures_array_ptr) delete textures_array_ptr;
- textures_array_ptr = new TexturesArray4AI(
- Number_of_Textures_1D,
- Texture_Resolution,
- *fileName,
- Contigs
- );
- // prepare before reading textures
- f32 original_color_control_points[3];
- prepare_before_copy(original_color_control_points);
- textures_array_ptr->copy_buffer_to_textures(
- Contact_Matrix,
- false
- );
- restore_settings_after_copy(original_color_control_points);
+global_variable
+libdeflate_compressor *
+Compressor;
- // 为 Pixel Cut 存储的数据分配空间,初始化,并且将数据push到extension中
- if (frag_cut_cal_ptr) delete frag_cut_cal_ptr;
- frag_cut_cal_ptr = new FragCutCal(
- textures_array_ptr,
- Number_of_Pixels_1D,
- auto_curation_state.auto_cut_diag_window_for_pixel_mean);
+global_variable
+u08 Magic[] = {'p', 's', 't', 'm'};
- // clear mem for textures
- textures_array_ptr->clear_textures();
-
- // 添加数据到extensions
- std::string graph_name = "pixel_discontinuity";
- bool is_pix_density_added = Extensions.is_graph_name_exist(graph_name);
- if (!is_pix_density_added) // 未添加pixel density
+global_function
+FILE *
+TestFile(const char *fileName, u64 *fileSize = 0)
+{
+ FILE *file=0;
+ {
+ file = fopen(fileName, "rb");
+ if (!file)
{
- u32 added_num = Extensions.get_num_extensions();
- u32* graph_data = new u32[Number_of_Pixels_1D];
- f32 max_desity = 0.f;
- for (auto& i : frag_cut_cal_ptr->hic_pixel_density_origin) max_desity = std::max(max_desity, i);
- for (u32 i=0; i < Number_of_Pixels_1D; i ++)
- {
- graph_data[i] = (u32)(255 * (1.001f- frag_cut_cal_ptr->hic_pixel_density_origin[i] / max_desity));
- }
- add_graph_to_extensions(arena, (u32*)graph_name.c_str(), graph_data);
- delete[] graph_data;
-
- push_extensions_to_opengl(arena, added_num, 0.05f); // push hic_pixel_density to opengl buffer
+#ifdef DEBUG
+ fprintf(stderr, "The file is not available: \'%s\' [errno %d] \n", fileName, errno);
+ exit(errno);
+#endif
}
- else
+ else
{
- fmt::print("hic_pixel_density extension already exists\n");
- assert(false);
+ if (fileSize)
+ {
+ fseek(file, 0, SEEK_END);
+ *fileSize = (u64)ftell(file);
+ fseek(file, 0, SEEK_SET);
+ }
+
+ u08 magicTest[sizeof(Magic)];
+
+ u32 bytesRead = (u32)fread(magicTest, 1, sizeof(magicTest), file);
+ if (bytesRead == sizeof(magicTest))
+ {
+ ForLoop(sizeof(Magic)) // #define ForLoop(n) for (u32 index=0; indexname) ));
+ gph->data = (u32 *)(dataPlusName + sizeof(gph->name));
+ u32 *namePtr = (u32 *)graph_name;
+ for (u32 i = 0; i < ArrayCount(gph->name); i++ ) // get the graph name
+ {
+ gph->name[i] = *(namePtr + i);
+ }
+ for (u32 i = 0; i < Number_of_Pixels_1D; i++) // get the graph data
+ {
+ gph->data[i] = *(graph_data + i);
+ }
+ node->type = extension_graph; // assign the gph to node
+ node->extension = gph;
+ AddExtension(node); // add node to extension
+
+ return ;
}
-global_variable
-memory_arena *
-Loading_Arena;
+
global_function
-void
-SetTheme(struct nk_context *ctx, enum theme theme)
-{
- struct nk_color table[NK_COLOR_COUNT];
- u32 themeSet = 1;
+void
+push_extensions_to_opengl(memory_arena *arena, u32 added_index = 0, f32 scale=-1.f)
+{
+ u32 exIndex = 0;
+ // TraverseLinkedList(Extensions.head, extension_node)
- switch (theme)
+ extension_node* node = Extensions.head ;
+ while (added_index--)
{
- case THEME_WHITE:
- {
- table[NK_COLOR_TEXT] = nk_rgba(70, 70, 70, 255);
- table[NK_COLOR_WINDOW] = nk_rgba(175, 175, 175, 255);
- table[NK_COLOR_HEADER] = nk_rgba(175, 175, 175, 255);
- table[NK_COLOR_BORDER] = nk_rgba(0, 0, 0, 255);
- table[NK_COLOR_BUTTON] = nk_rgba(185, 185, 185, 255);
- table[NK_COLOR_BUTTON_HOVER] = nk_rgba(170, 170, 170, 255);
- table[NK_COLOR_BUTTON_ACTIVE] = nk_rgba(160, 160, 160, 255);
- table[NK_COLOR_TOGGLE] = nk_rgba(150, 150, 150, 255);
- table[NK_COLOR_TOGGLE_HOVER] = nk_rgba(120, 120, 120, 255);
- table[NK_COLOR_TOGGLE_CURSOR] = nk_rgba(175, 175, 175, 255);
- table[NK_COLOR_SELECT] = nk_rgba(190, 190, 190, 255);
- table[NK_COLOR_SELECT_ACTIVE] = nk_rgba(175, 175, 175, 255);
- table[NK_COLOR_SLIDER] = nk_rgba(190, 190, 190, 255);
- table[NK_COLOR_SLIDER_CURSOR] = nk_rgba(80, 80, 80, 255);
- table[NK_COLOR_SLIDER_CURSOR_HOVER] = nk_rgba(70, 70, 70, 255);
- table[NK_COLOR_SLIDER_CURSOR_ACTIVE] = nk_rgba(60, 60, 60, 255);
- table[NK_COLOR_PROPERTY] = nk_rgba(175, 175, 175, 255);
- table[NK_COLOR_EDIT] = nk_rgba(150, 150, 150, 255);
- table[NK_COLOR_EDIT_CURSOR] = nk_rgba(0, 0, 0, 255);
- table[NK_COLOR_COMBO] = nk_rgba(175, 175, 175, 255);
- table[NK_COLOR_CHART] = nk_rgba(160, 160, 160, 255);
- table[NK_COLOR_CHART_COLOR] = nk_rgba(45, 45, 45, 255);
- table[NK_COLOR_CHART_COLOR_HIGHLIGHT] = nk_rgba( 255, 0, 0, 255);
- table[NK_COLOR_SCROLLBAR] = nk_rgba(180, 180, 180, 255);
- table[NK_COLOR_SCROLLBAR_CURSOR] = nk_rgba(140, 140, 140, 255);
- table[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = nk_rgba(150, 150, 150, 255);
- table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = nk_rgba(160, 160, 160, 255);
- table[NK_COLOR_TAB_HEADER] = nk_rgba(180, 180, 180, 255);
- }
- break;
+ node = node->next; // 移动到最后一个节点
+ exIndex ++ ;
+ }
+ for ( ; node; node = node->next) {
+
+ switch (node->type)
+ {
+ case extension_graph:
+ {
+ graph *gph = (graph *)node->extension; // get the graph ptr and assigned to gph
+#define DefaultGraphScale 0.2f
+#define DefaultGraphBase 32.0f
+#define DefaultGraphLineSize 1.0f
+#define DefaultGraphColour {0.1f, 0.8f, 0.7f, 1.0f}
+ gph->scale = scale>0.f? scale : DefaultGraphScale;
+ gph->base = DefaultGraphBase;
+ gph->lineSize = DefaultGraphLineSize;
+ gph->colour = DefaultGraphColour;
+ gph->on = 0;
- case THEME_RED:
- {
- table[NK_COLOR_TEXT] = nk_rgba(190, 190, 190, 255);
- table[NK_COLOR_WINDOW] = nk_rgba(30, 33, 40, 215);
- table[NK_COLOR_HEADER] = nk_rgba(181, 45, 69, 220);
- table[NK_COLOR_BORDER] = nk_rgba(51, 55, 67, 255);
- table[NK_COLOR_BUTTON] = nk_rgba(181, 45, 69, 255);
- table[NK_COLOR_BUTTON_HOVER] = nk_rgba(190, 50, 70, 255);
- table[NK_COLOR_BUTTON_ACTIVE] = nk_rgba(195, 55, 75, 255);
- table[NK_COLOR_TOGGLE] = nk_rgba(51, 55, 67, 255);
- table[NK_COLOR_TOGGLE_HOVER] = nk_rgba(45, 60, 60, 255);
- table[NK_COLOR_TOGGLE_CURSOR] = nk_rgba(181, 45, 69, 255);
- table[NK_COLOR_SELECT] = nk_rgba(51, 55, 67, 255);
- table[NK_COLOR_SELECT_ACTIVE] = nk_rgba(181, 45, 69, 255);
- table[NK_COLOR_SLIDER] = nk_rgba(51, 55, 67, 255);
- table[NK_COLOR_SLIDER_CURSOR] = nk_rgba(181, 45, 69, 255);
- table[NK_COLOR_SLIDER_CURSOR_HOVER] = nk_rgba(186, 50, 74, 255);
- table[NK_COLOR_SLIDER_CURSOR_ACTIVE] = nk_rgba(191, 55, 79, 255);
- table[NK_COLOR_PROPERTY] = nk_rgba(51, 55, 67, 255);
- table[NK_COLOR_EDIT] = nk_rgba(51, 55, 67, 225);
- table[NK_COLOR_EDIT_CURSOR] = nk_rgba(190, 190, 190, 255);
- table[NK_COLOR_COMBO] = nk_rgba(51, 55, 67, 255);
- table[NK_COLOR_CHART] = nk_rgba(51, 55, 67, 255);
- table[NK_COLOR_CHART_COLOR] = nk_rgba(170, 40, 60, 255);
- table[NK_COLOR_CHART_COLOR_HIGHLIGHT] = nk_rgba( 255, 0, 0, 255);
- table[NK_COLOR_SCROLLBAR] = nk_rgba(30, 33, 40, 255);
- table[NK_COLOR_SCROLLBAR_CURSOR] = nk_rgba(64, 84, 95, 255);
- table[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = nk_rgba(70, 90, 100, 255);
- table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = nk_rgba(75, 95, 105, 255);
- table[NK_COLOR_TAB_HEADER] = nk_rgba(181, 45, 69, 220);
- }
- break;
+ gph->shader = PushStructP(arena, editable_plot_shader);
+ gph->shader->shaderProgram = CreateShader(FragmentSource_EditablePlot.c_str(), VertexSource_EditablePlot.c_str(), GeometrySource_EditablePlot.c_str());
- case THEME_BLUE:
- {
- table[NK_COLOR_TEXT] = nk_rgba(20, 20, 20, 255);
- table[NK_COLOR_WINDOW] = nk_rgba(202, 212, 214, 215);
- table[NK_COLOR_HEADER] = nk_rgba(137, 182, 224, 220);
- table[NK_COLOR_BORDER] = nk_rgba(140, 159, 173, 255);
- table[NK_COLOR_BUTTON] = nk_rgba(137, 182, 224, 255);
- table[NK_COLOR_BUTTON_HOVER] = nk_rgba(142, 187, 229, 255);
- table[NK_COLOR_BUTTON_ACTIVE] = nk_rgba(147, 192, 234, 255);
- table[NK_COLOR_TOGGLE] = nk_rgba(177, 210, 210, 255);
- table[NK_COLOR_TOGGLE_HOVER] = nk_rgba(182, 215, 215, 255);
- table[NK_COLOR_TOGGLE_CURSOR] = nk_rgba(137, 182, 224, 255);
- table[NK_COLOR_SELECT] = nk_rgba(177, 210, 210, 255);
- table[NK_COLOR_SELECT_ACTIVE] = nk_rgba(137, 182, 224, 255);
- table[NK_COLOR_SLIDER] = nk_rgba(177, 210, 210, 255);
- table[NK_COLOR_SLIDER_CURSOR] = nk_rgba(137, 182, 224, 245);
- table[NK_COLOR_SLIDER_CURSOR_HOVER] = nk_rgba(142, 188, 229, 255);
- table[NK_COLOR_SLIDER_CURSOR_ACTIVE] = nk_rgba(147, 193, 234, 255);
- table[NK_COLOR_PROPERTY] = nk_rgba(210, 210, 210, 255);
- table[NK_COLOR_EDIT] = nk_rgba(210, 210, 210, 225);
- table[NK_COLOR_EDIT_CURSOR] = nk_rgba(20, 20, 20, 255);
- table[NK_COLOR_COMBO] = nk_rgba(210, 210, 210, 255);
- table[NK_COLOR_CHART] = nk_rgba(210, 210, 210, 255);
- table[NK_COLOR_CHART_COLOR] = nk_rgba(137, 182, 224, 255);
- table[NK_COLOR_CHART_COLOR_HIGHLIGHT] = nk_rgba( 255, 0, 0, 255);
- table[NK_COLOR_SCROLLBAR] = nk_rgba(190, 200, 200, 255);
- table[NK_COLOR_SCROLLBAR_CURSOR] = nk_rgba(64, 84, 95, 255);
- table[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = nk_rgba(70, 90, 100, 255);
- table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = nk_rgba(75, 95, 105, 255);
- table[NK_COLOR_TAB_HEADER] = nk_rgba(156, 193, 220, 255);
- }
- break;
+ glUseProgram(gph->shader->shaderProgram);
+ glBindFragDataLocation(gph->shader->shaderProgram, 0, "outColor");
+ gph->shader->matLocation = glGetUniformLocation(gph->shader->shaderProgram, "matrix");
+ gph->shader->colorLocation = glGetUniformLocation(gph->shader->shaderProgram, "color");
+ gph->shader->yScaleLocation = glGetUniformLocation(gph->shader->shaderProgram, "yscale");
+ gph->shader->yTopLocation = glGetUniformLocation(gph->shader->shaderProgram, "ytop");
+ gph->shader->lineSizeLocation = glGetUniformLocation(gph->shader->shaderProgram, "linewidth");
- case THEME_DARK:
- {
- table[NK_COLOR_TEXT] = nk_rgba(210, 210, 210, 255);
- table[NK_COLOR_WINDOW] = nk_rgba(57, 67, 71, 215);
- table[NK_COLOR_HEADER] = nk_rgba(51, 51, 56, 220);
- table[NK_COLOR_BORDER] = nk_rgba(46, 46, 46, 255);
- table[NK_COLOR_BUTTON] = nk_rgba(48, 83, 111, 255);
- table[NK_COLOR_BUTTON_HOVER] = nk_rgba(58, 93, 121, 255);
- table[NK_COLOR_BUTTON_ACTIVE] = nk_rgba(63, 98, 126, 255);
- table[NK_COLOR_TOGGLE] = nk_rgba(50, 58, 61, 255);
- table[NK_COLOR_TOGGLE_HOVER] = nk_rgba(45, 53, 56, 255);
- table[NK_COLOR_TOGGLE_CURSOR] = nk_rgba(48, 83, 111, 255);
- table[NK_COLOR_SELECT] = nk_rgba(57, 67, 61, 255);
- table[NK_COLOR_SELECT_ACTIVE] = nk_rgba(48, 83, 111, 255);
- table[NK_COLOR_SLIDER] = nk_rgba(50, 58, 61, 255);
- table[NK_COLOR_SLIDER_CURSOR] = nk_rgba(48, 83, 111, 245);
- table[NK_COLOR_SLIDER_CURSOR_HOVER] = nk_rgba(53, 88, 116, 255);
- table[NK_COLOR_SLIDER_CURSOR_ACTIVE] = nk_rgba(58, 93, 121, 255);
- table[NK_COLOR_PROPERTY] = nk_rgba(50, 58, 61, 255);
- table[NK_COLOR_EDIT] = nk_rgba(50, 58, 61, 225);
- table[NK_COLOR_EDIT_CURSOR] = nk_rgba(210, 210, 210, 255);
- table[NK_COLOR_COMBO] = nk_rgba(50, 58, 61, 255);
- table[NK_COLOR_CHART] = nk_rgba(50, 58, 61, 255);
- table[NK_COLOR_CHART_COLOR] = nk_rgba(48, 83, 111, 255);
- table[NK_COLOR_CHART_COLOR_HIGHLIGHT] = nk_rgba(255, 0, 0, 255);
- table[NK_COLOR_SCROLLBAR] = nk_rgba(50, 58, 61, 255);
- table[NK_COLOR_SCROLLBAR_CURSOR] = nk_rgba(48, 83, 111, 255);
- table[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = nk_rgba(53, 88, 116, 255);
- table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = nk_rgba(58, 93, 121, 255);
- table[NK_COLOR_TAB_HEADER] = nk_rgba(48, 83, 111, 255);
- }
- break;
+ glUniform1i(glGetUniformLocation(gph->shader->shaderProgram, "pixrearrangelookup"), 3);
+ glUniform1i(glGetUniformLocation(gph->shader->shaderProgram, "yvalues"), 4 + (s32)exIndex);
- case THEME_BLACK:
- case THEME_COUNT:
- themeSet = 0;
- }
+ u32 nValues = Number_of_Pixels_1D;
+ auto* xValues = new f32[nValues]; // allocate memory for xValues, actually, x is the coordinate of the pixel
+ auto* yValues = new f32[nValues];
+
+ u32 max = 0;
+ ForLoop(Number_of_Pixels_1D)
+ {
+ max = my_Max(max, gph->data[index]);
+ }
- if (themeSet) nk_style_from_table(ctx, table, Screen_Scale.x, Screen_Scale.y);
- else nk_style_default(ctx, Screen_Scale.x, Screen_Scale.y);
+ ForLoop(Number_of_Pixels_1D)
+ {
+ xValues[index] = (f32)index;
+ yValues[index] = (f32)gph->data[index] / (f32)max ; // normalise the data
+ }
- Theme_Colour = table[NK_COLOR_BUTTON_ACTIVE];
-
- NK_Context->style.slider.show_buttons = nk_true;
+ glActiveTexture(GL_TEXTURE4 + exIndex++);
- Current_Theme = theme;
-}
+ GLuint yVal, yValTex;
+ // generate a buffer object named yVal and save data to yVal
+ glGenBuffers(1, &yVal);
+ glBindBuffer(GL_TEXTURE_BUFFER, yVal);
+ glBufferData(GL_TEXTURE_BUFFER, sizeof(f32) * nValues, yValues, GL_STATIC_DRAW);
+ // add texture and link to the buffer object
+ glGenTextures(1, &yValTex);
+ glBindTexture(GL_TEXTURE_BUFFER, yValTex);
+ glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, yVal);
-global_function
-void
-Setup()
-{
- Decompressor = libdeflate_alloc_decompressor();
- if (!Decompressor)
- {
- fprintf(stderr, "Could not allocate decompressor\n");
- exit(1);
- }
+ gph->shader->yValuesBuffer = yVal;
+ gph->shader->yValuesBufferTex = yValTex;
+
+ // add the vertext data into buffer
+ glGenBuffers(1, &gph->vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, gph->vbo);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(f32) * nValues, xValues, GL_STATIC_DRAW);
- Compressor = libdeflate_alloc_compressor(12);
- if (!Compressor)
- {
- fprintf(stderr, "Could not allocate compressor\n");
- exit(1);
- }
+ // gen the vertex array object
+ glGenVertexArrays(1, &gph->vao);
+ glBindVertexArray(gph->vao);
- Texture_Buffer_Queue = PushStruct(Working_Set, texture_buffer_queue);
+ GLuint posAttrib = (GLuint)glGetAttribLocation(gph->shader->shaderProgram, "position");
+ glEnableVertexAttribArray(posAttrib);
+ glVertexAttribPointer(posAttrib, 1, GL_FLOAT, GL_FALSE, 0, 0);
- Meta_Data = PushStruct(Working_Set, meta_data);
- memset(Meta_Data, 0, sizeof(meta_data));
- MetaData_Active_Tag = 0;
- ForLoop(ArrayCount(Default_Tags)) strcpy((char *)Meta_Data->tags[MetaData_Active_Tag + index], Default_Tags[index]);
- if (Grey_Out_Settings)
- {
- delete Grey_Out_Settings;
- Grey_Out_Settings = nullptr;
- }
- Grey_Out_Settings = new GreyOutSettings(Meta_Data);
- if (user_profile_settings_ptr)
- {
- delete user_profile_settings_ptr;
- user_profile_settings_ptr = nullptr;
+ delete[] xValues;
+ delete[] yValues;
+
+ glActiveTexture(GL_TEXTURE0);
+ }
+ break;
+ }
}
- user_profile_settings_ptr = new UserProfileSettings();
- // Contig Name Label UI
+ return ;
+}
+
+
+
+global_function
+u08
+LoadState(u64 headerHash, char *path = 0);
+
+global_function
+load_file_result
+LoadFile(const char *filePath, memory_arena *arena, char **fileName, u64 *headerHash)
+{
+ u64 fileSize = 0;
+
+ FILE *file = TestFile(filePath, &fileSize); // 检查前4个字节读取到的数据, 如果为 u08 Magic[] = {'p', 's', 't', 'm'} 则通过验证,否则将指针file设置为空指针
+ if (!file) // 如果为空指针, 返回读取错误fileErr
{
- Contig_Name_Labels = PushStruct(Working_Set, ui_colour_element_bg);
- Contig_Name_Labels->on = 0;
- Contig_Name_Labels->fg = Yellow_Text_Float;
- Contig_Name_Labels->bg = Grey_Background;
-#define DefaultNameLabelTextSize 32.0f
- Contig_Name_Labels->size = DefaultNameLabelTextSize;
+ return(fileErr);
}
- // Scale Bar UI
- {
- Scale_Bars = PushStruct(Working_Set, ui_colour_element_bg);
- Scale_Bars->on = 0;
- Scale_Bars->fg = Red_Text_Float;
- Scale_Bars->bg = Grey_Background;
-#define DefaultScaleBarSize 20.0f
- Scale_Bars->size = DefaultScaleBarSize;
- }
-
- // Grid UI
- {
- Grid = PushStruct(Working_Set, ui_colour_element);
- Grid->on = 1;
- Grid->bg = Grey_Background;
-#define DefaultGridSize 0.00025f
- Grid->size = DefaultGridSize;
- }
+ FenceIn(File_Loaded = 0);
- // Contig Ids UI
+ static u32 reload = 0;
+
+ if (!reload)
{
- Contig_Ids = PushStruct(Working_Set, ui_colour_element);
- Contig_Ids->on = 1;
-#define DefaultContigIdSize (DefaultGridSize * 3.0f)
- Contig_Ids->size = DefaultContigIdSize;
+ reload = 1;
}
+ else // clear all the memory, in gl and the arena
+ {
+ glDeleteTextures(1, &Contact_Matrix->textures);
- // Tool Tip UI
- {
- Tool_Tip = PushStruct(Working_Set, ui_colour_element_bg);
- Tool_Tip->on = 1;
- Tool_Tip->fg = Yellow_Text_Float;
- Tool_Tip->bg = Grey_Background;
-#define DefaultToolTipTextSize 20.0f
- Tool_Tip->size = DefaultToolTipTextSize;
- }
+ glDeleteVertexArrays((GLsizei)(Number_of_Textures_1D * Number_of_Textures_1D), Contact_Matrix->vaos);
+ glDeleteBuffers((GLsizei)(Number_of_Textures_1D * Number_of_Textures_1D), Contact_Matrix->vbos);
- // Edit Mode Colours
- {
- Edit_Mode_Colours = PushStruct(Working_Set, edit_mode_colours);
- Edit_Mode_Colours->preSelect = Green_Float;
- Edit_Mode_Colours->select = Blue_Float;
- Edit_Mode_Colours->invSelect = Red_Float;
- Edit_Mode_Colours->fg = Yellow_Text_Float;
- Edit_Mode_Colours->bg = Grey_Background;
- }
-
- // Waypoint Mode Colours
- {
- Waypoint_Mode_Data = PushStruct(Working_Set, waypoint_mode_data);
- Waypoint_Mode_Data->base = Red_Full;
- Waypoint_Mode_Data->selected = Blue_Full;
- Waypoint_Mode_Data->text = Yellow_Text_Float;
- Waypoint_Mode_Data->bg = Grey_Background;
- Waypoint_Mode_Data->size = DefaultWaypointSize;
- }
-
- // Scaff Mode Colours
- {
- Scaff_Mode_Data = PushStruct(Working_Set, meta_mode_data);
- Scaff_Mode_Data->text = Yellow_Text_Float;
- Scaff_Mode_Data->bg = Grey_Background;
- Scaff_Mode_Data->size = DefaultScaffSize;
- }
-
- // Meta Mode Colours
- {
- MetaData_Mode_Data = PushStruct(Working_Set, meta_mode_data);
- MetaData_Mode_Data->text = Yellow_Text_Float;
- MetaData_Mode_Data->bg = Grey_Background;
- MetaData_Mode_Data->size = DefaultMetaDataSize;
- }
-
- // Extension Mode Colours
- {
- Extension_Mode_Data = PushStruct(Working_Set, meta_mode_data);
- Extension_Mode_Data->text = Yellow_Text_Float;
- Extension_Mode_Data->bg = Grey_Background;
- Extension_Mode_Data->size = DefaultExtensionSize;
- }
-
-#ifdef Internal
- {
- Tiles = PushStruct(Working_Set, ui_colour_element);
- Tiles->on = 1;
- Tiles->bg = {0.0f, 1.0f, 1.0f, 1.0f};
+ glDeleteBuffers(1, &Contact_Matrix->pixelStartLookupBuffer);
+ glDeleteTextures(1, &Contact_Matrix->pixelStartLookupBufferTex);
- QuadTrees = PushStruct(Working_Set, ui_colour_element);
- QuadTrees->on = 1;
- QuadTrees->bg = {0.0f, 1.0f, 0.0f, 1.0f};
- }
-#endif
+ glDeleteBuffers(1, &Contact_Matrix->pixelRearrangmentLookupBuffer);
+ glDeleteTextures(1, &Contact_Matrix->pixelRearrangmentLookupBufferTex);
- // Contact Matrix Shader
- {
- Contact_Matrix = PushStruct(Working_Set, contact_matrix);
- Contact_Matrix->shaderProgram = CreateShader(FragmentSource_Texture.c_str(), VertexSource_Texture.c_str());
+ glDeleteVertexArrays((GLsizei)Grid_Data->nBuffers, Grid_Data->vaos);
+ glDeleteBuffers((GLsizei)Grid_Data->nBuffers, Grid_Data->vbos);
- glUseProgram(Contact_Matrix->shaderProgram);
- glBindFragDataLocation(Contact_Matrix->shaderProgram, 0, "outColor");
+ glDeleteVertexArrays((GLsizei)Label_Box_Data->nBuffers, Label_Box_Data->vaos);
+ glDeleteBuffers((GLsizei)Label_Box_Data->nBuffers, Label_Box_Data->vbos);
- Contact_Matrix->matLocation = glGetUniformLocation(Contact_Matrix->shaderProgram, "matrix");
- glUniform1i(glGetUniformLocation(Contact_Matrix->shaderProgram, "tex"), 0);
- glUniform1i(glGetUniformLocation(Contact_Matrix->shaderProgram, "colormap"), 1);
- glUniform1i(glGetUniformLocation(Contact_Matrix->shaderProgram, "pixstartlookup"), 2);
- glUniform1i(glGetUniformLocation(Contact_Matrix->shaderProgram, "pixrearrangelookup"), 3);
+ glDeleteVertexArrays((GLsizei)Scale_Bar_Data->nBuffers, Scale_Bar_Data->vaos);
+ glDeleteBuffers((GLsizei)Scale_Bar_Data->nBuffers, Scale_Bar_Data->vbos);
- glActiveTexture(GL_TEXTURE1);
+ glDeleteVertexArrays((GLsizei)Contig_ColourBar_Data->nBuffers, Contig_ColourBar_Data->vaos);
+ glDeleteBuffers((GLsizei)Contig_ColourBar_Data->nBuffers, Contig_ColourBar_Data->vbos);
- Color_Maps = PushStruct(Working_Set, color_maps);
- u32 nMaps = Number_of_Color_Maps;
- Color_Maps->maps = PushArray(Working_Set, GLuint, nMaps);
- Color_Maps->mapPreviews = PushArray(Working_Set, struct nk_image, nMaps);
- Color_Maps->nMaps = nMaps;
- Color_Maps->currMap = 1;
+ glDeleteVertexArrays((GLsizei)Scaff_Bar_Data->nBuffers, Scaff_Bar_Data->vaos);
+ glDeleteBuffers((GLsizei)Scaff_Bar_Data->nBuffers, Scaff_Bar_Data->vbos);
- ForLoop(nMaps)
+ TraverseLinkedList(Extensions.head, extension_node)
{
- u32 mapPreviewImage[256];
-
- GLuint tbo, tboTex, texPreview;
-
- glGenBuffers(1, &tbo);
- glBindBuffer(GL_TEXTURE_BUFFER, tbo);
- glBufferData(GL_TEXTURE_BUFFER, sizeof(Color_Map_Data[index]), Color_Map_Data[index], GL_STATIC_DRAW);
-
- glGenTextures(1, &tboTex);
- glBindTexture(GL_TEXTURE_BUFFER, tboTex);
- glTexBuffer(GL_TEXTURE_BUFFER, GL_RGB32F, tbo);
-
- Color_Maps->maps[index] = tboTex;
-
- glActiveTexture(GL_TEXTURE0);
-
- ForLoop2(256) //TODO SIMD
+ switch (node->type)
{
- mapPreviewImage[index2] = ((u32)(Color_Map_Data[index][3 * index2] * 255.0f)) |
- (((u32)(Color_Map_Data[index][(3 * index2) + 1] * 255.0f)) << 8) |
- (((u32)(Color_Map_Data[index][(3 * index2) + 2] * 255.0f)) << 16) |
- 0xff000000;
+ case extension_graph:
+ {
+ graph *gph = (graph *)node->extension;
+ glDeleteVertexArrays(1, &gph->vao);
+ glDeleteBuffers(1, &gph->vbo);
+ glDeleteBuffers(1, &gph->shader->yValuesBuffer);
+ glDeleteTextures(1, &gph->shader->yValuesBufferTex);
+ }
+ break;
}
- glGenTextures(1, &texPreview);
- glBindTexture(GL_TEXTURE_2D, texPreview);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, mapPreviewImage);
- glGenerateMipmap(GL_TEXTURE_2D);
-
- Color_Maps->mapPreviews[index] = nk_image_id((s32)texPreview);
-
- glActiveTexture(GL_TEXTURE1);
}
- NextColorMap(-1);
-
- glActiveTexture(GL_TEXTURE0);
-
- Color_Maps->cpLocation = glGetUniformLocation(Contact_Matrix->shaderProgram, "controlpoints");
- Color_Maps->controlPoints[0] = 0.0f;
- Color_Maps->controlPoints[1] = 0.5f;
- Color_Maps->controlPoints[2] = 1.0f;
- glUniform3fv( Color_Maps->cpLocation, 1, Color_Maps->controlPoints);
- }
-
- // Flat Color Shader
- {
- Flat_Shader = PushStruct(Working_Set, flat_shader);
- Flat_Shader->shaderProgram = CreateShader(FragmentSource_Flat.c_str(), VertexSource_Flat.c_str());
- glUseProgram(Flat_Shader->shaderProgram);
- glBindFragDataLocation(Flat_Shader->shaderProgram, 0, "outColor");
+ Current_Loaded_Texture = 0;
+ Texture_Ptr = 0;
+
+ Mouse_Move.x = -1.0;
+ Mouse_Move.y = -1.0;
- Flat_Shader->matLocation = glGetUniformLocation(Flat_Shader->shaderProgram, "matrix");
- Flat_Shader->colorLocation = glGetUniformLocation(Flat_Shader->shaderProgram, "color");
- }
-
- // Fonts
- {
- UI_Shader = PushStruct(Working_Set, ui_shader);
- UI_Shader->shaderProgram = CreateShader(FragmentSource_UI.c_str(), VertexSource_UI.c_str());
- glUseProgram(UI_Shader->shaderProgram);
- glBindFragDataLocation(UI_Shader->shaderProgram, 0, "outColor");
- glUniform1i(glGetUniformLocation(UI_Shader->shaderProgram, "tex"), 0);
- UI_Shader->matLocation = glGetUniformLocation(UI_Shader->shaderProgram, "matrix");
+ Camera_Position.x = 0.0f;
+ Camera_Position.y = 0.0f;
+ Camera_Position.z = 1.0f;
+
+ Edit_Pixels.editing = 0;
+ Global_Mode = mode_normal;
- FontStash_Context = glfonsCreate(512, 512, FONS_ZERO_TOPLEFT);
- Font_Normal = fonsAddFontMem(FontStash_Context, "Sans Regular", FontNormal, (s32)FontNormal_Size, 0);
+ Extensions = {};
- if (Font_Normal == FONS_INVALID)
+ // delete the memory collected by new
+ if (Contact_Matrix->vaos)
{
- fprintf(stderr, "Could not add font 'DroidSerif-Regular.ttf'\n");
- exit(1);
+ delete[] Contact_Matrix->vaos;
+ Contact_Matrix->vaos = nullptr;
}
- Font_Bold = fonsAddFontMem(FontStash_Context, "Sans Bold", FontBold, (s32)FontBold_Size, 0);
- if (Font_Bold == FONS_INVALID)
+ if (Contact_Matrix->vbos)
{
- fprintf(stderr, "Could not add font 'DroidSerif-Bold.ttf'\n");
- exit(1);
+ delete[] Contact_Matrix->vbos;
+ Contact_Matrix->vbos = nullptr;
}
+ if (pixel_density_extension)
+ {
+ delete pixel_density_extension;
+ pixel_density_extension = nullptr;
+ }
+ if (frag_cut_cal_ptr)
+ {
+ delete frag_cut_cal_ptr;
+ frag_cut_cal_ptr = nullptr;
+ }
+ ResetMemoryArenaP(arena); // release all the memory allocated, avoid memory leak
+ auto_curation_state.clear();
}
- // Quad EBO
- {
- GLushort pIndexQuad[6];
- pIndexQuad[0] = 0;
- pIndexQuad[1] = 1;
- pIndexQuad[2] = 2;
- pIndexQuad[3] = 2;
- pIndexQuad[4] = 3;
- pIndexQuad[5] = 0;
-
- glGenBuffers(1, &Quad_EBO);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Quad_EBO);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(GLushort), pIndexQuad, GL_STATIC_DRAW);
- }
-
- GLuint posAttribFlatShader = (GLuint)glGetAttribLocation(Flat_Shader->shaderProgram, "position");
- auto PushGenericBuffer = [posAttribFlatShader] (quad_data **quadData, u32 numberOfBuffers) -> void
+ // File Contents
{
- *quadData = PushStruct(Working_Set, quad_data);
-
- (*quadData)->vaos = PushArray(Working_Set, GLuint, numberOfBuffers);
- (*quadData)->vbos = PushArray(Working_Set, GLuint, numberOfBuffers);
+ char *tmp = (char *)filePath;
+#ifdef _WIN32
+ char sep = '\\';
+#else
+ char sep = '/';
+#endif
- glUseProgram(Flat_Shader->shaderProgram);
+ while (*++tmp) {}
+ while ((*--tmp != sep) && *tmp) {}
- ForLoop(numberOfBuffers)
- {
- glGenVertexArrays(1, (*quadData)->vaos + index);
- glBindVertexArray((*quadData)->vaos[index]);
+ *fileName = tmp + 1;
- glGenBuffers(1, (*quadData)->vbos + index);
- glBindBuffer(GL_ARRAY_BUFFER, (*quadData)->vbos[index]);
- glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(vertex), NULL, GL_DYNAMIC_DRAW);
+ u32 intBuff[16];
+ PushStringIntoIntArray(intBuff, ArrayCount(intBuff), (u08 *)(*fileName)); // 将字符穿转移到intbuff数组中
- glEnableVertexAttribArray(posAttribFlatShader);
- glVertexAttribPointer(posAttribFlatShader, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), 0);
+ /*
+ 这段代码假设文件中的数据是以 4 字节整数的形式存储的,并且依次存储了
+ nBytesHeaderComp 和 nBytesHeader 两个值。通常情况下,
+ 这种操作用于读取文件中存储的数据头部信息或者其他固定格式的数据。
+ */
+ u32 nBytesHeaderComp; // 压缩后数据大小
+ u32 nBytesHeader; // 解压后数据大小
+ fread(&nBytesHeaderComp, 1, 4, file); // 从文件中读取 4 个字节的数据,并将其存储在 nBytesHeaderComp 变量中
+ fread(&nBytesHeader, 1, 4, file);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Quad_EBO);
- }
- };
+ u08 *header = PushArrayP(arena, u08, nBytesHeader); // 从内存池中分配u08 数组,大小为 nBytesHeader
+ u08 *compressionBuffer = PushArrayP(arena, u08, nBytesHeaderComp); // 从内存池中分配u08 数组,大小为 nBytesHeaderComp
- // Edit Mode Data
- {
- PushGenericBuffer(&Edit_Mode_Data, 12);
- }
+ fread(compressionBuffer, 1, nBytesHeaderComp, file); // nBytesHeaderComp个字节的压缩数据,存储到compressionBuffer
+ *headerHash = FastHash64( // head的地址采用fasthash加密,作为存储文件的文件名。 compressionBuffer所指向的值进行hash得到一个名字,作为存储文件的文件名
+ compressionBuffer,
+ nBytesHeaderComp,
+ FastHash64(intBuff, sizeof(intBuff), 0xbafd06832de619c2)
+ );
+ // fprintf(stdout, "The headerHash is calculated accordig to the compressed head, the hash number is (%llu) and the cache file name is (%s)\n", *headerHash, (u08*) headerHash);
+ if (
+ libdeflate_deflate_decompress(
+ Decompressor, // 指向 解压缩器
+ (const void *)compressionBuffer, // 指向 即将解压的数据,(const void *)强制转换为不可修改的内存块
+ nBytesHeaderComp, // 解压缩的字节数
+ (void *)header, // 指向 解压缩后存储的位置,转换为通用内存块
+ nBytesHeader, // 解压后预计大小
+ NULL) // 表示不传递其他参数给压缩函数
+ )
+ {
+ return(decompErr); // decompress err
+ }
+ FreeLastPushP(arena); // comp buffer 释放内存池(arena)中最近一次通过 PushArrayP 宏分配的内存空间
+ // 遍历内存池链表,找到最后一个内存池,并释放其最近一次分配的内存空间。防止内存泄漏
- // Tool Tip Data
- {
- PushGenericBuffer(&Tool_Tip_Data, 1);
- }
+ /*
+ header的格式
+ ==========================
+ nBytes Contents
+ --------------------------
+ 8 Total_Genome_Length
+ 4 Number_of_Original_Contigs
+ -------------------
+ Number_of_Original_Contigs 个 contigs 的存储规则
+ -------------------
+ 4 contig fracs
+ 64 name
+ ------------------
+ 1 textureRes
+ 1 nTextRes
+ 1 mipMapLevels
- // Waypoint Data
- {
- PushGenericBuffer(&Waypoint_Data, (3 * Waypoints_Stack_Size) + 1);
- }
+ */
- // Nuklear Setup
- {
-#define NK_Memory_Size MegaByte(32)
- NK_Device = PushStruct(Working_Set, device);
- u08 *nkCmdMemory = PushArray(Working_Set, u08, NK_Memory_Size);
- nk_buffer_init_fixed(&NK_Device->cmds, (void *)nkCmdMemory, NK_Memory_Size);
- NK_Device->lastContextMemory = PushArray(Working_Set, u08, NK_Memory_Size);
- memset(NK_Device->lastContextMemory, 0, NK_Memory_Size);
- NK_Device->prog = UI_Shader->shaderProgram;
- NK_Device->uniform_proj = UI_Shader->matLocation;
- NK_Device->attrib_pos = UI_SHADER_LOC_POSITION;
- NK_Device->attrib_uv = UI_SHADER_LOC_TEXCOORD;
- NK_Device->attrib_col = UI_SHADER_LOC_COLOR;
+ u64 val64;
+ u08 *ptr = (u08 *)&val64; // 获取val64存储的 八位无符号整型(u08)的指针
+ ForLoop(8)
+ {
+ *ptr++ = *header++; // 指针赋值给到val64的大小 -> 整个基因的长度
+ }
+ Total_Genome_Length = val64;
- GLsizei vs = sizeof(nk_glfw_vertex);
- size_t vp = offsetof(nk_glfw_vertex, position);
- size_t vt = offsetof(nk_glfw_vertex, uv);
- size_t vc = offsetof(nk_glfw_vertex, col);
+ u32 val32;
+ ptr = (u08 *)&val32;
+ ForLoop(4)
+ {
+ *ptr++ = *header++;
+ }
+ Number_of_Original_Contigs = val32; // 指针赋值给到val32的值 -> contigs的数目
- glGenBuffers(1, &NK_Device->vbo);
- glGenBuffers(1, &NK_Device->ebo);
- glGenVertexArrays(1, &NK_Device->vao);
+ // 从内存池中分配存储原始 contig 的数组内存,类型为 original_contig,数组长度为 Number_of_Original_Contigs
+ Original_Contigs = PushArrayP(arena, original_contig, Number_of_Original_Contigs);
+ // 分配一个存储浮点数的数组
+ // f32 *contigFracs = PushArrayP(arena, f32, Number_of_Original_Contigs);
+ f32 *contigFracs = new f32[Number_of_Original_Contigs];
+ ForLoop(Number_of_Original_Contigs) // 读取 contigs fraction (f32) and name
+ {
- glBindVertexArray(NK_Device->vao);
- glBindBuffer(GL_ARRAY_BUFFER, NK_Device->vbo);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, NK_Device->ebo);
+ f32 frac;
+ u32 name[16];
- glEnableVertexAttribArray((GLuint)NK_Device->attrib_pos);
- glEnableVertexAttribArray((GLuint)NK_Device->attrib_uv);
- glEnableVertexAttribArray((GLuint)NK_Device->attrib_col);
+ // 读取每个contig 对应的一个f32
+ ptr = (u08 *)&frac;
+ ForLoop2(4) // 从header中读取4个字节的数据存储到frac中
+ {
+ *ptr++ = *header++;
+ }
+ contigFracs[index] = frac; // 将这个f32 存储到 contigFracs[index] 中
+
+ // 读取contig的名字
+ ptr = (u08 *)name;
+ ForLoop2(64)
+ {
+ *ptr++ = *header++;
+ }
+ // contig name赋值
+ ForLoop2(16)
+ {
+ Original_Contigs[index].name[index2] = name[index2]; // 将 u32 name[16] 给到每一个contig 的name
+ }
+
+ (Original_Contigs + index)->contigMapPixels = PushArrayP(arena, u32, Number_of_Pixels_1D); // 为每个contig 的 mapPixels 变量 申请内存
+ (Original_Contigs + index)->nContigs = 0;
+ }
- glVertexAttribPointer((GLuint)NK_Device->attrib_pos, 2, GL_FLOAT, GL_FALSE, vs, (void*)vp);
- glVertexAttribPointer((GLuint)NK_Device->attrib_uv, 2, GL_FLOAT, GL_FALSE, vs, (void*)vt);
- glVertexAttribPointer((GLuint)NK_Device->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, vs, (void*)vc);
+ u08 textureRes = *header++; // 分辨率
+ u08 nTextRes = *header++; // 纹理数目
+ u08 mipMapLevels = *header; // ??
- NK_Atlas = PushStruct(Working_Set, nk_font_atlas);
- nk_font_atlas_init_default(NK_Atlas);
- nk_font_atlas_begin(NK_Atlas);
- struct nk_font_config cfg = nk_font_config(14);
- cfg.oversample_h = 3;
- cfg.oversample_v = 3;
- NK_Font = nk_font_atlas_add_from_memory(NK_Atlas, FontBold, (nk_size)FontBold_Size, 22 * Screen_Scale.y, &cfg);
- NK_Font_Browser = nk_font_atlas_add_from_memory(NK_Atlas, FontBold, (nk_size)FontBold_Size, 14 * Screen_Scale.y, &cfg);
+ Texture_Resolution = Pow2(textureRes); // 纹理分辨率 当前显示的像素点个数,1024
+ Number_of_Textures_1D = Pow2(nTextRes); // 一维纹理数目 可以放大的次数,每一个像素点可以放大32次,
+ Number_of_MipMaps = mipMapLevels;
- s32 w,h;
- const void *image = nk_font_atlas_bake(NK_Atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
+ Number_of_Pixels_1D = Number_of_Textures_1D * Texture_Resolution; // 更新一维数据的长度
- glGenTextures(1, &NK_Device->font_tex);
- glBindTexture(GL_TEXTURE_2D, NK_Device->font_tex);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)w, (GLsizei)h, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, image);
+ // update the pixel_cut consider range if high resolution
+ if (Number_of_Pixels_1D > 32768) auto_curation_state.auto_cut_diag_window_for_pixel_mean = 16;
- nk_font_atlas_end(NK_Atlas, nk_handle_id((s32)NK_Device->font_tex), &NK_Device->null);
- u08 *nkContextMemory = PushArray(Working_Set, u08, NK_Memory_Size);
- nk_init_fixed(NK_Context, (void *)nkContextMemory, NK_Memory_Size, &NK_Font->handle);
+ Map_State = PushStructP(arena, map_state); // 从内存池中分配一个包含 map_state 结构的内存块,并返回指向该结构的指针, 存储contigs map到图像中的数据
+ Map_State->contigIds = PushArrayP(arena, u32, Number_of_Pixels_1D); // 从内存池中分配存储 contigIds 的数组,数组长度为 Number_of_Pixels_1D
+ Map_State->originalContigIds = PushArrayP(arena, u32, Number_of_Pixels_1D); //
+ Map_State->contigRelCoords = PushArrayP(arena, u32, Number_of_Pixels_1D); // 像素坐标
+ Map_State->scaffIds = PushArrayP(arena, u32, Number_of_Pixels_1D); // scaffID
+ Map_State->metaDataFlags = PushArrayP(arena, u64, Number_of_Pixels_1D); // 标记
+ memset(Map_State->scaffIds, 0, Number_of_Pixels_1D * sizeof(u32)); // 将scaffID和metaDataFlags初始化为0
+ memset(Map_State->metaDataFlags, 0, Number_of_Pixels_1D * sizeof(u64));
+ f32 total = 0.0f; // 所有contig的一个浮点数的累积, finally should approximately be 1.0
+ u32 lastPixel = 0;
+ u32 relCoord = 0;
- SetTheme(NK_Context, THEME_DARK);
+ ForLoop(Number_of_Original_Contigs) // 初始设定每个contig的每个像素点的id和局部坐标
+ {
+ total += contigFracs[index]; // 当前所有contig对应的浮点数的累积,包括当前contig
+ u32 pixel = (u32)((f64)Number_of_Pixels_1D * (f64)total); // 每行像素点数 * 当前占比
+
+ relCoord = 0;
+#ifdef RevCoords
+ u32 tmp = pixel - lastPixel - 1;
+#endif
+ while (lastPixel < pixel)
+ {
+ Map_State->originalContigIds[lastPixel] = index; // 每一个像素点对应的都是当前contig的编号
+ Map_State->contigRelCoords[lastPixel++] = // 每一个像素点对应的在当前contig中的局部坐标
+#ifdef RevCoords
+ tmp - relCoord++;
+#else
+ relCoord++;
+#endif
+ }
+ }
+ delete[] contigFracs;
+ while (lastPixel < Number_of_Pixels_1D) // 处理数值计算导致的lastPixel小于Number_of_Pixels_1D的问题
+ {
+ Map_State->originalContigIds[lastPixel] = (u32)(Number_of_Original_Contigs - 1); //假设其为最后一个contig的像素点
+ Map_State->contigRelCoords[lastPixel++] = relCoord++;
+ }
- Theme_Name[THEME_RED] = (u08 *)"Red";
- Theme_Name[THEME_BLUE] = (u08 *)"Blue";
- Theme_Name[THEME_WHITE] = (u08 *)"White";
- Theme_Name[THEME_BLACK] = (u08 *)"Black";
- Theme_Name[THEME_DARK] = (u08 *)"Dark";
- }
+ Contigs = PushStructP(arena, contigs); // 声明一个存储contigs的内存块, 其返回Contigs作为这个块的指针,实际上此处为整个genome的信息
+ Contigs->contigs_arr = PushArrayP(arena, contig, Max_Number_of_Contigs); // 每一个Contigs中会有contigs (片段),一共有Max_Number_of_Contigs多个片段,最多存放4096个contigs
+ Contigs->contigInvertFlags = PushArrayP(arena, u08, (Max_Number_of_Contigs + 7) >> 3); // (4096 + 7 ) >> 3 = 512, 声明512个u08的存储空间
- Loading_Arena = PushStruct(Working_Set, memory_arena);
- CreateMemoryArena(*Loading_Arena, MegaByte(512));
- //Loading_Arena = PushSubArena(Working_Set, MegaByte(128));
-}
+ UpdateContigsFromMapState(); // 根据mapstate 跟新当前的contigs, 并且更新original_contigs里面的每个contig所包含的片段的个数和片段的中点
+ u32 nBytesPerText = 0; // 程序将一整张图分成了32*32个小格子,每一个格子被称作texture
+ ForLoop(Number_of_MipMaps)
+ {
+ nBytesPerText += Pow2((2 * textureRes--)); // sum([2**(2*i) for i in range(10, 10-Number_of_MipMaps, -1)])/2
+ }
+ nBytesPerText >>= 1; // 除以 2 因为数据是经过压缩的
+ Bytes_Per_Texture = nBytesPerText; // 一个texture 对应的字节数目
+ File_Atlas = PushArrayP(arena, file_atlas_entry, (Number_of_Textures_1D + 1) * (Number_of_Textures_1D >> 1)); // variable to store the data entry
-global_function
-void
-TakeScreenShot(int nchannels = 4)
-{
- s32 viewport[4];
- glGetIntegerv (GL_VIEWPORT, viewport);
+ u32 currLocation = sizeof(Magic) + 8 + nBytesHeaderComp; // current localtion of the pointer = magic_check + (u32 compressed head length) + (u32 decompressed head length) + compressed header length
+
+ // locating the pointers to data of entries
+ ForLoop((Number_of_Textures_1D + 1) * (Number_of_Textures_1D >> 1)) // loop through total number of the textures
+ {
+ /*
+ 数据结构:
+ - magic (4 bytes)
+ - 8 bytes
+ - headercomp (nBytesHeaderComp bytes)
+ - a block of entry:
+ - number of bytes in u32
+ - data
- u08 *imageBuffer = PushArray(Working_Set, u08, (u32)(nchannels * viewport[2] * viewport[3]));
- glReadPixels ( 0, 0, viewport[2], viewport[3],
- nchannels==4 ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE,
- imageBuffer);
+ */
+ file_atlas_entry *entry = File_Atlas + index; // get the temprory pointer of the entry
+ u32 nBytes; // define a u32 to save the data
+ fread(&nBytes, 1, 4, file); // 读取四个字节, 前四个字节存储一个u32表示大小,后面的数据存储
+ fseek(file, nBytes, SEEK_CUR); // 文件指针会向前移动 nBytes 个字节,SEEK_CUR在c标准库中被定义为1, after the loop, pointer file is moved to the end of the reading file
+ currLocation += 4; // 每移动一次,currLocation 增加 4
- stbi_flip_vertically_on_write(1);
- stbi_write_png("PretextView_ScreenShot.png", viewport[2], viewport[3], nchannels, imageBuffer, nchannels * viewport[2]); //TODO change png compression to use libdeflate zlib impl
- FreeLastPush(Working_Set);
-}
+ entry->base = currLocation; // asign the current location to File_Atlas + index
+ entry->nBytes = nBytes; // asign the size to File_Atlas + index
+ currLocation += nBytes;
+ }
+ // Extensions
+ {
+ u08 magicTest[sizeof(Extension_Magic_Bytes[0])]; // define a u08 array, to check the end of the file, use this to read the extensions
-global_function
-void
-InvertMap(
- u32 pixelFrom, // from pixel
- u32 pixelTo, // end pixel
- bool update_contigs_flag
- )
-{
- if (pixelFrom > pixelTo)
- {
- u32 tmp = pixelFrom;
- pixelFrom = pixelTo;
- pixelTo = tmp;
- }
-
- u32 nPixels = Number_of_Pixels_1D;
+ while ((u64)(currLocation + sizeof(magicTest)) < fileSize)
+ {
+ u32 bytesRead = (u32)fread(magicTest, 1, sizeof(magicTest), file); // reading 4 bytes from the file
+ currLocation += bytesRead;
+ if (bytesRead == sizeof(magicTest))
+ {
+ ForLoop(ArrayCount(Extension_Magic_Bytes))
+ {
+ u08 foundExtension = 1;
+ u08 *magic = (u08 *)Extension_Magic_Bytes[index];
+ ForLoop2(sizeof(magicTest))
+ {
+ if (magic[index2] != magicTest[index2]) // magicTest is from the file, magic is from the definition // if magic this isn't the same, means no extensions found
+ {
+ foundExtension = 0;
+ break;
+ }
+ }
- Assert(pixelFrom < nPixels);
- Assert(pixelTo < nPixels);
-
- u32 copySize = (pixelTo - pixelFrom + 1) >> 1;
-
- u32 *tmpBuffer = new u32[copySize];
- u32 *tmpBuffer2 = new u32[copySize];
- u32 *tmpBuffer3 = new u32[copySize];
- u32 *tmpBuffer4 = new u32[copySize];
- u64 *tmpBuffer5 = new u64[copySize];
+ if (foundExtension) // if extension is found
+ {
+ extension_type type = (extension_type)index; // get the type of the extension
+ u32 extensionSize = 0;
+ switch (type)
+ {
+ case extension_graph:
+ {
+ u32 compSize;
+ fread(&compSize, 1, sizeof(u32), file); // get the size of the extension data
+ graph *gph = PushStructP(arena, graph); // create the size to store the extension data
+ extension_node *node = PushStructP(arena, extension_node);
+ u08 *dataPlusName = PushArrayP(arena, u08, ((sizeof(u32) * Number_of_Pixels_1D) + sizeof(gph->name) )); // there are 1024 * 32 u32 numbers. Every single one of them represents the data on a pixel.
+#pragma clang diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+ gph->data = (u32 *)(dataPlusName + sizeof(gph->name)); // the first 16 u32 are the name of the extention, which can include 16*32/8=64 u08 (char).
+#pragma clang diagnostic pop
+ extensionSize += (compSize + sizeof(u32));
+ u08 *compBuffer = PushArrayP(arena, u08, compSize);
+ fread(compBuffer, 1, compSize, file); // read the extension data from the file pointer
+ if (libdeflate_deflate_decompress(Decompressor, (const void *)compBuffer, compSize, (void *)dataPlusName, (sizeof(u32) * Number_of_Pixels_1D) + sizeof(gph->name), NULL)) // decompress compBuffer to dataPlusName
+ /* code from the libdeflate.h
+ enum libdeflate_result {
+ // Decompression was successful.
+ LIBDEFLATE_SUCCESS = 0,
- glBindBuffer(GL_TEXTURE_BUFFER, Contact_Matrix->pixelRearrangmentLookupBuffer);
- u32 *buffer = (u32 *)glMapBufferRange(GL_TEXTURE_BUFFER, 0, nPixels * sizeof(u32), GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); // map buffer to read and write
+ // Decompression failed because the compressed data was invalid,
+ * corrupt, or otherwise unsupported.
+ LIBDEFLATE_BAD_DATA = 1,
- if (buffer)
- {
- ForLoop(copySize) // put the first half in the buffer
- {
- tmpBuffer[index] = buffer[pixelFrom + index];
- tmpBuffer2[index] = Map_State->contigRelCoords[pixelFrom + index];
- tmpBuffer3[index] = Map_State->originalContigIds[pixelFrom + index];
- tmpBuffer4[index] = Map_State->scaffIds[pixelFrom + index];
- tmpBuffer5[index] = Map_State->metaDataFlags[pixelFrom + index];
- }
+ // A NULL 'actual_out_nbytes_ret' was provided, but the data would have
+ * decompressed to fewer than 'out_nbytes_avail' bytes.
+ LIBDEFLATE_SHORT_OUTPUT = 2,
- ForLoop(copySize) // set the first half to the second half
- {
- buffer[pixelFrom + index] = buffer[pixelTo - index];
- Map_State->contigRelCoords[pixelFrom + index] = Map_State->contigRelCoords[pixelTo - index];
- Map_State->originalContigIds[pixelFrom + index] = Map_State->originalContigIds[pixelTo - index];
- Map_State->scaffIds[pixelFrom + index] = Map_State->scaffIds[pixelTo - index];
- Map_State->metaDataFlags[pixelFrom + index] = Map_State->metaDataFlags[pixelTo - index];
- }
+ // The data would have decompressed to more than 'out_nbytes_avail'
+ * bytes.
+ LIBDEFLATE_INSUFFICIENT_SPACE = 3,
+ };
+ */
+ { // unsuccessful decompress
+ FreeLastPushP(arena); // data
+ FreeLastPushP(arena); // graph
+ FreeLastPushP(arena); // node
+ }
+ else
+ { // successful decompress
+#pragma clang diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+ u32 *namePtr = (u32 *)dataPlusName; // get a temp pointer,将原来的u08指针切换为u32指针,所指向的位置相同,只是不同的解释方式
+#pragma clang diagnostic pop
+ ForLoop2(ArrayCount(gph->name)) // get the graph name
+ {
+ gph->name[index2] = *(namePtr + index2);
+ }
- ForLoop(copySize) // set the second half from the buffer
- {
- buffer[pixelTo - index] = tmpBuffer[index];
- Map_State->contigRelCoords[pixelTo - index] = tmpBuffer2[index];
- Map_State->originalContigIds[pixelTo - index] = tmpBuffer3[index];
- Map_State->scaffIds[pixelTo - index] = tmpBuffer4[index];
- Map_State->metaDataFlags[pixelTo - index] = tmpBuffer5[index];
+ node->type = type; // assign the gph to node
+ node->extension = gph;
+ AddExtension(node); // add node to extension
+ }
+ FreeLastPushP(arena); // compBuffer
+ }
+ break;
+ }
+ currLocation += extensionSize;
+ }
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
}
- }
- else
- {
- fprintf(stderr, "Could not map pixel rearrange buffer\n");
+
+ fclose(file); // the positions and file pointers will be saved to texture_buffer_queue, which can be read in multi-thread mode
}
- glUnmapBuffer(GL_TEXTURE_BUFFER);
- glBindBuffer(GL_TEXTURE_BUFFER, 0);
+ // Load Textures: reading from file and pushing into glTexture with index Contact_Matrix->textures
+ {
+ InitialiseTextureBufferQueue(arena, Texture_Buffer_Queue, Bytes_Per_Texture, filePath); // 初始化所有的queue texture_buffer_queue, 一共有8个queue,每个queue有8个buffer
- delete[] tmpBuffer ;
- delete[] tmpBuffer2;
- delete[] tmpBuffer3;
- delete[] tmpBuffer4;
- delete[] tmpBuffer5;
+ u32 nTextures = (Number_of_Textures_1D + 1) * (Number_of_Textures_1D >> 1); // number of textures (528)
+ // u32 *packedTextureIndexes = PushArrayP(arena, u32, nTextures); // using a pointer of sequences of u32 as the texture index
+ u32* packedTextureIndexes = new u32[nTextures]; // (u32*) malloc(sizeof(u32) * nTextures); // this is released so new is ok
+ ThreadPoolAddTask(Thread_Pool, PopulateTextureLoadQueue, packedTextureIndexes); // multi-thread for loading the texture entries
- if (update_contigs_flag) UpdateContigsFromMapState(); // update the contigs from the buffer
+ glActiveTexture(GL_TEXTURE0); // 所有的子图加载在 texture 0
+ glGenTextures(1, &Contact_Matrix->textures); // 获取一个texture 存到
+ glBindTexture(GL_TEXTURE_2D_ARRAY, Contact_Matrix->textures); // 绑定到当前的texture
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 0);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, (GLint)Number_of_MipMaps - 1);
- map_edit edit;
- edit.finalPix1 = (u32)pixelTo;
- edit.finalPix2 = (u32)pixelFrom;
- edit.delta = 0;
- MoveWayPoints(&edit);
-}
+ u32 resolution = Texture_Resolution;
+ ForLoop(Number_of_MipMaps) // 初始一个texture的一个维度有1024个像素点,放大后一个texture的一个维度只有32(1024 / 2**5)个像素点
+ { // 初始化所有层级mipmap level的 gl_texture_2d_array
+ glCompressedTexImage3D (
+ GL_TEXTURE_2D_ARRAY, // 指定纹理目标 例如GL_TEXTURE_3D
+ (GLint)index, // 指定纹理层级
+ GL_COMPRESSED_RED_RGTC1, // texture数据的压缩格式 Unsigned normalized 1-component only.
+ (GLsizei)resolution, (GLsizei)resolution, (GLsizei)nTextures, // 纹理宽度, 高度, 深度
+ 0, // border
+ (GLsizei)((resolution >> 1) * resolution * nTextures), // 每一个texture 的数据大小 (bytes),注意此处初始化了全部的 nTextures 个texture
+ 0); // 指向数据的指针
+ resolution >>= 1;
+ }
+
+ u32 ptr = 0;
+ printf("Loading textures...\n");
+ ForLoop(Number_of_Textures_1D)
+ {
+ ForLoop2(Number_of_Textures_1D - index)
+ {
+ volatile texture_buffer *loadedTexture = 0; // 使用volatile锁放弃存取优化。如果优化(不使用volatile),该值存取会被优化,可能会存放在寄存器中,而不是每次访问该值都会从内存中读取
+ while (!loadedTexture)
+ {
+ #ifndef _WIN32 // unix
+ __atomic_load(&Current_Loaded_Texture, &loadedTexture, __ATOMIC_SEQ_CST);
+ #else // windows
+ // loadedTexture = InterlockedCompareExchangePointer(&Current_Loaded_Texture, nullptr, nullptr);
+ loadedTexture = (texture_buffer*)InterlockedCompareExchangePointer(
+ (PVOID volatile*)&Current_Loaded_Texture,
+ NULL,
+ NULL);
+ #endif // __WIN32
+ }
+ u08 *texture = loadedTexture->texture; // 获取loadedtexture的texture的指针
+
+ // push the texture data (number_of_mipmaps) to the gl_texture_2d_array
+ resolution = Texture_Resolution;
+ for ( GLint level = 0;
+ level < (GLint)Number_of_MipMaps;
+ ++level )
+ {
+ GLsizei nBytes = (GLsizei)(resolution * (resolution >> 1)); // 为什么每一个mipmap存储的像素点个数是 resolution ** 2 / 2 ,不应该是resolution**2吗
+ // 此处将texture的数据压入到gl中,存储为gl_texture_2d_array的对象
+ glCompressedTexSubImage3D(
+ GL_TEXTURE_2D_ARRAY, // target texture. Must be GL_TEXTURE_3D or GL_TEXTURE_2D_ARRAY.
+ level, // level-of-detail number. Level 0 is the base image level. Level n is the nth mipmap reduction image.
+ 0, 0, (GLint)Texture_Ptr, // Texture_Ptr is the index of Current_loaded_texture
+ (GLsizei)resolution, (GLsizei)resolution, 1, // Specifies the width, height, depth of the texture subimage.
+ GL_COMPRESSED_RED_RGTC1, // 压缩数据的格式,这就是为什么只用了一半的 (nBytes) bytes 的数据表示了 resolution * resolution 的图片
+ nBytes, // the number of unsigned bytes of image data starting at the address specified by data.
+ texture // a pointer to the compressed image data in memory.
+ ); // 是否此处将texture给到 GL_TEXTURE_2D_ARRAY, check the doc on https://registry.khronos.org/OpenGL-Refpages/es3.0/html/glCompressedTexSubImage3D.xhtml
+ resolution >>= 1;
+ texture += nBytes;
+ }
-global_function
-s32
-RearrangeMap( // NOTE: VERY IMPORTANT
- u32 pixelFrom, // start of the fragment
- u32 pixelTo, // end of the fragment
- s32 delta, // movement of the distance
- u08 snap, // if true, the fragment will snap to the nearest contig
- bool update_contigs_flag // if true, update the contigs from the map state
- )
-{
+ printf("\r%3d/%3d (%1.2f%%) textures loaded from disk...", Texture_Ptr + 1, nTextures, 100.0 * (f64)((f32)(Texture_Ptr + 1) / (f32)((Number_of_Textures_1D >> 1) * (Number_of_Textures_1D + 1)))); // echo out 读取到了第Texture_Ptr个texture
+ fflush(stdout);
- u32 nPixels = Number_of_Pixels_1D;
+ AddTextureBufferToQueue(Texture_Buffer_Queue, (texture_buffer *)loadedTexture); // texture_buffer_queue 是全部的读取任务队列,读取后的buffer重新添加到队列中,供下一次读取。解决了从队列中弹出任务后任务队列空了的疑问。读取文件的任务队列在别的地方还会被调用吗?
+ FenceIn(Current_Loaded_Texture = 0); // 将临时变量置空,重新读取到current_loaded_texture后会跳出上面的循环
+ __atomic_fetch_add(&Texture_Ptr, 1, 0); // 更新全局的 texture_ptr
+ ptr ++ ;
+ }
+ }
- if (std::abs(delta) >= nPixels ||
- pixelFrom >= nPixels ||
- pixelTo >= nPixels)
- {
- fmt::print(
- stderr,
- "RearrangeMap: Invalid parameters: delta = {}, pixelFrom = {}, pixelTo = {}, nPixels = {}, file: {}, line: {}\n",
- delta, pixelFrom, pixelTo, nPixels,
- __FILE__, __LINE__
- );
- assert(0);
+ printf("\n");
+ CloseTextureBufferQueueFiles(Texture_Buffer_Queue); // 关闭所有的buffer_texture中的文件流指针file,并且释放解压器内存
+ delete[] packedTextureIndexes; // packedTextureIndexes 返回
+ glBindTexture(GL_TEXTURE_2D_ARRAY, 0); // 给之前已经压入的GL_TEXTURE_2D_ARRAY解除绑定
}
- if (pixelFrom > pixelTo) // Swap, make sure pixelFrom is less than pixelTo
- {
- std::swap(pixelFrom, pixelTo);
- }
- u32 nPixelsInRange = pixelTo - pixelFrom + 1;
-
- pixelFrom += nPixels;
- pixelTo += nPixels;
+
+ { // Define Contact Matrix Vertex Data (vao, vbo)
+ glUseProgram(Contact_Matrix->shaderProgram);
- auto GetRealBufferLocation = [nPixels] (u32 index)
- {
- u32 result;
+ // Contact_Matrix->vaos = PushArrayP(arena, GLuint, Number_of_Textures_1D * Number_of_Textures_1D); //
+ // Contact_Matrix->vbos = PushArrayP(arena, GLuint, Number_of_Textures_1D * Number_of_Textures_1D); //
+ Contact_Matrix->vaos = new GLuint[ Number_of_Textures_1D * Number_of_Textures_1D]; // (GLuint*) malloc(sizeof(GLuint) * Number_of_Textures_1D * Number_of_Textures_1D ); // TODO make sure the memory is freed before the re-allocation
+ Contact_Matrix->vbos = new GLuint[ Number_of_Textures_1D * Number_of_Textures_1D]; // (GLuint*) malloc(sizeof(GLuint) * Number_of_Textures_1D * Number_of_Textures_1D );
- Assert(index >= 0 && index < 3 * nPixels);
+ setContactMatrixVertexArray(Contact_Matrix, false, false); // set the vertex data of the contact matrix
- if (index >= (2 * nPixels))
- {
- result = index - (2 * nPixels);
- }
- else if (index >= nPixels)
- {
- result = index - nPixels;
- }
- else
- {
- result = index;
- }
+ }
- return(result);
- };
+ // Texture Pixel Lookups texture像素查找
+ {
+ GLuint pixStart, pixStartTex, pixRearrage, pixRearrageTex;
+
+ u32 nTex = (Number_of_Textures_1D + 1) * (Number_of_Textures_1D >> 1); // (32 + 1) * 32 / 2 = 528
+ u32 nPix1D = Number_of_Textures_1D * Texture_Resolution; // 32 * 1024
- u32 forward = delta > 0; // move direction
+ glActiveTexture(GL_TEXTURE2); // 调用 glActiveTexture 函数,可以选择当前活动的纹理单元,并且后续的纹理操作都会影响到该纹理单元
- if (snap) // can not put the selected frag into one frag.
- {
- if (forward) // move to the end
- {
- u32 target = GetRealBufferLocation(pixelTo + (u32)delta);
- u32 targetContigId = Map_State->contigIds[target] + (target == Number_of_Pixels_1D - 1 ? 1 : 0); // why is the last pixel +1?
- if (targetContigId) // only if the target is not the selected contig
- {
- contig *targetContig = Contigs->contigs_arr + targetContigId - 1;
-
- u32 targetCoord = IsContigInverted(targetContigId - 1) ? (targetContig->startCoord - targetContig->length + 1) : (targetContig->startCoord + targetContig->length - 1);
- while (delta > 0 &&
- (Map_State->contigIds[target] != targetContigId - 1 ||
- Map_State->contigRelCoords[target] != targetCoord))
- {
- --target;
- --delta;
- }
- }
- else
- {
- delta = 0;
- }
- }
- else // move to the start
+ u32 *pixStartLookup = PushArrayP(arena, u32, 2 * nTex); // 申请空间 2 * 528 个 u32
+ u32 ptr = 0;
+ for (u32 i = 0; i < Number_of_Textures_1D; i ++ ) // 遍历每一个texture
{
- u32 target = GetRealBufferLocation((u32)((s32)pixelFrom + delta));
- u32 targetContigId = Map_State->contigIds[target];
- if (targetContigId < (Contigs->numberOfContigs - 1)) // only if the target is not the selected contig
+ for (u32 j = i ; j < Number_of_Textures_1D; j ++ )
{
- contig *targetContig = Contigs->contigs_arr + (target ? targetContigId + 1 : 0);
- u32 targetCoord = targetContig->startCoord;
- while (delta < 0 && (Map_State->contigIds[target] != (target ? targetContigId + 1 : 0) || Map_State->contigRelCoords[target] != targetCoord))
- {
- ++target;
- ++delta;
- }
+ pixStartLookup[ptr++] = (u32)(j * Texture_Resolution); // 列 * 1024 双数索引是列,单数是行
+ pixStartLookup[ptr++] = (u32)(i * Texture_Resolution); // 行 * 1024
}
- else delta = 0;
}
- }
-
- if (delta)
- {
- u32 startCopyFromRange; // location start to copy
- u32 startCopyToRange; // location start to put the copied data
- if (forward) // move to the end
- {
- startCopyFromRange = pixelTo + 1;
- startCopyToRange = pixelFrom;
- }
- else // move to the start
- {
- startCopyFromRange = (u32)((s32)pixelFrom + delta);
- startCopyToRange = (u32)((s32)pixelTo + delta) + 1;
- }
+ glGenBuffers(1, &pixStart); // 生成一个缓冲区对象,并将其标识符存储到 pixStart 变量中。这样,pixStart 变量就可以用于引用这个生成的缓冲区对象
+ glBindBuffer(GL_TEXTURE_BUFFER, pixStart); // 缓冲区对象 pixStart 就会被绑定到当前的纹理缓冲区上,后续的操作会影响这个缓冲区对象
+ glBufferData(GL_TEXTURE_BUFFER, sizeof(u32) * 2 * nTex, pixStartLookup, GL_STATIC_DRAW); // 将数据从 pixStartLookup 指向的内存区域拷贝到绑定到 GL_TEXTURE_BUFFER 目标的缓冲区对象中,大小为 sizeof(u32) * 2 * nTex 字节,并且告诉 OpenGL 这些数据是静态的,不会频繁地变化
- u32 copySize = std::abs(delta);
+ glGenTextures(1, &pixStartTex); // 生成一个纹理对象,并将其标识符存储到 pixStartTex 变量中
+ glBindTexture(GL_TEXTURE_BUFFER, pixStartTex); // 纹理对象 pixStartTex 就会被绑定到当前的纹理缓冲区上,后续的纹理操作(比如使用 glTexBuffer 函数将其与纹理缓冲区对象关联)将会影响到这个纹理对象
+ glTexBuffer( // 纹理缓冲区对象与缓冲区对象关联的函数
+ GL_TEXTURE_BUFFER, // 要关联到缓冲区的纹理目标,这里是 GL_TEXTURE_BUFFER,表示纹理缓冲区。
+ GL_RG32UI, // 纹理缓冲区数据的格式, GL_RG32UI表示每个像素由两个u32组成,一个红色分量和一个绿色分量
+ pixStart); // 缓冲区对象的标识符,这个缓冲区会与纹理缓冲区关联
- u32 *tmpBuffer = new u32[copySize];
- u32 *tmpBuffer2 = new u32[copySize]; // original contig ids
- u32 *tmpBuffer3 = new u32[copySize]; // original contig coords
- u32 *tmpBuffer4 = new u32[copySize]; // scaff ids
- u64 *tmpBuffer5 = new u64[copySize]; // meta data flags
+ Contact_Matrix->pixelStartLookupBuffer = pixStart; // 缓冲区对象标识符
+ Contact_Matrix->pixelStartLookupBufferTex = pixStartTex; // 纹理对象标识符
- glBindBuffer(GL_TEXTURE_BUFFER, Contact_Matrix->pixelRearrangmentLookupBuffer); // pixel rearrange buffer
- u32 *buffer = (u32 *)glMapBufferRange(GL_TEXTURE_BUFFER, 0, nPixels * sizeof(u32), GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); // map the buffer
+ FreeLastPushP(arena); // pixStartLookup 释放存放像素点开始的空间
- if (buffer)
- {
- ForLoop(copySize) // copySize is abs(delta)
- {
- tmpBuffer[index] = buffer[GetRealBufferLocation(index + startCopyFromRange)]; // TODO understand how is the texture buffer data getting exchanged
- tmpBuffer2[index] = Map_State->originalContigIds[GetRealBufferLocation(index + startCopyFromRange)];
- tmpBuffer3[index] = Map_State->contigRelCoords[GetRealBufferLocation(index + startCopyFromRange)];
- tmpBuffer4[index] = Map_State->scaffIds[GetRealBufferLocation(index + startCopyFromRange)];
- tmpBuffer5[index] = Map_State->metaDataFlags[GetRealBufferLocation(index + startCopyFromRange)];
- }
-
- // copy the selected fragment to the new location
- if (forward) // move to the ends
- {
- ForLoop(nPixelsInRange) // (pixelTo - pixelFrom + 1)
- {
- buffer[GetRealBufferLocation(pixelTo + (u32)delta - index)] = buffer[GetRealBufferLocation(pixelTo - index)];
- Map_State->originalContigIds[GetRealBufferLocation(pixelTo + (u32)delta - index)] = Map_State->originalContigIds[GetRealBufferLocation(pixelTo - index)];
- Map_State->contigRelCoords[GetRealBufferLocation(pixelTo + (u32)delta - index)] = Map_State->contigRelCoords[GetRealBufferLocation(pixelTo - index)];
- Map_State->scaffIds[GetRealBufferLocation(pixelTo + (u32)delta - index)] = Map_State->scaffIds[GetRealBufferLocation(pixelTo - index)];
- Map_State->metaDataFlags[GetRealBufferLocation(pixelTo + (u32)delta - index)] = Map_State->metaDataFlags[GetRealBufferLocation(pixelTo - index)];
- }
- }
- else // move to the start
- {
- ForLoop(nPixelsInRange)
- {
- buffer[GetRealBufferLocation((u32)((s32)pixelFrom + delta) + index)] = buffer[GetRealBufferLocation(pixelFrom + index)];
- Map_State->originalContigIds[GetRealBufferLocation((u32)((s32)pixelFrom + delta) + index)] = Map_State->originalContigIds[GetRealBufferLocation(pixelFrom + index)];
- Map_State->contigRelCoords[GetRealBufferLocation((u32)((s32)pixelFrom + delta) + index)] = Map_State->contigRelCoords[GetRealBufferLocation(pixelFrom + index)];
- Map_State->scaffIds[GetRealBufferLocation((u32)((s32)pixelFrom + delta) + index)] = Map_State->scaffIds[GetRealBufferLocation(pixelFrom + index)];
- Map_State->metaDataFlags[GetRealBufferLocation((u32)((s32)pixelFrom + delta) + index)] = Map_State->metaDataFlags[GetRealBufferLocation(pixelFrom + index)];
- }
- }
+ glActiveTexture(GL_TEXTURE3); // 激活第三个texture,以下代码会影响第三个texture
- // copy the influenced fragment (delta) to the new location
- ForLoop(copySize)
- {
- buffer[GetRealBufferLocation(index + startCopyToRange)] = tmpBuffer[index];
- Map_State->originalContigIds[GetRealBufferLocation(index + startCopyToRange)] = tmpBuffer2[index];
- Map_State->contigRelCoords[GetRealBufferLocation(index + startCopyToRange)] = tmpBuffer3[index];
- Map_State->scaffIds[GetRealBufferLocation(index + startCopyToRange)] = tmpBuffer4[index];
- Map_State->metaDataFlags[GetRealBufferLocation(index + startCopyToRange)] = tmpBuffer5[index];
- }
- }
- else
+ u32 *pixRearrageLookup = PushArrayP(arena, u32, nPix1D); // allocte 1024 * 32 u32 memory
+ for (u32 i = 0 ; i < nPix1D; i ++ )
{
- fprintf(stderr, "Could not map pixel rearrange buffer\n");
+ pixRearrageLookup[i] = (u32)i; // assign the index to the pixRearrageLookup
}
- glUnmapBuffer(GL_TEXTURE_BUFFER);
- glBindBuffer(GL_TEXTURE_BUFFER, 0);
- delete[] tmpBuffer ;
- delete[] tmpBuffer2;
- delete[] tmpBuffer3;
- delete[] tmpBuffer4;
- delete[] tmpBuffer5;
- // FreeLastPush(Working_Set); // tmpBuffer
- // FreeLastPush(Working_Set); // tmpBuffer2
- // FreeLastPush(Working_Set); // tmpBuffer3
- // FreeLastPush(Working_Set); // tmpBuffer4
- // FreeLastPush(Working_Set); // tmpBuffer5
+ glGenBuffers(1, &pixRearrage); // generate a buffer object
+ glBindBuffer(GL_TEXTURE_BUFFER, pixRearrage); // bind as a texture buffer for the current buffer
+ glBufferData(GL_TEXTURE_BUFFER, sizeof(u32) * nPix1D, pixRearrageLookup, GL_DYNAMIC_DRAW); // copy the data from pixRearrageLookup to the buffer object, and tell OpenGL that the data is dynamic and will change frequently
+ glGenTextures(1, &pixRearrageTex);
+ glBindTexture(GL_TEXTURE_BUFFER, pixRearrageTex);
+ glTexBuffer(GL_TEXTURE_BUFFER, GL_R32UI, pixRearrage);
- if (update_contigs_flag) UpdateContigsFromMapState();
-
- map_edit edit;
- edit.finalPix1 = (u32)GetRealBufferLocation((u32)((s32)pixelFrom + delta));
- edit.finalPix2 = (u32)GetRealBufferLocation((u32)((s32)pixelTo + delta));
- edit.delta = (s32)delta;
- MoveWayPoints(&edit);
- }
+ Contact_Matrix->pixelRearrangmentLookupBuffer = pixRearrage; // 32 * 1024 u32, this is a ascending order of 0 to 1024 * 32
+ Contact_Matrix->pixelRearrangmentLookupBufferTex = pixRearrageTex; // texture 的索引
- return(delta);
-}
+ FreeLastPushP(arena); // free pixRearrageLookup as it has already been copied to the buffer object with index pixRearrage
+ glUniform1ui(glGetUniformLocation(Contact_Matrix->shaderProgram, "pixpertex"), Texture_Resolution); // 将1024传递给 pixpertex,每个texture有多少个像素点
+ glUniform1f(glGetUniformLocation(Contact_Matrix->shaderProgram, "oopixpertex"), 1.0f / (f32)Texture_Resolution); // 将 1 / 1024 传递给 oopixpertex
+ glUniform1ui(glGetUniformLocation(Contact_Matrix->shaderProgram, "ntex1dm1"), Number_of_Textures_1D - 1); // 将31传递给 ntex1dm1
+ glActiveTexture(GL_TEXTURE0); // 关闭激活的texture 3
+ }
-global_function
-void
-BreakMap(
- const u32& loc,
- const u32 ignore_len // cut点到开头或者结尾的长度不足ignore_len的contig不会被切断
-)
-{
- if (loc >= Number_of_Pixels_1D)
+ GLuint posAttribFlatShader = (GLuint)glGetAttribLocation(Flat_Shader->shaderProgram, "position");
+ u32 pad = 0;
+ auto PushGenericBuffer = [posAttribFlatShader, pad, arena] (quad_data **quadData, u32 numberOfBuffers)
{
- char buff[512];
- snprintf(buff, sizeof(buff), "[Pixel Cut] Error: loc (%d) should be smaller than number of pixels (%d)", loc, Number_of_Pixels_1D);
- MY_CHECK(buff);
- assert(0);
- }
- u32 original_contig_id = Map_State->originalContigIds[loc];
- u32 contig_id = Map_State->contigIds[loc];
- u32 contig_rel_coord = Map_State->contigRelCoords[loc];
+ (void)pad;
- s32 ptr_left = (s32)loc, ptr_right = (s32)loc;
- u08 inversed = IsContigInverted(contig_id);
- while ( // 从loc向左遍历,找到第一个不满足条件的像素点索引
- --ptr_left >= 0 &&
- Map_State->contigIds[ptr_left] == contig_id &&
- (Map_State->contigRelCoords[ptr_left] == Map_State->contigRelCoords[ptr_left+1]+ (inversed ? +1 : -1)) ) {};
- while ( // 从loc向右遍历,找到第一个不满足条件的像素点索引
- ++ptr_right < Number_of_Pixels_1D &&
- Map_State->contigIds[ptr_right] == contig_id &&
- (Map_State->contigRelCoords[ptr_right - 1] == Map_State->contigRelCoords[ptr_right]+ (inversed ? +1 : -1)) ) {};
-
- if ((loc - ptr_left) < ignore_len || (ptr_right - loc) < ignore_len )
- {
- fmt::print(
- "[Pixel Cut] Warning: original_contig_id {} current_contig_id {}, pixel range: [{}, cut({}), {}], left({}), right({}), smaller than ignore_len ({}), cut at loc: ({}) is ignored\n",
- original_contig_id%Max_Number_of_Contigs,
- contig_id,
- ptr_left,
- loc,
- ptr_right,
- loc - ptr_left,
- ptr_right - loc,
- ignore_len, loc);
- return;
- }
+ *quadData = PushStructP(arena, quad_data);
+
+ (*quadData)->vaos = PushArrayP(arena, GLuint, numberOfBuffers);
+ (*quadData)->vbos = PushArrayP(arena, GLuint, numberOfBuffers);
+ (*quadData)->nBuffers = numberOfBuffers;
- ptr_left++; ptr_right--;
+ glUseProgram(Flat_Shader->shaderProgram);
- // cut the contig by amending the original Contig Ids.
- for (u32 tmp = loc; tmp <= ptr_right; tmp++) // left side
- {
- if (Map_State->originalContigIds[tmp] > (std::numeric_limits::max() - Max_Number_of_Contigs))
+ ForLoop(numberOfBuffers)
{
- fmt::print("[Pixel Cut] originalContigIds[{}] + {} = {} is greater than the max number of contigs ({}), file: {}, line: {}\n", tmp,
- Max_Number_of_Contigs,
- (u64)Map_State->originalContigIds[tmp] + Max_Number_of_Contigs,
- std::numeric_limits::max(),
- __FILE__, __LINE__);
- assert(0);
- }
- Map_State->originalContigIds[tmp] += Max_Number_of_Contigs; // NOTE: the number can not exceed the max number 2**32 - 1 = 4294967295. However, it is not easy to exceed the max number of contigs, as 4294967295 / 4096 = 1048575.9997
- }
-
- fmt::print(
- "[Pixel Cut] Original contig_id ({}), current_id ({}), pixel range: [{}, {}] {} inversed, cut at {}\n",
- original_contig_id%Max_Number_of_Contigs,
- contig_id,
- ptr_left,
- ptr_right,
- inversed ? "(is)" : "(isn\'t)",
- loc );
-
- return ;
-
-}
+ glGenVertexArrays(1, (*quadData)->vaos + index);
+ glBindVertexArray((*quadData)->vaos[index]);
+ glGenBuffers(1, (*quadData)->vbos + index);
+ glBindBuffer(GL_ARRAY_BUFFER, (*quadData)->vbos[index]);
+ glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(vertex), NULL, GL_DYNAMIC_DRAW);
-global_function
-std::vector
-get_exclude_metaData_idx(const std::vector& exclude_tags)
-{
- if (exclude_tags.empty()) return std::vector();
+ glEnableVertexAttribArray(posAttribFlatShader);
+ glVertexAttribPointer(posAttribFlatShader, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), 0);
- std::vector exclude_frag_idx((u32) exclude_tags.size(), -1);
- for (u32 i=0; i < exclude_frag_idx.size(); i++)
- {
- for (u32 j=0; j < 64; j++)
- {
- if (!Meta_Data->tags[j]) break;
- auto tmp = std::string((char*)Meta_Data->tags[j]);
- std::transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
- if ( tmp == exclude_tags[i])
- {
- exclude_frag_idx[i] = j;
- break;
- }
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Quad_EBO);
}
- }
- return exclude_frag_idx;
-}
-
-
+ };
-void RedoAllEdits(map_editor* map_editor_)
-{
- while (map_editor_->nUndone) RedoMapEdit();
- return ;
-}
+ // Grid Data
+ {
+ PushGenericBuffer(&Grid_Data, 2 * (Max_Number_of_Contigs + 1));
+ }
+ // Label Box Data
+ {
+ PushGenericBuffer(&Label_Box_Data, 2 * Max_Number_of_Contigs);
+ }
-void EraseAllEdits(map_editor* map_editor_, u32 max_edit_recorded=Edits_Stack_Size)
-{
- u32 nEdits = my_Min(max_edit_recorded, map_editor_->nEdits);
- ForLoop(nEdits) UndoMapEdit();
- return ;
-}
+ //Scale Bar Data
+ {
+ PushGenericBuffer(&Scale_Bar_Data, 4 * (2 + MaxTicksPerScaleBar));
+ }
+ //Contig Colour Bars
+ {
+ PushGenericBuffer(&Contig_ColourBar_Data, Max_Number_of_Contigs);
+ }
-void run_ai_detection()
-{
- std::cout << "Running AI detection..." << std::endl;
- int status = std::system("/Users/sg35/miniconda3/envs/auto_cut/bin/python /Users/sg35/PretextView/python/autoCut/auto_cut.py");
+ //Scaff Bars
+ {
+ PushGenericBuffer(&Scaff_Bar_Data, Max_Number_of_Contigs);
+ }
- // 检查命令执行状态
- if (status == 0) {
- std::cout << "Command successful!" << std::endl;
- } else {
- std::cerr << "Command failed, code: " << status << std::endl;
+ // Extensions
+ {
+ push_extensions_to_opengl(arena, 0);
}
-}
-void cut_frags(const std::vector& problem_locs)
-{
- for (auto & i : problem_locs)
+#ifdef Internal
{
- // cut the fragment
- BreakMap(i, auto_curation_state.auto_cut_smallest_frag_size_in_pixel);
- UpdateContigsFromMapState();
+ PushGenericBuffer(&Texture_Tile_Grid, 2 * (Number_of_Textures_1D + 1));
+ PushGenericBuffer(&QuadTree_Data, 1 << (2 * (Waypoints_Quadtree_Levels + 1)));
}
- Redisplay = 1;
-}
+#endif
+
+ // Map Editor
+ {
+ Map_Editor = PushStructP(arena, map_editor);
+ Map_Editor->nEdits = 0;
+ Map_Editor->editStackPtr = 0;
+ Map_Editor->nUndone = 0;
+ Map_Editor->edits = PushArrayP(arena, map_edit, Edits_Stack_Size);
+ }
+
+ // Waypoint Editor
+ {
+ Waypoint_Editor = PushStructP(arena, waypoint_editor);
+ Waypoint_Editor->nWaypointsActive = 0;
+ Waypoint_Editor->freeWaypoints = {};
+ Waypoint_Editor->activeWaypoints = {};
+ Waypoint_Editor->freeWaypoints.next = PushArrayP(arena, waypoint, Waypoints_Stack_Size);
+ Waypoint_Editor->quadtree = PushQuadTree(arena);
+ Waypoint_Editor->freeNodes = {};
+ Waypoint_Editor->freeNodes.next = PushArrayP(arena, waypoint_quadtree_node, Waypoints_Stack_Size);
-void AutoCurationFromFragsOrder(
- const FragsOrder* frags_order_,
- contigs* contigs_,
- map_state* map_state_,
- SelectArea* select_area=nullptr)
-{
- u08 using_select_area = (select_area && select_area->select_flag)? 1 : 0;
- u32 num_frags = contigs_->numberOfContigs;
- if (!using_select_area )
- {
- if ( num_frags != frags_order_->get_num_frags())
+ Waypoint_Editor->freeWaypoints.next->prev = &Waypoint_Editor->freeWaypoints;
+ Waypoint_Editor->freeNodes.next->prev = &Waypoint_Editor->freeNodes;
+ ForLoop(Waypoints_Stack_Size - 1)
{
- fprintf(stderr, "Number of contigs(%d) and fragsOrder.num_frags(%d) do not match.\n", num_frags, frags_order_->get_num_frags());
- assert(0);
+ waypoint *wayp = Waypoint_Editor->freeWaypoints.next + index;
+ wayp->next = (wayp + 1);
+ (wayp + 1)->prev = wayp;
+ (wayp + 1)->next = 0;
+
+ waypoint_quadtree_node *node = Waypoint_Editor->freeNodes.next + index;
+ node->next = (node + 1);
+ (node + 1)->prev = node;
+ (node + 1)->next = 0;
}
}
- else
+
+ // 为添加的功能初始化指针
{
- if (select_area->get_to_sort_frags_num() != frags_order_->get_num_frags())
- {
- fmt::print(
- stderr,
- "num_to_sort_contigs({}) != fragsOrder.num_frags({}), file:{}, line:{}\n", select_area->get_to_sort_frags_num(),
- frags_order_->get_num_frags(),
- __FILE__, __LINE__);
- assert(0);
- }
- }
+ // 给pixel_density_extension分配内存
+ // pixel_density_extension = new Extension_Graph_Data(Number_of_Pixels_1D);
+
+ // 为 copy textures to cpu 分配内存
+ if (textures_array_ptr) delete textures_array_ptr;
+ textures_array_ptr = new TexturesArray4AI(
+ Number_of_Textures_1D,
+ Texture_Resolution,
+ *fileName,
+ Contigs
+ );
+ // prepare before reading textures
+ f32 original_color_control_points[3];
+ prepare_before_copy(original_color_control_points);
+ textures_array_ptr->copy_buffer_to_textures(
+ Contact_Matrix,
+ false // show_flag
+ );
+ restore_settings_after_copy(original_color_control_points);
- u32 num_autoCurated_edits=0;
+ // 为 Pixel Cut 存储的数据分配空间,初始化,并且将数据push到extension中
+ if (frag_cut_cal_ptr) delete frag_cut_cal_ptr;
+ frag_cut_cal_ptr = new FragCutCal(
+ textures_array_ptr,
+ Number_of_Pixels_1D,
+ auto_curation_state.auto_cut_diag_window_for_pixel_mean);
- // check the difference between the contigs, order and the new frags order
- u32 start_loc = 0;
- std::vector> current_order(num_frags); // [contig_id, contig_length]
- std::vector predicted_order = frags_order_->get_order_without_chromosomeInfor(); // start from 1
- if (using_select_area)
- {
- std::vector full_predicted_order(num_frags);
- std::iota(full_predicted_order.begin(), full_predicted_order.end(), 1);
- auto frags_id_to_sort = select_area->get_to_sort_frags_id(Contigs);
- for (u32 i=0; i< select_area->get_to_sort_frags_num(); i++)
- full_predicted_order[frags_id_to_sort[i]] = (predicted_order[i]>0?1:-1) * (select_area->get_first_frag_id() + std::abs(predicted_order[i]));
- predicted_order = full_predicted_order;
- }
- for (s32 i = 0; i < num_frags; ++i) current_order[i] = {i+1, contigs_->contigs_arr[i].length}; // start from 1
- auto move_current_order_element = [¤t_order, &num_frags](u32 from, u32 to)
- {
- if (from >= num_frags || to >= num_frags)
+ // clear mem for textures
+ textures_array_ptr->clear_textures();
+
+ // 添加数据到extensions
+ std::string graph_name = "pixel_discontinuity";
+ bool is_pix_density_added = Extensions.is_graph_name_exist(graph_name);
+ if (!is_pix_density_added) // 未添加pixel density
{
- fprintf(stderr, "Invalid from(%d) or to(%d), index should betwee [0, %d].\n", from, to, num_frags-1);
- return;
- }
- if (from == to) return;
- auto tmp = current_order[from];
- if (from > to)
- {
- for (u32 i = from; i > to; --i) current_order[i] = current_order[i-1];
+ u32 added_num = Extensions.get_num_extensions();
+ u32* graph_data = new u32[Number_of_Pixels_1D];
+ f32 max_desity = 0.f;
+ for (auto& i : frag_cut_cal_ptr->hic_pixel_density_origin) max_desity = std::max(max_desity, i);
+ for (u32 i=0; i < Number_of_Pixels_1D; i ++)
+ {
+ graph_data[i] = (u32)(255 * (1.001f- frag_cut_cal_ptr->hic_pixel_density_origin[i] / max_desity));
+ }
+ add_graph_to_extensions(arena, (u32*)graph_name.c_str(), graph_data);
+ delete[] graph_data;
+
+ push_extensions_to_opengl(arena, added_num, 0.05f); // push hic_pixel_density to opengl buffer
}
- else // to > from
+ else
{
- for (u32 i = from; i < to; ++i) current_order[i] = current_order[i+1];
- }
- current_order[to] = tmp;
- };
-
- // update the map state based on the new order
- for (u32 i = 0; i < num_frags; ++i)
- {
- if (predicted_order[i] == current_order[i].first) // leave the contig unchanged
- {
- start_loc += current_order[i].second;
- continue;
+ fmt::print("hic_pixel_density extension already exists\n");
+ assert(false);
}
+ }
- // only invert
- if (predicted_order[i] == -current_order[i].first)
- {
- u32 pixelFrom = start_loc, pixelEnd= start_loc + current_order[i].second - 1;
- InvertMap(pixelFrom, pixelEnd);
- AddMapEdit(0, {start_loc, start_loc + current_order[i].second - 1}, true);
- current_order[i].first = -current_order[i].first;
- start_loc += current_order[i].second;
- printf("[Pixel Sort] (#%d) Invert contig %d.\n", ++num_autoCurated_edits, predicted_order[i]);
- continue;
- }
- else if (
- predicted_order[i] != current_order[i].first &&
- predicted_order[i] != -current_order[i].first) // move the contig to the new position
- {
+ FenceIn(File_Loaded = 1);
- bool is_curated_inverted = predicted_order[i] < 0;
+ if (LoadState(*headerHash)) LoadState(*headerHash + 1);
+ return(ok);
+}
- // find the pixel range of the contig to move
- u32 pixelFrom = 0, tmp_i = 0; // tmp_i is the index of the current contig, which is going to be processed
- while (std::abs(predicted_order[i])!=std::abs(current_order[tmp_i].first))
+global_variable
+memory_arena *
+Loading_Arena;
+
+global_function
+void
+SetTheme(struct nk_context *ctx, enum theme theme)
+{
+ struct nk_color table[NK_COLOR_COUNT];
+ u32 themeSet = 1;
+
+ switch (theme)
+ {
+ case THEME_WHITE:
{
- if (tmp_i >= num_frags)
- {
- char buff[256];
- snprintf(buff, sizeof(buff), "Error: contig %d not found in the current order.\n", current_order[i].first);
- MY_CHECK(buff);
- assert(0);
- }
- pixelFrom += current_order[tmp_i].second; // length updated based on the current order
- if (pixelFrom>=Number_of_Pixels_1D)
- {
- char buff[256];
- snprintf(buff, sizeof(buff), "Error: pixelFrom(%d) >= Number_of_Pixels_1D(%d).\n", pixelFrom, Number_of_Pixels_1D);
- MY_CHECK(buff);
- assert(0);
- }
- ++tmp_i;
+ table[NK_COLOR_TEXT] = nk_rgba(70, 70, 70, 255);
+ table[NK_COLOR_WINDOW] = nk_rgba(175, 175, 175, 255);
+ table[NK_COLOR_HEADER] = nk_rgba(175, 175, 175, 255);
+ table[NK_COLOR_BORDER] = nk_rgba(0, 0, 0, 255);
+ table[NK_COLOR_BUTTON] = nk_rgba(185, 185, 185, 255);
+ table[NK_COLOR_BUTTON_HOVER] = nk_rgba(170, 170, 170, 255);
+ table[NK_COLOR_BUTTON_ACTIVE] = nk_rgba(160, 160, 160, 255);
+ table[NK_COLOR_TOGGLE] = nk_rgba(150, 150, 150, 255);
+ table[NK_COLOR_TOGGLE_HOVER] = nk_rgba(120, 120, 120, 255);
+ table[NK_COLOR_TOGGLE_CURSOR] = nk_rgba(175, 175, 175, 255);
+ table[NK_COLOR_SELECT] = nk_rgba(190, 190, 190, 255);
+ table[NK_COLOR_SELECT_ACTIVE] = nk_rgba(175, 175, 175, 255);
+ table[NK_COLOR_SLIDER] = nk_rgba(190, 190, 190, 255);
+ table[NK_COLOR_SLIDER_CURSOR] = nk_rgba(80, 80, 80, 255);
+ table[NK_COLOR_SLIDER_CURSOR_HOVER] = nk_rgba(70, 70, 70, 255);
+ table[NK_COLOR_SLIDER_CURSOR_ACTIVE] = nk_rgba(60, 60, 60, 255);
+ table[NK_COLOR_PROPERTY] = nk_rgba(175, 175, 175, 255);
+ table[NK_COLOR_EDIT] = nk_rgba(150, 150, 150, 255);
+ table[NK_COLOR_EDIT_CURSOR] = nk_rgba(0, 0, 0, 255);
+ table[NK_COLOR_COMBO] = nk_rgba(175, 175, 175, 255);
+ table[NK_COLOR_CHART] = nk_rgba(160, 160, 160, 255);
+ table[NK_COLOR_CHART_COLOR] = nk_rgba(45, 45, 45, 255);
+ table[NK_COLOR_CHART_COLOR_HIGHLIGHT] = nk_rgba( 255, 0, 0, 255);
+ table[NK_COLOR_SCROLLBAR] = nk_rgba(180, 180, 180, 255);
+ table[NK_COLOR_SCROLLBAR_CURSOR] = nk_rgba(140, 140, 140, 255);
+ table[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = nk_rgba(150, 150, 150, 255);
+ table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = nk_rgba(160, 160, 160, 255);
+ table[NK_COLOR_TAB_HEADER] = nk_rgba(180, 180, 180, 255);
}
- u32 pixelEnd = pixelFrom + current_order[tmp_i].second - 1;
- if (is_curated_inverted)
+ break;
+
+ case THEME_RED:
{
- InvertMap(pixelFrom, pixelEnd);
- current_order[tmp_i].first = -current_order[tmp_i].first;
+ table[NK_COLOR_TEXT] = nk_rgba(190, 190, 190, 255);
+ table[NK_COLOR_WINDOW] = nk_rgba(30, 33, 40, 215);
+ table[NK_COLOR_HEADER] = nk_rgba(181, 45, 69, 220);
+ table[NK_COLOR_BORDER] = nk_rgba(51, 55, 67, 255);
+ table[NK_COLOR_BUTTON] = nk_rgba(181, 45, 69, 255);
+ table[NK_COLOR_BUTTON_HOVER] = nk_rgba(190, 50, 70, 255);
+ table[NK_COLOR_BUTTON_ACTIVE] = nk_rgba(195, 55, 75, 255);
+ table[NK_COLOR_TOGGLE] = nk_rgba(51, 55, 67, 255);
+ table[NK_COLOR_TOGGLE_HOVER] = nk_rgba(45, 60, 60, 255);
+ table[NK_COLOR_TOGGLE_CURSOR] = nk_rgba(181, 45, 69, 255);
+ table[NK_COLOR_SELECT] = nk_rgba(51, 55, 67, 255);
+ table[NK_COLOR_SELECT_ACTIVE] = nk_rgba(181, 45, 69, 255);
+ table[NK_COLOR_SLIDER] = nk_rgba(51, 55, 67, 255);
+ table[NK_COLOR_SLIDER_CURSOR] = nk_rgba(181, 45, 69, 255);
+ table[NK_COLOR_SLIDER_CURSOR_HOVER] = nk_rgba(186, 50, 74, 255);
+ table[NK_COLOR_SLIDER_CURSOR_ACTIVE] = nk_rgba(191, 55, 79, 255);
+ table[NK_COLOR_PROPERTY] = nk_rgba(51, 55, 67, 255);
+ table[NK_COLOR_EDIT] = nk_rgba(51, 55, 67, 225);
+ table[NK_COLOR_EDIT_CURSOR] = nk_rgba(190, 190, 190, 255);
+ table[NK_COLOR_COMBO] = nk_rgba(51, 55, 67, 255);
+ table[NK_COLOR_CHART] = nk_rgba(51, 55, 67, 255);
+ table[NK_COLOR_CHART_COLOR] = nk_rgba(170, 40, 60, 255);
+ table[NK_COLOR_CHART_COLOR_HIGHLIGHT] = nk_rgba( 255, 0, 0, 255);
+ table[NK_COLOR_SCROLLBAR] = nk_rgba(30, 33, 40, 255);
+ table[NK_COLOR_SCROLLBAR_CURSOR] = nk_rgba(64, 84, 95, 255);
+ table[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = nk_rgba(70, 90, 100, 255);
+ table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = nk_rgba(75, 95, 105, 255);
+ table[NK_COLOR_TAB_HEADER] = nk_rgba(181, 45, 69, 220);
}
- s32 delta = start_loc - pixelFrom;
- RearrangeMap(pixelFrom, pixelEnd, delta);
- AddMapEdit(delta, {(u32)((s32)pixelFrom + delta), (u32)((s32)pixelEnd + delta)}, is_curated_inverted);
+ break;
- // update the current order, insert the contig to the new position
- move_current_order_element(tmp_i, i); // move element from tmp_i to i
- start_loc += current_order[i].second; // update start_loc after move fragments
- if (is_curated_inverted)
+ case THEME_BLUE:
{
- printf("[Pixel Sort] (#%d) Invert and Move contig %d to %d, start_loc:%d.\n", ++num_autoCurated_edits, predicted_order[i], i, start_loc);
+ table[NK_COLOR_TEXT] = nk_rgba(20, 20, 20, 255);
+ table[NK_COLOR_WINDOW] = nk_rgba(202, 212, 214, 215);
+ table[NK_COLOR_HEADER] = nk_rgba(137, 182, 224, 220);
+ table[NK_COLOR_BORDER] = nk_rgba(140, 159, 173, 255);
+ table[NK_COLOR_BUTTON] = nk_rgba(137, 182, 224, 255);
+ table[NK_COLOR_BUTTON_HOVER] = nk_rgba(142, 187, 229, 255);
+ table[NK_COLOR_BUTTON_ACTIVE] = nk_rgba(147, 192, 234, 255);
+ table[NK_COLOR_TOGGLE] = nk_rgba(177, 210, 210, 255);
+ table[NK_COLOR_TOGGLE_HOVER] = nk_rgba(182, 215, 215, 255);
+ table[NK_COLOR_TOGGLE_CURSOR] = nk_rgba(137, 182, 224, 255);
+ table[NK_COLOR_SELECT] = nk_rgba(177, 210, 210, 255);
+ table[NK_COLOR_SELECT_ACTIVE] = nk_rgba(137, 182, 224, 255);
+ table[NK_COLOR_SLIDER] = nk_rgba(177, 210, 210, 255);
+ table[NK_COLOR_SLIDER_CURSOR] = nk_rgba(137, 182, 224, 245);
+ table[NK_COLOR_SLIDER_CURSOR_HOVER] = nk_rgba(142, 188, 229, 255);
+ table[NK_COLOR_SLIDER_CURSOR_ACTIVE] = nk_rgba(147, 193, 234, 255);
+ table[NK_COLOR_PROPERTY] = nk_rgba(210, 210, 210, 255);
+ table[NK_COLOR_EDIT] = nk_rgba(210, 210, 210, 225);
+ table[NK_COLOR_EDIT_CURSOR] = nk_rgba(20, 20, 20, 255);
+ table[NK_COLOR_COMBO] = nk_rgba(210, 210, 210, 255);
+ table[NK_COLOR_CHART] = nk_rgba(210, 210, 210, 255);
+ table[NK_COLOR_CHART_COLOR] = nk_rgba(137, 182, 224, 255);
+ table[NK_COLOR_CHART_COLOR_HIGHLIGHT] = nk_rgba( 255, 0, 0, 255);
+ table[NK_COLOR_SCROLLBAR] = nk_rgba(190, 200, 200, 255);
+ table[NK_COLOR_SCROLLBAR_CURSOR] = nk_rgba(64, 84, 95, 255);
+ table[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = nk_rgba(70, 90, 100, 255);
+ table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = nk_rgba(75, 95, 105, 255);
+ table[NK_COLOR_TAB_HEADER] = nk_rgba(156, 193, 220, 255);
}
- else printf("[Pixel Sort] (#%d) Move contig %d to %d, start_loc:%d.\n", ++num_autoCurated_edits, predicted_order[i], i, start_loc);
- continue;
- }
- else
- {
- fprintf(stderr, "Unknown error, predicted_order[%d] = %d, current[%d] = %d.\n", i, predicted_order[i], i, current_order[i].first);
- continue;
- }
+ break;
+
+ case THEME_DARK:
+ {
+ table[NK_COLOR_TEXT] = nk_rgba(210, 210, 210, 255);
+ table[NK_COLOR_WINDOW] = nk_rgba(57, 67, 71, 215);
+ table[NK_COLOR_HEADER] = nk_rgba(51, 51, 56, 220);
+ table[NK_COLOR_BORDER] = nk_rgba(46, 46, 46, 255);
+ table[NK_COLOR_BUTTON] = nk_rgba(48, 83, 111, 255);
+ table[NK_COLOR_BUTTON_HOVER] = nk_rgba(58, 93, 121, 255);
+ table[NK_COLOR_BUTTON_ACTIVE] = nk_rgba(63, 98, 126, 255);
+ table[NK_COLOR_TOGGLE] = nk_rgba(50, 58, 61, 255);
+ table[NK_COLOR_TOGGLE_HOVER] = nk_rgba(45, 53, 56, 255);
+ table[NK_COLOR_TOGGLE_CURSOR] = nk_rgba(48, 83, 111, 255);
+ table[NK_COLOR_SELECT] = nk_rgba(57, 67, 61, 255);
+ table[NK_COLOR_SELECT_ACTIVE] = nk_rgba(48, 83, 111, 255);
+ table[NK_COLOR_SLIDER] = nk_rgba(50, 58, 61, 255);
+ table[NK_COLOR_SLIDER_CURSOR] = nk_rgba(48, 83, 111, 245);
+ table[NK_COLOR_SLIDER_CURSOR_HOVER] = nk_rgba(53, 88, 116, 255);
+ table[NK_COLOR_SLIDER_CURSOR_ACTIVE] = nk_rgba(58, 93, 121, 255);
+ table[NK_COLOR_PROPERTY] = nk_rgba(50, 58, 61, 255);
+ table[NK_COLOR_EDIT] = nk_rgba(50, 58, 61, 225);
+ table[NK_COLOR_EDIT_CURSOR] = nk_rgba(210, 210, 210, 255);
+ table[NK_COLOR_COMBO] = nk_rgba(50, 58, 61, 255);
+ table[NK_COLOR_CHART] = nk_rgba(50, 58, 61, 255);
+ table[NK_COLOR_CHART_COLOR] = nk_rgba(48, 83, 111, 255);
+ table[NK_COLOR_CHART_COLOR_HIGHLIGHT] = nk_rgba(255, 0, 0, 255);
+ table[NK_COLOR_SCROLLBAR] = nk_rgba(50, 58, 61, 255);
+ table[NK_COLOR_SCROLLBAR_CURSOR] = nk_rgba(48, 83, 111, 255);
+ table[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = nk_rgba(53, 88, 116, 255);
+ table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = nk_rgba(58, 93, 121, 255);
+ table[NK_COLOR_TAB_HEADER] = nk_rgba(48, 83, 111, 255);
+ }
+ break;
+
+ case THEME_BLACK:
+ case THEME_COUNT:
+ themeSet = 0;
}
- printf("[Pixel Sort] finished with %d edits\n", num_autoCurated_edits);
- return ;
+ if (themeSet) nk_style_from_table(ctx, table, Screen_Scale.x, Screen_Scale.y);
+ else nk_style_default(ctx, Screen_Scale.x, Screen_Scale.y);
+
+ Theme_Colour = table[NK_COLOR_BUTTON_ACTIVE];
+
+ NK_Context->style.slider.show_buttons = nk_true;
+
+ Current_Theme = theme;
}
+
global_function
void
-auto_cut_func(
- char * currFileName,
- memory_arena* arena = nullptr,
- std::string file_save_name = std::string("/auto_curation_tmp")
-)
-{
- if (!currFileName || !auto_cut_state) return;
-
- if (auto_cut_state == 2) // restore the cutted frags within the selected area
- {
- u32 start = auto_curation_state.get_start();
- u32 end = auto_curation_state.get_end();
- if (start < 0 || end < 0)
- {
- fmt::print(
- stdout,
- "Error: no area selected. start({}) or end({}) is less than 0\n",
- start, end);
- return ;
- }
- fmt::print(stdout, "[Pixel cut] restoring the cutted frags within the selected area: [{}, {}]\n", start, end);
- Map_State->restore_cutted_contigs( start, end );
- UpdateContigsFromMapState();
- Redisplay = 1;
- return ;
+Setup()
+{
+ Decompressor = libdeflate_alloc_decompressor();
+ if (!Decompressor)
+ {
+ fprintf(stderr, "Could not allocate decompressor\n");
+ exit(1);
}
- // classic cut
- {
- SelectArea selected_area;
- auto_curation_state.get_selected_fragments(
- selected_area,
- Map_State,
- Number_of_Pixels_1D,
- Contigs);
- glBindBuffer(GL_TEXTURE_BUFFER, Contact_Matrix->pixelRearrangmentLookupBuffer);
- const u32 *pixel_rearrange_index = (const u32 *)glMapBufferRange(GL_TEXTURE_BUFFER, 0, Number_of_Pixels_1D * sizeof(u32), GL_MAP_READ_BIT);
- std::vector cut_locs_pixel = frag_cut_cal_ptr->get_cut_locs_pixel(
- auto_curation_state,
- pixel_rearrange_index, // pixel_rearrangement_buffer
- Contigs,
- &selected_area
- );
- glUnmapBuffer(GL_TEXTURE_BUFFER);
-
- fmt::print(stdout, "[Pixel cut] cut locs in pixel: [");
- for (auto & i : cut_locs_pixel) fmt::print(stdout, "{} ", i);
- fmt::print(stdout, "]\n");
-
- // cut the contigs
- cut_frags(cut_locs_pixel);
+ Compressor = libdeflate_alloc_compressor(12);
+ if (!Compressor)
+ {
+ fprintf(stderr, "Could not allocate compressor\n");
+ exit(1);
}
- // generate figures
- if (0)
- {
- fprintf(stdout, "[Pixel cut] generating hic figures...\n");
- Hic_Figure hic_figure(
- Total_Genome_Length,
- file_save_name,
- textures_array_ptr );
- hic_figure.generate_hic_figures();
-
- // run ai model with python script
- run_ai_detection();
-
- // restore the error info via reading the error json
- HIC_Problems hic_problems("/auto_curation_tmp/auto_cut_output/infer_result/infer_result.json", (f32) Total_Genome_Length / (f32)Number_of_Pixels_1D );
- std::vector> problem_loc = hic_problems.get_problem_loci();
- }
-
-
- // cut the contigs
- // cut_frags();
-
- return ;
-}
-
-
-global_function
-void
-auto_sort_func(char* currFileName)
-{
- if (!currFileName || !auto_sort_state) return;
-
- fprintf(stdout, "========================\n");
- fprintf(stdout, "[Pixel Sort] start...\n");
- fprintf(stdout, "[Pixel Sort] smallest_frag_size_in_pixel: %d\n", auto_curation_state.smallest_frag_size_in_pixel);
- fprintf(stdout, "[Pixel Sort] link_score_threshold: %.3f\n", auto_curation_state.link_score_threshold);
- fprintf(stdout, "[Pixel Sort] Sort mode: %s\n", auto_curation_state.get_sort_mode_name().c_str());
+ Texture_Buffer_Queue = PushStruct(Working_Set, texture_buffer_queue);
- // compress the HiC data
- // prepare before reading textures
- f32 original_color_control_points[3];
- prepare_before_copy(original_color_control_points);
- textures_array_ptr->copy_buffer_to_textures_dynamic(Contact_Matrix, false);
- restore_settings_after_copy(original_color_control_points);
- // check if select the area for sorting
- SelectArea selected_area;
- auto_curation_state.get_selected_fragments(
- selected_area,
- Map_State,
- Number_of_Pixels_1D,
- Contigs
- );
- if (auto_curation_state.get_start() >=0 && auto_curation_state.get_end() >= 0 && selected_area.selected_frag_ids.size() > 0)
- {
- fprintf(stdout, "[Pixel Sort] Using selected area for sorting:\n");
- fprintf(stdout, "[Pixel Sort] Selected pixel range: %d ~ %d\n", auto_curation_state.get_start(), auto_curation_state.get_end());
- std::stringstream ss;
- ss << selected_area.selected_frag_ids[0];
- for (u32 i = 1; i < selected_area.selected_frag_ids.size(); ++i) ss << ", " << selected_area.selected_frag_ids[i];
- fmt::print(stdout, "[Pixel Sort] Selected fragments ({}): {}\n\n", selected_area.selected_frag_ids.size(), ss.str().c_str());
- selected_area.select_flag = true;
- selected_area.start_pixel = auto_curation_state.get_start();
- selected_area.end_pixel = auto_curation_state.get_end();
+ Meta_Data = PushStruct(Working_Set, meta_data);
+ memset(Meta_Data, 0, sizeof(meta_data));
+ MetaData_Active_Tag = 0;
+ ForLoop(ArrayCount(Default_Tags)) strcpy((char *)Meta_Data->tags[MetaData_Active_Tag + index], Default_Tags[index]);
+ if (Grey_Out_Settings)
+ {
+ delete Grey_Out_Settings;
+ Grey_Out_Settings = nullptr;
+ }
+ Grey_Out_Settings = new GreyOutSettings(Meta_Data);
+ if (user_profile_settings_ptr)
+ {
+ delete user_profile_settings_ptr;
+ user_profile_settings_ptr = nullptr;
}
+ user_profile_settings_ptr = new UserProfileSettings();
- textures_array_ptr->cal_compressed_hic(
- Contigs,
- Extensions,
- false,
- false,
- &selected_area
- );
- FragsOrder frags_order(textures_array_ptr->get_num_frags()); // intilize the frags_order with the number of fragments including the filtered out ones
- // exclude the fragments with first two tags during the auto curation
- std::vector exclude_tags = {"haplotig", "unloc"};
- std::vector exclude_meta_tag_idx = get_exclude_metaData_idx(exclude_tags);
- LikelihoodTable likelihood_table(
- textures_array_ptr->get_frags(),
- textures_array_ptr->get_compressed_hic(),
- (f32)auto_curation_state.smallest_frag_size_in_pixel / ((f32)Number_of_Pixels_1D + 1.f),
- exclude_meta_tag_idx,
- Number_of_Pixels_1D);
-
- #ifdef DEBUG_OUTPUT_LIKELIHOOD_TABLE
- likelihood_table.output_fragsInfo_likelihoodTable("frags_info_likelihood_table.txt", textures_array_ptr->get_compressed_hic());
- #endif // DEBUG_OUTPUT_LIKELIHOOD_TABLE
+ // Contig Name Label UI
+ {
+ Contig_Name_Labels = PushStruct(Working_Set, ui_colour_element_bg);
+ Contig_Name_Labels->on = 0;
+ Contig_Name_Labels->fg = Yellow_Text_Float;
+ Contig_Name_Labels->bg = Grey_Background;
+#define DefaultNameLabelTextSize 32.0f
+ Contig_Name_Labels->size = DefaultNameLabelTextSize;
+ }
- // clear mem for textures and compressed hic
- textures_array_ptr->clear_textures();
- textures_array_ptr->clear_compressed_hic();
+ // Scale Bar UI
+ {
+ Scale_Bars = PushStruct(Working_Set, ui_colour_element_bg);
+ Scale_Bars->on = 0;
+ Scale_Bars->fg = Red_Text_Float;
+ Scale_Bars->bg = Grey_Background;
+#define DefaultScaleBarSize 20.0f
+ Scale_Bars->size = DefaultScaleBarSize;
+ }
+
+ // Grid UI
+ {
+ Grid = PushStruct(Working_Set, ui_colour_element);
+ Grid->on = 1;
+ Grid->bg = Grey_Background;
+#define DefaultGridSize 0.00025f
+ Grid->size = DefaultGridSize;
+ }
- // use the compressed_hic to calculate the frags_order directly
- if (auto_curation_state.sort_mode == 0 || !selected_area.select_flag) // sort with union find if sorting the whole genome
+ // Contig Ids UI
{
- frag_sort_method->sort_according_likelihood_unionFind(
- likelihood_table,
- frags_order,
- selected_area,
- auto_curation_state.link_score_threshold,
- textures_array_ptr->get_frags());
+ Contig_Ids = PushStruct(Working_Set, ui_colour_element);
+ Contig_Ids->on = 1;
+#define DefaultContigIdSize (DefaultGridSize * 3.0f)
+ Contig_Ids->size = DefaultContigIdSize;
}
- else if (auto_curation_state.sort_mode == 1)
+
+ // Tool Tip UI
{
- frag_sort_method->sort_according_likelihood_unionFind_doFuse(
- likelihood_table,
- frags_order,
- selected_area,
- auto_curation_state.link_score_threshold,
- textures_array_ptr->get_frags(), true, true);
+ Tool_Tip = PushStruct(Working_Set, ui_colour_element_bg);
+ Tool_Tip->on = 1;
+ Tool_Tip->fg = Yellow_Text_Float;
+ Tool_Tip->bg = Grey_Background;
+#define DefaultToolTipTextSize 20.0f
+ Tool_Tip->size = DefaultToolTipTextSize;
}
- else if (auto_curation_state.sort_mode == 2)
+
+ // Edit Mode Colours
{
- frag_sort_method->sort_according_likelihood_unionFind_doFuse(
- likelihood_table,
- frags_order,
- selected_area,
- auto_curation_state.link_score_threshold,
- textures_array_ptr->get_frags(), false, true);
+ Edit_Mode_Colours = PushStruct(Working_Set, edit_mode_colours);
+ Edit_Mode_Colours->preSelect = Green_Float;
+ Edit_Mode_Colours->select = Blue_Float;
+ Edit_Mode_Colours->invSelect = Red_Float;
+ Edit_Mode_Colours->fg = Yellow_Text_Float;
+ Edit_Mode_Colours->bg = Grey_Background;
}
- else if (auto_curation_state.sort_mode == 3) // not finished yet
+
+ // Waypoint Mode Colours
{
- frag_sort_method->sort_according_yahs(
- likelihood_table,
- frags_order,
- selected_area,
- auto_curation_state.link_score_threshold,
- textures_array_ptr->get_frags()
- );
+ Waypoint_Mode_Data = PushStruct(Working_Set, waypoint_mode_data);
+ Waypoint_Mode_Data->base = Red_Full;
+ Waypoint_Mode_Data->selected = Blue_Full;
+ Waypoint_Mode_Data->text = Yellow_Text_Float;
+ Waypoint_Mode_Data->bg = Grey_Background;
+ Waypoint_Mode_Data->size = DefaultWaypointSize;
}
- else
+
+ // Scaff Mode Colours
{
- fprintf(stderr, "[Pixel Sort] Error: Unknown sort mode (%d)\n", auto_curation_state.sort_mode);
- assert(0);
+ Scaff_Mode_Data = PushStruct(Working_Set, meta_mode_data);
+ Scaff_Mode_Data->text = Yellow_Text_Float;
+ Scaff_Mode_Data->bg = Grey_Background;
+ Scaff_Mode_Data->size = DefaultScaffSize;
}
- AutoCurationFromFragsOrder(
- &frags_order,
- Contigs,
- Map_State,
- &selected_area);
- std::cout << std::endl;
- auto_sort_state = 0;
- return;
-}
+ // Meta Mode Colours
+ {
+ MetaData_Mode_Data = PushStruct(Working_Set, meta_mode_data);
+ MetaData_Mode_Data->text = Yellow_Text_Float;
+ MetaData_Mode_Data->bg = Grey_Background;
+ MetaData_Mode_Data->size = DefaultMetaDataSize;
+ }
+ // Extension Mode Colours
+ {
+ Extension_Mode_Data = PushStruct(Working_Set, meta_mode_data);
+ Extension_Mode_Data->text = Yellow_Text_Float;
+ Extension_Mode_Data->bg = Grey_Background;
+ Extension_Mode_Data->size = DefaultExtensionSize;
+ }
-// set the vertex array for the contact matrix
-// copy_flag: if true, set vaos to [-1, 1, -1, 1] for copying tiles from opengl buffer to cpu memory
-global_function
-void setContactMatrixVertexArray(
- contact_matrix* Contact_Matrix_,
- bool copy_flag,
- bool regenerate_flag)
-{
- glUseProgram(Contact_Matrix_->shaderProgram);
- GLuint posAttrib = (GLuint)glGetAttribLocation(Contact_Matrix_->shaderProgram, "position");
- GLuint texAttrib = (GLuint)glGetAttribLocation(Contact_Matrix_->shaderProgram, "texcoord");
-
- /*
- 从左上到右下开始遍历,见上述编号
- */
- f32 x = -0.5f;
- f32 y = 0.5f;
- f32 quadSize = 1.0f / (f32)Number_of_Textures_1D; // 1.0 / 32.f = 0.03125
- f32 allCornerCoords[2][2] = {{0.0f, 1.0f}, {1.0f, 0.0f}};
+#ifdef Internal
+ {
+ Tiles = PushStruct(Working_Set, ui_colour_element);
+ Tiles->on = 1;
+ Tiles->bg = {0.0f, 1.0f, 1.0f, 1.0f};
- if (regenerate_flag) // first delete the generated vertex array objects and buffers
- {
- glDeleteVertexArrays((GLsizei)(Number_of_Textures_1D * Number_of_Textures_1D), Contact_Matrix->vaos);
- glDeleteBuffers((GLsizei)(Number_of_Textures_1D * Number_of_Textures_1D), Contact_Matrix->vbos);
+ QuadTrees = PushStruct(Working_Set, ui_colour_element);
+ QuadTrees->on = 1;
+ QuadTrees->bg = {0.0f, 1.0f, 0.0f, 1.0f};
}
-
- u32 ptr = 0;
- ForLoop(Number_of_Textures_1D)
+#endif
+
+ // Contact Matrix Shader
{
- ForLoop2(Number_of_Textures_1D)
- {
- tex_vertex textureVertices[4];
+ Contact_Matrix = PushStruct(Working_Set, contact_matrix);
+ Contact_Matrix->shaderProgram = CreateShader(FragmentSource_Texture.c_str(), VertexSource_Texture.c_str());
- glGenVertexArrays( // 生成对象的名称,
- 1, // 生成的个数
- Contact_Matrix_->vaos + ptr); // 存储位置的指针
- glBindVertexArray(Contact_Matrix_->vaos[ptr]); // 绑定顶点名称
+ glUseProgram(Contact_Matrix->shaderProgram);
+ glBindFragDataLocation(Contact_Matrix->shaderProgram, 0, "outColor");
- f32 *cornerCoords = allCornerCoords[index2 >= index ? 0 : 1]; // 包含对角线的上三角的时候取第一行{0, 1},否则取第二行{1, 0} 为了解决关于对角线对称
-
- u32 min = my_Min(index, index2);
- u32 max = my_Max(index, index2);
- /*
- 对称性编号
- [[ 0 1 2 3 4 5 6 7 8 9]
- [ 1 10 11 12 13 14 15 16 17 18]
- [ 2 11 19 20 21 22 23 24 25 26]
- [ 3 12 20 27 28 29 30 31 32 33]
- [ 4 13 21 28 34 35 36 37 38 39]
- [ 5 14 22 29 35 40 41 42 43 44]
- [ 6 15 23 30 36 41 45 46 47 48]
- [ 7 16 24 31 37 42 46 49 50 51]
- [ 8 17 25 32 38 43 47 50 52 53]
- [ 9 18 26 33 39 44 48 51 53 54]]
- */
- f32 texture_index_symmetric = (f32)((min * (Number_of_Textures_1D - 1))
- - (((min-1) * min) >> 1 )
- + max) ;
-
- /*
- 3 2
- 0 1
- */
- f32 half_len = 1.0f;
- textureVertices[0].x = !copy_flag? x : -half_len; // x -> [-0.5, 0.5]
- textureVertices[0].y = !copy_flag? y - quadSize : -half_len; // y -> [-0.5, 0.5]
- textureVertices[0].s = !copy_flag? cornerCoords[0] : 0.f; // s表示texture的水平分量
- textureVertices[0].t = !copy_flag? cornerCoords[1] : 0.f; // t表示texture的垂直分量
- textureVertices[0].u = texture_index_symmetric;
+ Contact_Matrix->matLocation = glGetUniformLocation(Contact_Matrix->shaderProgram, "matrix");
+ glUniform1i(glGetUniformLocation(Contact_Matrix->shaderProgram, "tex"), 0);
+ glUniform1i(glGetUniformLocation(Contact_Matrix->shaderProgram, "colormap"), 1);
+ glUniform1i(glGetUniformLocation(Contact_Matrix->shaderProgram, "pixstartlookup"), 2);
+ glUniform1i(glGetUniformLocation(Contact_Matrix->shaderProgram, "pixrearrangelookup"), 3);
- textureVertices[1].x = !copy_flag? x + quadSize : half_len;
- textureVertices[1].y = !copy_flag? y - quadSize : -half_len;
- textureVertices[1].s = !copy_flag? 1.0f : 1.f;
- textureVertices[1].t = !copy_flag? 1.0f : 0.f;
- textureVertices[1].u = texture_index_symmetric;
+ glActiveTexture(GL_TEXTURE1);
- textureVertices[2].x = !copy_flag? x + quadSize : half_len;
- textureVertices[2].y = !copy_flag? y : half_len;
- textureVertices[2].s = !copy_flag? cornerCoords[1] : 1.f;
- textureVertices[2].t = !copy_flag? cornerCoords[0] : 1.f;
- textureVertices[2].u = texture_index_symmetric;
-
- textureVertices[3].x = !copy_flag? x : -half_len;
- textureVertices[3].y = !copy_flag? y : half_len;
- textureVertices[3].s = !copy_flag? 0.0f : 0.f;
- textureVertices[3].t = !copy_flag? 0.0f : 1.f;
- textureVertices[3].u = texture_index_symmetric;
+ Color_Maps = PushStruct(Working_Set, color_maps);
+ u32 nMaps = Number_of_Color_Maps;
+ Color_Maps->maps = PushArray(Working_Set, GLuint, nMaps);
+ Color_Maps->mapPreviews = PushArray(Working_Set, struct nk_image, nMaps);
+ Color_Maps->nMaps = nMaps;
+ Color_Maps->currMap = 1;
- glGenBuffers( // 生成buffer的名字 存储在contact_matrix->vbos+ptr 对应的地址上
- 1, // 个数
- Contact_Matrix_->vbos + ptr); // 指针,存储生成的名字
- glBindBuffer( // 绑定到一个已经命名的buffer对象上
- GL_ARRAY_BUFFER, // 绑定的对象,gl_array_buffer 一般是绑定顶点的信息
- Contact_Matrix_->vbos[ptr]); // 通过输入buffer的名字将其绑定到gl_array_buffer
- glBufferData( // 创建、初始化存储数据的buffer
- GL_ARRAY_BUFFER, // 绑定的对象,gl_array_buffer 一般是绑定顶点的信息
- 4 * sizeof(tex_vertex), // 对象的大小(bytes)
- textureVertices, // 即将绑定到gl_array_buffer的数据的指针
- GL_STATIC_DRAW); // 绑定后的数据是用于干什么的
-
- // tell GL how to interpret the data in the GL_ARRAY_BUFFER
- glEnableVertexAttribArray(posAttrib);
- glVertexAttribPointer( // 定义一个数组存储所有的通用顶点属性
- posAttrib, // 即将修改属性的索引
- 2, // 定义每个属性的参数的个数, 只能为1 2 3 4中的一个,初始值为4
- GL_FLOAT, // 定义该属性的数据类型,则数据为4个字节, 占用两个的话,则一共为8字节
- GL_FALSE, // normalized, 是否要在取用的时候规范化这些数
- sizeof(tex_vertex), // stride 定义从一个信息的指针下一个信息指针的bytes的间隔, 一个信息包到下一个信息包的长度
- 0); // const void* 指定当前与 GL_ARRAY_BUFFER 绑定的缓冲区数据头指针偏移多少个到 第一个通用顶点属性的第一个特征开始的位置。 初始值为 0。因为此处想要读取的信息为 x 和 y
- glEnableVertexAttribArray(texAttrib); //
- glVertexAttribPointer(
- texAttrib,
- 3,
- GL_FLOAT, // 定义每个属性的数据类型
- GL_FALSE, // GL_FALSE, GL_TRUE
- sizeof(tex_vertex),
- (void *)(3 * sizeof(GLfloat))); // 偏移量为3,因为前三个为x, y and pad, 想要读取的数据为 s, t and u
+ ForLoop(nMaps)
+ {
+ u32 mapPreviewImage[256];
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Quad_EBO);
+ GLuint tbo, tboTex, texPreview;
- x += quadSize; // next column
- ++ptr; // ptr for current texture
- }
+ glGenBuffers(1, &tbo);
+ glBindBuffer(GL_TEXTURE_BUFFER, tbo);
+ glBufferData(GL_TEXTURE_BUFFER, sizeof(Color_Map_Data[index]), Color_Map_Data[index], GL_STATIC_DRAW);
- y -= quadSize; // next row
- x = -0.5f; // from column 0
- }
-}
+ glGenTextures(1, &tboTex);
+ glBindTexture(GL_TEXTURE_BUFFER, tboTex);
+ glTexBuffer(GL_TEXTURE_BUFFER, GL_RGB32F, tbo);
+ Color_Maps->maps[index] = tboTex;
-global_function
-void
-prepare_before_copy(f32 *original_color_control_points)
-{
- // prepare before reading textures
- glActiveTexture(GL_TEXTURE1);
+ glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_BUFFER, Color_Maps->maps[Color_Maps->nMaps-1]); // 绑定到颜色映射的最后一个颜色
- glActiveTexture(GL_TEXTURE0);
- for (u32 i = 0; i < 3 ; i ++ )
- original_color_control_points[i] = Color_Maps->controlPoints[i];
- Color_Maps->controlPoints[0] = 0.0f;
- Color_Maps->controlPoints[1] = 0.5f;
- Color_Maps->controlPoints[2] = 1.0f;
- glUseProgram(Contact_Matrix->shaderProgram);
- glUniform3fv( Color_Maps->cpLocation, 1, Color_Maps->controlPoints);
- setContactMatrixVertexArray(Contact_Matrix, true, true); // set the vertex for copying
- return ;
-}
+ ForLoop2(256) //TODO SIMD
+ {
+ mapPreviewImage[index2] = ((u32)(Color_Map_Data[index][3 * index2] * 255.0f)) |
+ (((u32)(Color_Map_Data[index][(3 * index2) + 1] * 255.0f)) << 8) |
+ (((u32)(Color_Map_Data[index][(3 * index2) + 2] * 255.0f)) << 16) |
+ 0xff000000;
+ }
+ glGenTextures(1, &texPreview);
+ glBindTexture(GL_TEXTURE_2D, texPreview);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, mapPreviewImage);
+ glGenerateMipmap(GL_TEXTURE_2D);
+ Color_Maps->mapPreviews[index] = nk_image_id((s32)texPreview);
-global_function
-void
-restore_settings_after_copy(const f32 *original_color_control_points)
-{
- // restore settings
- setContactMatrixVertexArray(Contact_Matrix, false, true); // restore the vertex array for rendering
- for (u32 i = 0 ; i < 3 ; i ++ )
- Color_Maps->controlPoints[i] = original_color_control_points[i];
- glUseProgram(Contact_Matrix->shaderProgram);
- glUniform3fv( Color_Maps->cpLocation, 1, Color_Maps->controlPoints);
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_BUFFER, Color_Maps->maps[Color_Maps->currMap]);
- glActiveTexture(GL_TEXTURE0);
-}
+ glActiveTexture(GL_TEXTURE1);
+ }
+ NextColorMap(-1);
+ glActiveTexture(GL_TEXTURE0);
-global_function void
-JumpToDiagonal(GLFWwindow *window)
-{
- Camera_Position.x = -Camera_Position.y;
- ClampCamera();
- Redisplay = 1;
-}
+ Color_Maps->cpLocation = glGetUniformLocation(Contact_Matrix->shaderProgram, "controlpoints");
+ Color_Maps->controlPoints[0] = 0.0f;
+ Color_Maps->controlPoints[1] = 0.5f;
+ Color_Maps->controlPoints[2] = 1.0f;
+ glUniform3fv( Color_Maps->cpLocation, 1, Color_Maps->controlPoints);
+ }
+ // Flat Color Shader
+ {
+ Flat_Shader = PushStruct(Working_Set, flat_shader);
+ Flat_Shader->shaderProgram = CreateShader(FragmentSource_Flat.c_str(), VertexSource_Flat.c_str());
-global_function
-u32
-ToggleEditMode(GLFWwindow* window)
-{
- u32 result = 1;
+ glUseProgram(Flat_Shader->shaderProgram);
+ glBindFragDataLocation(Flat_Shader->shaderProgram, 0, "outColor");
- if (Edit_Mode && !Edit_Pixels.editing)
+ Flat_Shader->matLocation = glGetUniformLocation(Flat_Shader->shaderProgram, "matrix");
+ Flat_Shader->colorLocation = glGetUniformLocation(Flat_Shader->shaderProgram, "color");
+ }
+
+ // Fonts
{
- Edit_Pixels.scaffSelecting = 0;
- Global_Mode = mode_normal;
- if (Tool_Tip->on)
+ UI_Shader = PushStruct(Working_Set, ui_shader);
+ UI_Shader->shaderProgram = CreateShader(FragmentSource_UI.c_str(), VertexSource_UI.c_str());
+ glUseProgram(UI_Shader->shaderProgram);
+ glBindFragDataLocation(UI_Shader->shaderProgram, 0, "outColor");
+ glUniform1i(glGetUniformLocation(UI_Shader->shaderProgram, "tex"), 0);
+ UI_Shader->matLocation = glGetUniformLocation(UI_Shader->shaderProgram, "matrix");
+
+ FontStash_Context = glfonsCreate(512, 512, FONS_ZERO_TOPLEFT);
+ Font_Normal = fonsAddFontMem(FontStash_Context, "Sans Regular", FontNormal, (s32)FontNormal_Size, 0);
+
+ if (Font_Normal == FONS_INVALID)
{
- f64 mousex, mousey;
- glfwGetCursorPos(window, &mousex, &mousey);
- MouseMove(window, mousex, mousey);
+ fprintf(stderr, "Could not add font 'DroidSerif-Regular.ttf'\n");
+ exit(1);
+ }
+ Font_Bold = fonsAddFontMem(FontStash_Context, "Sans Bold", FontBold, (s32)FontBold_Size, 0);
+ if (Font_Bold == FONS_INVALID)
+ {
+ fprintf(stderr, "Could not add font 'DroidSerif-Bold.ttf'\n");
+ exit(1);
}
}
- else if (Normal_Mode || Select_Sort_Area_Mode || MetaData_Edit_Mode)
+
+ // Quad EBO
{
- Global_Mode = mode_edit;
+ GLushort pIndexQuad[6];
+ pIndexQuad[0] = 0;
+ pIndexQuad[1] = 1;
+ pIndexQuad[2] = 2;
+ pIndexQuad[3] = 2;
+ pIndexQuad[4] = 3;
+ pIndexQuad[5] = 0;
+
+ glGenBuffers(1, &Quad_EBO);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Quad_EBO);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(GLushort), pIndexQuad, GL_STATIC_DRAW);
}
- else
+
+ GLuint posAttribFlatShader = (GLuint)glGetAttribLocation(Flat_Shader->shaderProgram, "position");
+ auto PushGenericBuffer = [posAttribFlatShader] (quad_data **quadData, u32 numberOfBuffers) -> void
{
- result = 0;
- }
+ *quadData = PushStruct(Working_Set, quad_data);
- return(result);
-}
+ (*quadData)->vaos = PushArray(Working_Set, GLuint, numberOfBuffers);
+ (*quadData)->vbos = PushArray(Working_Set, GLuint, numberOfBuffers);
+ glUseProgram(Flat_Shader->shaderProgram);
-global_function
- u32
- ToggleExtensionMode(GLFWwindow *window)
-{
- u32 result = 1;
+ ForLoop(numberOfBuffers)
+ {
+ glGenVertexArrays(1, (*quadData)->vaos + index);
+ glBindVertexArray((*quadData)->vaos[index]);
- if (Extension_Mode)
+ glGenBuffers(1, (*quadData)->vbos + index);
+ glBindBuffer(GL_ARRAY_BUFFER, (*quadData)->vbos[index]);
+ glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(vertex), NULL, GL_DYNAMIC_DRAW);
+
+ glEnableVertexAttribArray(posAttribFlatShader);
+ glVertexAttribPointer(posAttribFlatShader, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), 0);
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Quad_EBO);
+ }
+ };
+
+ // Edit Mode Data
{
- Global_Mode = mode_normal;
+ PushGenericBuffer(&Edit_Mode_Data, 12);
}
- else if (Normal_Mode)
+
+ // Tool Tip Data
{
- Global_Mode = mode_extension;
+ PushGenericBuffer(&Tool_Tip_Data, 1);
}
- else
+
+ // Waypoint Data
{
- result = 0;
+ PushGenericBuffer(&Waypoint_Data, (3 * Waypoints_Stack_Size) + 1);
}
- return result;
-}
+ // Nuklear Setup
+ {
+#define NK_Memory_Size MegaByte(32)
+ NK_Device = PushStruct(Working_Set, device);
+ u08 *nkCmdMemory = PushArray(Working_Set, u08, NK_Memory_Size);
+ nk_buffer_init_fixed(&NK_Device->cmds, (void *)nkCmdMemory, NK_Memory_Size);
+ NK_Device->lastContextMemory = PushArray(Working_Set, u08, NK_Memory_Size);
+ memset(NK_Device->lastContextMemory, 0, NK_Memory_Size);
+ NK_Device->prog = UI_Shader->shaderProgram;
+ NK_Device->uniform_proj = UI_Shader->matLocation;
+ NK_Device->attrib_pos = UI_SHADER_LOC_POSITION;
+ NK_Device->attrib_uv = UI_SHADER_LOC_TEXCOORD;
+ NK_Device->attrib_col = UI_SHADER_LOC_COLOR;
+ GLsizei vs = sizeof(nk_glfw_vertex);
+ size_t vp = offsetof(nk_glfw_vertex, position);
+ size_t vt = offsetof(nk_glfw_vertex, uv);
+ size_t vc = offsetof(nk_glfw_vertex, col);
-global_function
-u32
-ToggleWaypointMode(GLFWwindow* window)
-{
- u32 result = 1;
+ glGenBuffers(1, &NK_Device->vbo);
+ glGenBuffers(1, &NK_Device->ebo);
+ glGenVertexArrays(1, &NK_Device->vao);
- if (Waypoint_Edit_Mode)
- {
- Global_Mode = mode_normal;
- if (Tool_Tip->on)
- {
- f64 mousex, mousey;
- glfwGetCursorPos(window, &mousex, &mousey);
- MouseMove(window, mousex, mousey);
- }
- }
- else if (Normal_Mode)
- {
- Global_Mode = mode_waypoint_edit;
- f64 mousex, mousey;
- glfwGetCursorPos(window, &mousex, &mousey);
- MouseMove(window, mousex, mousey);
- }
- else
- {
- result = 0;
+ glBindVertexArray(NK_Device->vao);
+ glBindBuffer(GL_ARRAY_BUFFER, NK_Device->vbo);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, NK_Device->ebo);
+
+ glEnableVertexAttribArray((GLuint)NK_Device->attrib_pos);
+ glEnableVertexAttribArray((GLuint)NK_Device->attrib_uv);
+ glEnableVertexAttribArray((GLuint)NK_Device->attrib_col);
+
+ glVertexAttribPointer((GLuint)NK_Device->attrib_pos, 2, GL_FLOAT, GL_FALSE, vs, (void*)vp);
+ glVertexAttribPointer((GLuint)NK_Device->attrib_uv, 2, GL_FLOAT, GL_FALSE, vs, (void*)vt);
+ glVertexAttribPointer((GLuint)NK_Device->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, vs, (void*)vc);
+
+ NK_Atlas = PushStruct(Working_Set, nk_font_atlas);
+ nk_font_atlas_init_default(NK_Atlas);
+ nk_font_atlas_begin(NK_Atlas);
+ struct nk_font_config cfg = nk_font_config(14);
+ cfg.oversample_h = 3;
+ cfg.oversample_v = 3;
+ NK_Font = nk_font_atlas_add_from_memory(NK_Atlas, FontBold, (nk_size)FontBold_Size, 22 * Screen_Scale.y, &cfg);
+ NK_Font_Browser = nk_font_atlas_add_from_memory(NK_Atlas, FontBold, (nk_size)FontBold_Size, 14 * Screen_Scale.y, &cfg);
+
+ s32 w,h;
+ const void *image = nk_font_atlas_bake(NK_Atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
+
+ glGenTextures(1, &NK_Device->font_tex);
+ glBindTexture(GL_TEXTURE_2D, NK_Device->font_tex);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)w, (GLsizei)h, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, image);
+
+ nk_font_atlas_end(NK_Atlas, nk_handle_id((s32)NK_Device->font_tex), &NK_Device->null);
+ u08 *nkContextMemory = PushArray(Working_Set, u08, NK_Memory_Size);
+ nk_init_fixed(NK_Context, (void *)nkContextMemory, NK_Memory_Size, &NK_Font->handle);
+
+ SetTheme(NK_Context, THEME_DARK);
+
+ Theme_Name[THEME_RED] = (u08 *)"Red";
+ Theme_Name[THEME_BLUE] = (u08 *)"Blue";
+ Theme_Name[THEME_WHITE] = (u08 *)"White";
+ Theme_Name[THEME_BLACK] = (u08 *)"Black";
+ Theme_Name[THEME_DARK] = (u08 *)"Dark";
}
- return(result);
+ Loading_Arena = PushStruct(Working_Set, memory_arena);
+ CreateMemoryArena(*Loading_Arena, MegaByte(512));
+ //Loading_Arena = PushSubArena(Working_Set, MegaByte(128));
}
+
+
global_function
-u32
-ToggleScaffMode(GLFWwindow* window)
+void
+TakeScreenShot(int nchannels = 4)
{
- u32 result = 1;
+ s32 viewport[4];
+ glGetIntegerv (GL_VIEWPORT, viewport);
- if (Scaff_Edit_Mode && !Scaff_Painting_Flag)
- {
- Global_Mode = mode_normal;
- Scaff_Painting_Flag = 0;
- Scaff_Painting_Id = 0;
- Scaff_FF_Flag = 0;
- if (Tool_Tip->on)
- {
- f64 mousex, mousey;
- glfwGetCursorPos(window, &mousex, &mousey);
- MouseMove(window, mousex, mousey);
- }
- }
- else if (Normal_Mode)
- {
- Global_Mode = mode_scaff_edit;
- f64 mousex, mousey;
- glfwGetCursorPos(window, &mousex, &mousey);
- MouseMove(window, mousex, mousey);
- }
- else
- {
- result = 0;
- }
+ u08 *imageBuffer = PushArray(Working_Set, u08, (u32)(nchannels * viewport[2] * viewport[3]));
+ glReadPixels ( 0, 0, viewport[2], viewport[3],
+ nchannels==4 ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE,
+ imageBuffer);
- return(result);
+ stbi_flip_vertically_on_write(1);
+ stbi_write_png("PretextView_ScreenShot.png", viewport[2], viewport[3], nchannels, imageBuffer, nchannels * viewport[2]); //TODO change png compression to use libdeflate zlib impl
+ FreeLastPush(Working_Set);
}
+
+
global_function
-u32
-ToggleMetaDataMode(GLFWwindow* window)
+void
+InvertMap(
+ u32 pixelFrom, // from pixel
+ u32 pixelTo, // end pixel
+ bool update_contigs_flag
+ )
{
- u32 result = 1;
-
- if (MetaData_Edit_Mode)
- {
- Global_Mode = mode_normal;
- if (Tool_Tip->on)
- {
- f64 mousex, mousey;
- glfwGetCursorPos(window, &mousex, &mousey);
- MouseMove(window, mousex, mousey);
- }
- }
- else if (Normal_Mode || (Edit_Mode && !Edit_Pixels.editing) || Select_Sort_Area_Mode)
- {
- Global_Mode = mode_meta_edit;
- f64 mousex, mousey;
- glfwGetCursorPos(window, &mousex, &mousey);
- MouseMove(window, mousex, mousey);
- }
- else
+ if (pixelFrom > pixelTo)
{
- result = 0;
+ u32 tmp = pixelFrom;
+ pixelFrom = pixelTo;
+ pixelTo = tmp;
}
- return(result);
-}
+ u32 nPixels = Number_of_Pixels_1D;
+ Assert(pixelFrom < nPixels);
+ Assert(pixelTo < nPixels);
+
+ u32 copySize = (pixelTo - pixelFrom + 1) >> 1;
+
+ u32 *tmpBuffer = new u32[copySize];
+ u32 *tmpBuffer2 = new u32[copySize];
+ u32 *tmpBuffer3 = new u32[copySize];
+ u32 *tmpBuffer4 = new u32[copySize];
+ u64 *tmpBuffer5 = new u64[copySize];
-global_function
-u32
-ToggleSelectSortAreaMode(GLFWwindow* window)
-{
- u32 result = 1;
+ glBindBuffer(GL_TEXTURE_BUFFER, Contact_Matrix->pixelRearrangmentLookupBuffer);
+ u32 *buffer = (u32 *)glMapBufferRange(GL_TEXTURE_BUFFER, 0, nPixels * sizeof(u32), GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); // map buffer to read and write
- if (Select_Sort_Area_Mode)
+ if (buffer)
{
- Global_Mode = mode_normal;
- if (Tool_Tip->on)
+ ForLoop(copySize) // put the first half in the buffer
{
- f64 mousex, mousey;
- glfwGetCursorPos(window, &mousex, &mousey);
- MouseMove(window, mousex, mousey);
+ tmpBuffer[index] = buffer[pixelFrom + index];
+ tmpBuffer2[index] = Map_State->contigRelCoords[pixelFrom + index];
+ tmpBuffer3[index] = Map_State->originalContigIds[pixelFrom + index];
+ tmpBuffer4[index] = Map_State->scaffIds[pixelFrom + index];
+ tmpBuffer5[index] = Map_State->metaDataFlags[pixelFrom + index];
+ }
+
+ ForLoop(copySize) // set the first half to the second half
+ {
+ buffer[pixelFrom + index] = buffer[pixelTo - index];
+ Map_State->contigRelCoords[pixelFrom + index] = Map_State->contigRelCoords[pixelTo - index];
+ Map_State->originalContigIds[pixelFrom + index] = Map_State->originalContigIds[pixelTo - index];
+ Map_State->scaffIds[pixelFrom + index] = Map_State->scaffIds[pixelTo - index];
+ Map_State->metaDataFlags[pixelFrom + index] = Map_State->metaDataFlags[pixelTo - index];
+ }
+
+ ForLoop(copySize) // set the second half from the buffer
+ {
+ buffer[pixelTo - index] = tmpBuffer[index];
+ Map_State->contigRelCoords[pixelTo - index] = tmpBuffer2[index];
+ Map_State->originalContigIds[pixelTo - index] = tmpBuffer3[index];
+ Map_State->scaffIds[pixelTo - index] = tmpBuffer4[index];
+ Map_State->metaDataFlags[pixelTo - index] = tmpBuffer5[index];
}
- }
- else if (Normal_Mode || (Edit_Mode && !Edit_Pixels.editing) || MetaData_Edit_Mode)
- {
- Global_Mode = mode_selectExclude_sort_area;
- f64 mousex, mousey;
- glfwGetCursorPos(window, &mousex, &mousey);
- MouseMove(window, mousex, mousey);
}
else
{
- result = 0;
+ fprintf(stderr, "Could not map pixel rearrange buffer\n");
}
- return(result);
+ glUnmapBuffer(GL_TEXTURE_BUFFER);
+ glBindBuffer(GL_TEXTURE_BUFFER, 0);
-}
+ delete[] tmpBuffer ;
+ delete[] tmpBuffer2;
+ delete[] tmpBuffer3;
+ delete[] tmpBuffer4;
+ delete[] tmpBuffer5;
+
+ if (update_contigs_flag) UpdateContigsFromMapState(); // update the contigs from the buffer
+ map_edit edit;
+ edit.finalPix1 = (u32)pixelTo;
+ edit.finalPix2 = (u32)pixelFrom;
+ edit.delta = 0;
+ MoveWayPoints(&edit);
+}
global_function
-void
-ToggleToolTip(GLFWwindow* window)
+s32
+RearrangeMap( // NOTE: VERY IMPORTANT
+ u32 pixelFrom, // start of the fragment
+ u32 pixelTo, // end of the fragment
+ s32 delta, // movement of the distance
+ u08 snap, // if true, the fragment will snap to the nearest contig
+ bool update_contigs_flag // if true, update the contigs from the map state
+ )
{
- Tool_Tip->on = !Tool_Tip->on;
- if (Tool_Tip->on)
+
+ u32 nPixels = Number_of_Pixels_1D;
+
+ if (std::abs(delta) >= nPixels ||
+ pixelFrom >= nPixels ||
+ pixelTo >= nPixels)
{
- f64 mousex, mousey;
- glfwGetCursorPos(window, &mousex, &mousey);
- MouseMove(window, mousex, mousey);
+ fmt::print(
+ stderr,
+ "RearrangeMap: Invalid parameters: delta = {}, pixelFrom = {}, pixelTo = {}, nPixels = {}, file {} line {}\n",
+ delta, pixelFrom, pixelTo, nPixels,
+ __FILE__, __LINE__
+ );
+ assert(0);
}
-}
-#if 0
-enum
-MouseButon
-{
- left,
- right,
- middle,
-};
-
-struct
-KeyBindings
-{
- s32 ui;
- s32 editMode;
- s32 waypointMode;
- s32 undoEdit;
- s32 redoEdit;
- s32 selectWholeSeq_key;
- MouseButon selectWholeSeq_mouse;
-
-};
-#endif
+ if (pixelFrom > pixelTo) // Swap, make sure pixelFrom is less than pixelTo
+ {
+ std::swap(pixelFrom, pixelTo);
+ }
+ u32 nPixelsInRange = pixelTo - pixelFrom + 1;
-global_variable
-s32
-Windowed_Xpos, Windowed_Ypos, Windowed_Width, Windowed_Height;
+ pixelFrom += nPixels;
+ pixelTo += nPixels;
-#if 0
-struct
-GLFWKeyAndScancode
-{
- s32 key;
- s32 scancode;
-};
+ auto GetRealBufferLocation = [nPixels] (u32 index)
+ {
+ u32 result;
-global_variable
-GLFWKeyAndScancode
-LastPressedKey = {0, 0};
-#endif
+ Assert(index >= 0 && index < 3 * nPixels);
-global_variable
-nk_keys
-NK_Pressed_Keys[1024] = {};
+ if (index >= (2 * nPixels))
+ {
+ result = index - (2 * nPixels);
+ }
+ else if (index >= nPixels)
+ {
+ result = index - nPixels;
+ }
+ else
+ {
+ result = index;
+ }
-global_variable
-u32
-NK_Pressed_Keys_Ptr = 0;
+ return(result);
+ };
-global_variable
-u32
-GatheringTextInput = 0;
+ u32 forward = delta > 0; // move direction
-global_function
-void
-KeyBoard(GLFWwindow* window, s32 key, s32 scancode, s32 action, s32 mods)
-{
- if (!Loading && !auto_sort_state && !auto_cut_state && (action != GLFW_RELEASE || key == GLFW_KEY_SPACE || key == GLFW_KEY_A || key == GLFW_KEY_LEFT_SHIFT))
+ if (snap) // can not put the selected frag into one frag.
{
- if (UI_On)
+ if (forward) // move to the end
{
-#if 0
- LastPressedKey.key = key;
- LastPressedKey.scancode = scancode;
-#else
- (void)scancode;
-#endif
-
- if (key == GLFW_KEY_ENTER && mods == GLFW_MOD_ALT)
+ u32 target = GetRealBufferLocation(pixelTo + (u32)delta);
+ u32 targetContigId = Map_State->contigIds[target] + (target == Number_of_Pixels_1D - 1 ? 1 : 0); // why is the last pixel +1?
+ if (targetContigId) // only if the target is not the selected contig
{
- if (glfwGetWindowMonitor(window))
- {
- glfwSetWindowMonitor(window, NULL,
- Windowed_Xpos, Windowed_Ypos,
- Windowed_Width, Windowed_Height, 0);
- }
- else
+ contig *targetContig = Contigs->contigs_arr + targetContigId - 1;
+
+ u32 targetCoord = IsContigInverted(targetContigId - 1) ? (targetContig->startCoord - targetContig->length + 1) : (targetContig->startCoord + targetContig->length - 1);
+ while (delta > 0 &&
+ (Map_State->contigIds[target] != targetContigId - 1 ||
+ Map_State->contigRelCoords[target] != targetCoord))
{
- GLFWmonitor* monitor = glfwGetPrimaryMonitor();
- if (monitor)
- {
- const GLFWvidmode* mode = glfwGetVideoMode(monitor);
- glfwGetWindowPos(window, &Windowed_Xpos, &Windowed_Ypos);
- glfwGetWindowSize(window, &Windowed_Width, &Windowed_Height);
- glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
- }
+ --target;
+ --delta;
}
}
-#ifdef Internal
- else if (key == GLFW_KEY_ESCAPE && !mods)
- {
- glfwSetWindowShouldClose(window, GLFW_TRUE);
- }
-#endif
- /*nk_input_key(NK_Context, NK_KEY_DEL, glfwGetKey(window, GLFW_KEY_DELETE) == GLFW_PRESS);
- nk_input_key(NK_Context, NK_KEY_ENTER, glfwGetKey(window, GLFW_KEY_ENTER) == GLFW_PRESS);
- nk_input_key(NK_Context, NK_KEY_TAB, glfwGetKey(window, GLFW_KEY_TAB) == GLFW_PRESS);
- nk_input_key(NK_Context, NK_KEY_BACKSPACE, glfwGetKey(window, GLFW_KEY_BACKSPACE) == GLFW_PRESS);
- nk_input_key(NK_Context, NK_KEY_LEFT, glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS);
- nk_input_key(NK_Context, NK_KEY_RIGHT, glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS);
- nk_input_key(NK_Context, NK_KEY_UP, glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS);
- nk_input_key(NK_Context, NK_KEY_DOWN, glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS);
-
- if (glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS || glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS)
- {
- nk_input_key(NK_Context, NK_KEY_COPY, glfwGetKey(window, GLFW_KEY_C) == GLFW_PRESS);
- nk_input_key(NK_Context, NK_KEY_PASTE, glfwGetKey(window, GLFW_KEY_P) == GLFW_PRESS);
- nk_input_key(NK_Context, NK_KEY_CUT, glfwGetKey(window, GLFW_KEY_X) == GLFW_PRESS);
- nk_input_key(NK_Context, NK_KEY_CUT, glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS);
- nk_input_key(NK_Context, NK_KEY_SHIFT, 1);
- }
else
{
- nk_input_key(NK_Context, NK_KEY_COPY, 0);
- nk_input_key(NK_Context, NK_KEY_PASTE, 0);
- nk_input_key(NK_Context, NK_KEY_CUT, 0);
- nk_input_key(NK_Context, NK_KEY_SHIFT, 0);
- }*/
-
-
- else if (key == GLFW_KEY_U)
- {
- Deferred_Close_UI = 1;
+ delta = 0;
}
- else if (action != GLFW_RELEASE && !GatheringTextInput)
+ }
+ else // move to the start
+ {
+ u32 target = GetRealBufferLocation((u32)((s32)pixelFrom + delta));
+ u32 targetContigId = Map_State->contigIds[target];
+ if (targetContigId < (Contigs->numberOfContigs - 1)) // only if the target is not the selected contig
{
- nk_keys addKey = NK_KEY_NONE;
- switch (key)
+ contig *targetContig = Contigs->contigs_arr + (target ? targetContigId + 1 : 0);
+ u32 targetCoord = targetContig->startCoord;
+ while (delta < 0 && (Map_State->contigIds[target] != (target ? targetContigId + 1 : 0) || Map_State->contigRelCoords[target] != targetCoord))
{
- case GLFW_KEY_DELETE:
- addKey = NK_KEY_DEL;
- break;
-
- case GLFW_KEY_ENTER:
- addKey = NK_KEY_ENTER;
- break;
+ ++target;
+ ++delta;
+ }
+ }
+ else delta = 0;
+ }
+ }
- case GLFW_KEY_TAB:
- addKey = NK_KEY_TAB;
- break;
+ if (delta)
+ {
+ u32 startCopyFromRange; // location start to copy
+ u32 startCopyToRange; // location start to put the copied data
- case GLFW_KEY_BACKSPACE:
- addKey = NK_KEY_BACKSPACE;
- break;
+ if (forward) // move to the end
+ {
+ startCopyFromRange = pixelTo + 1;
+ startCopyToRange = pixelFrom;
+ }
+ else // move to the start
+ {
+ startCopyFromRange = (u32)((s32)pixelFrom + delta);
+ startCopyToRange = (u32)((s32)pixelTo + delta) + 1;
+ }
- case GLFW_KEY_LEFT:
- addKey = NK_KEY_LEFT;
- break;
+ u32 copySize = std::abs(delta);
- case GLFW_KEY_RIGHT:
- addKey = NK_KEY_RIGHT;
- break;
+ u32 *tmpBuffer = new u32[copySize];
+ u32 *tmpBuffer2 = new u32[copySize]; // original contig ids
+ u32 *tmpBuffer3 = new u32[copySize]; // original contig coords
+ u32 *tmpBuffer4 = new u32[copySize]; // scaff ids
+ u64 *tmpBuffer5 = new u64[copySize]; // meta data flags
- case GLFW_KEY_UP:
- addKey = NK_KEY_UP;
- break;
+ glBindBuffer(GL_TEXTURE_BUFFER, Contact_Matrix->pixelRearrangmentLookupBuffer); // pixel rearrange buffer
+ u32 *buffer = (u32 *)glMapBufferRange(GL_TEXTURE_BUFFER, 0, nPixels * sizeof(u32), GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); // map the buffer
- case GLFW_KEY_DOWN:
- addKey = NK_KEY_DOWN;
- break;
+ if (buffer)
+ {
+ ForLoop(copySize) // copySize is abs(delta)
+ {
+ tmpBuffer[index] = buffer[GetRealBufferLocation(index + startCopyFromRange)]; // TODO understand how is the texture buffer data getting exchanged
+ tmpBuffer2[index] = Map_State->originalContigIds[GetRealBufferLocation(index + startCopyFromRange)];
+ tmpBuffer3[index] = Map_State->contigRelCoords[GetRealBufferLocation(index + startCopyFromRange)];
+ tmpBuffer4[index] = Map_State->scaffIds[GetRealBufferLocation(index + startCopyFromRange)];
+ tmpBuffer5[index] = Map_State->metaDataFlags[GetRealBufferLocation(index + startCopyFromRange)];
+ }
+
+ // copy the selected fragment to the new location
+ if (forward) // move to the ends
+ {
+ ForLoop(nPixelsInRange) // (pixelTo - pixelFrom + 1)
+ {
+ buffer[GetRealBufferLocation(pixelTo + (u32)delta - index)] = buffer[GetRealBufferLocation(pixelTo - index)];
+ Map_State->originalContigIds[GetRealBufferLocation(pixelTo + (u32)delta - index)] = Map_State->originalContigIds[GetRealBufferLocation(pixelTo - index)];
+ Map_State->contigRelCoords[GetRealBufferLocation(pixelTo + (u32)delta - index)] = Map_State->contigRelCoords[GetRealBufferLocation(pixelTo - index)];
+ Map_State->scaffIds[GetRealBufferLocation(pixelTo + (u32)delta - index)] = Map_State->scaffIds[GetRealBufferLocation(pixelTo - index)];
+ Map_State->metaDataFlags[GetRealBufferLocation(pixelTo + (u32)delta - index)] = Map_State->metaDataFlags[GetRealBufferLocation(pixelTo - index)];
}
-
- if (addKey != NK_KEY_NONE)
+ }
+ else // move to the start
+ {
+ ForLoop(nPixelsInRange)
{
- NK_Pressed_Keys[NK_Pressed_Keys_Ptr++] = addKey;
- if (NK_Pressed_Keys_Ptr == ArrayCount(NK_Pressed_Keys)) NK_Pressed_Keys_Ptr = 0;
+ buffer[GetRealBufferLocation((u32)((s32)pixelFrom + delta) + index)] = buffer[GetRealBufferLocation(pixelFrom + index)];
+ Map_State->originalContigIds[GetRealBufferLocation((u32)((s32)pixelFrom + delta) + index)] = Map_State->originalContigIds[GetRealBufferLocation(pixelFrom + index)];
+ Map_State->contigRelCoords[GetRealBufferLocation((u32)((s32)pixelFrom + delta) + index)] = Map_State->contigRelCoords[GetRealBufferLocation(pixelFrom + index)];
+ Map_State->scaffIds[GetRealBufferLocation((u32)((s32)pixelFrom + delta) + index)] = Map_State->scaffIds[GetRealBufferLocation(pixelFrom + index)];
+ Map_State->metaDataFlags[GetRealBufferLocation((u32)((s32)pixelFrom + delta) + index)] = Map_State->metaDataFlags[GetRealBufferLocation(pixelFrom + index)];
}
}
+
+ // copy the influenced fragment (delta) to the new location
+ ForLoop(copySize)
+ {
+ buffer[GetRealBufferLocation(index + startCopyToRange)] = tmpBuffer[index];
+ Map_State->originalContigIds[GetRealBufferLocation(index + startCopyToRange)] = tmpBuffer2[index];
+ Map_State->contigRelCoords[GetRealBufferLocation(index + startCopyToRange)] = tmpBuffer3[index];
+ Map_State->scaffIds[GetRealBufferLocation(index + startCopyToRange)] = tmpBuffer4[index];
+ Map_State->metaDataFlags[GetRealBufferLocation(index + startCopyToRange)] = tmpBuffer5[index];
+ }
}
- else // not UI_On
+ else
{
- u32 keyPressed = 1;
+ fprintf(stderr, "Could not map pixel rearrange buffer\n");
+ }
- switch (key)
- {
-
- case GLFW_KEY_A:
- if (Scaff_Edit_Mode)
- {
- if (action != GLFW_RELEASE) Scaff_FF_Flag |= 1;
- else Scaff_FF_Flag &= ~1;
- }
- else keyPressed = 0;
- break;
+ glUnmapBuffer(GL_TEXTURE_BUFFER);
+ glBindBuffer(GL_TEXTURE_BUFFER, 0);
+ delete[] tmpBuffer ;
+ delete[] tmpBuffer2;
+ delete[] tmpBuffer3;
+ delete[] tmpBuffer4;
+ delete[] tmpBuffer5;
+ // FreeLastPush(Working_Set); // tmpBuffer
+ // FreeLastPush(Working_Set); // tmpBuffer2
+ // FreeLastPush(Working_Set); // tmpBuffer3
+ // FreeLastPush(Working_Set); // tmpBuffer4
+ // FreeLastPush(Working_Set); // tmpBuffer5
- case GLFW_KEY_B:
- Scale_Bars->on = !Scale_Bars->on;
- break;
- case GLFW_KEY_C:
- if (Select_Sort_Area_Mode && auto_curation_state.get_selected_fragments_num(Map_State, Number_of_Pixels_1D) > 0) // local area break
- {
- auto_cut_state = 1;
- }
- else // open "coverage" extension
- {
- if (!Extensions.head) break;
- TraverseLinkedList(Extensions.head, extension_node)
- {
- switch (node->type)
- {
- case extension_graph:
- {
+ if (update_contigs_flag) UpdateContigsFromMapState();
+
+ map_edit edit;
+ edit.finalPix1 = (u32)GetRealBufferLocation((u32)((s32)pixelFrom + delta));
+ edit.finalPix2 = (u32)GetRealBufferLocation((u32)((s32)pixelTo + delta));
+ edit.delta = (s32)delta;
+ MoveWayPoints(&edit);
+ }
- graph *gph = (graph *)node->extension;
- if (strcmp((char *)gph->name, "coverage") == 0)
- {
- gph->on = !gph->on;
- break;
- }
- }
- }
- }
- }
-
- break;
+ return(delta);
+}
- case GLFW_KEY_D:
- if (Scaff_Edit_Mode && (mods & GLFW_MOD_SHIFT))
- {
- ForLoop(Contigs->numberOfContigs) (Contigs->contigs_arr + index)->scaffId = 0;
- UpdateScaffolds();
- }
- else if (MetaData_Edit_Mode && (mods & GLFW_MOD_SHIFT)) memset(Map_State->metaDataFlags, 0, Number_of_Pixels_1D * sizeof(u64));
- else keyPressed = 0;
- break;
- case GLFW_KEY_E:
- keyPressed = ToggleEditMode(window);
- break;
+/*
+ BreakMap: cut the contig at loc, and update the original contig ids
+ loc: the location to cut
+ ignore_len: the length of the contig to be ignored
+ extension_flag: if true, consider the extension signal
+
+*/
+global_function
+void
+BreakMap(
+ const int& loc,
+ const u32& ignore_len // cut点到开头或者结尾的长度不足ignore_len的contig不会被切断
+)
+{
+ if (loc >= Number_of_Pixels_1D)
+ {
+ char buff[512];
+ snprintf(buff, sizeof(buff), "[Pixel Cut] Error: loc (%d) should be smaller than number of pixels (%d)", loc, Number_of_Pixels_1D);
+ MY_CHECK(buff);
+ assert(0);
+ }
+ u32 original_contig_id = Map_State->originalContigIds[loc];
+ u32 contig_id = Map_State->contigIds[loc];
+ u32 contig_rel_coord = Map_State->contigRelCoords[loc];
- case GLFW_KEY_F:
- keyPressed = ToggleSelectSortAreaMode(window);
- break;
+ s32 ptr_left = (s32)loc, ptr_right = (s32)loc;
+ u08 inversed = IsContigInverted(contig_id);
+ while ( // 从loc向左遍历,找到最后一个满足条件的像素点索引
+ ptr_left > 0 &&
+ Map_State->contigIds[ptr_left] == contig_id &&
+ (Map_State->contigRelCoords[ptr_left-1] == Map_State->contigRelCoords[ptr_left]+ (inversed ? +1 : -1)) ) { --ptr_left; };
+ while ( // 从loc向右遍历,找到最后一个满足条件的像素点索引
+ ptr_right < Number_of_Pixels_1D-1 &&
+ Map_State->contigIds[ptr_right] == contig_id &&
+ (Map_State->contigRelCoords[ptr_right] == Map_State->contigRelCoords[ptr_right+1]+ (inversed ? +1 : -1)) ) {++ptr_right;};
+
+ int l_len = loc - ptr_left + 1, r_len = ptr_right - loc ; // treat the loc as the right side
+ if (l_len <= (ignore_len) || r_len <= (ignore_len-1) )
+ {
+ fmt::print(
+ "[Pixel Cut::warning] original_contig_id {} current_contig_id {}, pixel range: [{}, cut({}), {}], left_len({})<=ignore_len({}) or right_len({})<=ignore_len({}-1), cut at loc: ({}) is ignored\n",
+ original_contig_id % Max_Number_of_Contigs,
+ contig_id,
+ ptr_left,
+ loc,
+ ptr_right,
+ l_len, ignore_len,
+ r_len, ignore_len,
+ loc);
+ return;
+ }
- case GLFW_KEY_G:
- if (!Extensions.head) break;
- TraverseLinkedList(Extensions.head, extension_node)
- {
- switch (node->type)
- {
- case extension_graph:
- {
+ // cut the contig by amending the original Contig Ids.
+ for (u32 tmp = loc + 1; tmp <= ptr_right; tmp++) // cut_loc is included as left
+ {
+ if (Map_State->originalContigIds[tmp] > (std::numeric_limits::max() - Max_Number_of_Contigs))
+ {
+ fmt::print("[Pixel Cut] originalContigIds[{}] + {} = {} is greater than the max number of contigs ({}), file {}, line {}\n", tmp,
+ Max_Number_of_Contigs,
+ (u64)Map_State->originalContigIds[tmp] + Max_Number_of_Contigs,
+ std::numeric_limits::max(),
+ __FILE__, __LINE__);
+ assert(0);
+ }
+ Map_State->originalContigIds[tmp] += Max_Number_of_Contigs; // NOTE: the number can not exceed the max number 2**32 - 1 = 4294967295. However, it is not easy to exceed the max number of contigs, as 4294967295 / 4096 = 1048575.9997
+ }
- graph *gph = (graph *)node->extension;
- if (strcmp((char *)gph->name, "gap") == 0)
- {
- gph->on = !gph->on;
- break;
- }
- }
- }
- }
- break;
+ fmt::print(
+ "[Pixel Cut] Original contig_id ({}), current_id ({}), pixel range: [{}, {}] {} inversed, cut at {}\n",
+ original_contig_id%Max_Number_of_Contigs,
+ contig_id,
+ ptr_left,
+ ptr_right,
+ inversed ? "(is)" : "(isn\'t)",
+ loc );
- case GLFW_KEY_H:
- break;
+ return ;
- case GLFW_KEY_I:
- Contig_Ids->on = !Contig_Ids->on;
- break;
+}
- case GLFW_KEY_J:
- JumpToDiagonal(window);
- break;
- case GLFW_KEY_K:
- break;
+global_function
+std::vector
+get_exclude_metaData_idx(const std::vector& exclude_tags)
+{
+ if (exclude_tags.empty()) return std::vector();
- case GLFW_KEY_L:
- if (Waypoint_Edit_Mode)
- {
- Long_Waypoints_Mode = (Long_Waypoints_Mode +1) % 3;
- }
- else
- {
- Grid->on = !Grid->on;
- }
- break;
+ std::vector exclude_frag_idx((u32) exclude_tags.size(), -1);
+ for (u32 i=0; i < exclude_frag_idx.size(); i++)
+ {
+ for (u32 j=0; j < 64; j++)
+ {
+ if (!Meta_Data->tags[j]) break;
+ auto tmp = std::string((char*)Meta_Data->tags[j]);
+ std::transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
+ if ( tmp == exclude_tags[i])
+ {
+ exclude_frag_idx[i] = j;
+ break;
+ }
+ }
+ }
+ return exclude_frag_idx;
+}
- case GLFW_KEY_M:
- keyPressed = ToggleMetaDataMode(window);
- break;
- case GLFW_KEY_N:
- Contig_Name_Labels->on = !Contig_Name_Labels->on;
- break;
- case GLFW_KEY_O:
+void RedoAllEdits(map_editor* map_editor_)
+{
+ while (map_editor_->nUndone) RedoMapEdit();
+ return ;
+}
+
+
+void EraseAllEdits(map_editor* map_editor_, u32 max_edit_recorded=Edits_Stack_Size)
+{
+ u32 nEdits = my_Min(max_edit_recorded, map_editor_->nEdits);
+ ForLoop(nEdits) UndoMapEdit();
+ return ;
+}
+
+
+void run_ai_detection()
+{
+ std::cout << "Running AI detection..." << std::endl;
+ int status = std::system("/Users/sg35/miniconda3/envs/auto_cut/bin/python /Users/sg35/PretextView/python/autoCut/auto_cut.py");
+
+ // 检查命令执行状态
+ if (status == 0) {
+ std::cout << "Command successful!" << std::endl;
+ } else {
+ std::cerr << "Command failed, code: " << status << std::endl;
+ }
+}
+
+void cut_frags(const std::vector& problem_locs, bool consider_gap_extension_flag=true, bool consider_min_len_flag=true)
+{
+ const u32* gap_data_ptr = (auto_curation_state.auto_cut_with_extension && consider_gap_extension_flag) ? Extensions.get_graph_data_ptr("gap"):nullptr;
+
+ for (auto & loc_orig : problem_locs)
+ {
+ int loc = loc_orig;
+ if (gap_data_ptr) // correct loc with considering the gap extension
+ {
+ int distance_tmp = 0;
+ while (distance_tmp <= auto_curation_state.auto_cut_gap_loc_threshold)
+ {
+ if (loc_orig + distance_tmp < Number_of_Pixels_1D && gap_data_ptr[loc_orig + distance_tmp] > 0 )
+ {
+ fmt::println(
+ "[Pixel Cut] gap[{}+{}] = {}, correct cut from ({}) to ({})",
+ loc_orig, distance_tmp, gap_data_ptr[loc_orig + distance_tmp], loc_orig, loc_orig + distance_tmp
+ );
+ loc = loc_orig + distance_tmp;
break;
-
- case GLFW_KEY_P:
+ }
+ else if (loc_orig-distance_tmp >= 0 && gap_data_ptr[loc_orig - distance_tmp] > 0)
+ {
+ fmt::println(
+ "[Pixel Cut] gap[{}-{}] = {}, correct cut from ({}) to ({})",
+ loc_orig, distance_tmp, gap_data_ptr[loc_orig - distance_tmp], loc_orig, loc_orig - distance_tmp
+ );
+ loc = loc_orig - distance_tmp;
break;
+ }
+ else
+ {
+ distance_tmp++;
+ }
+ }
+ }
+ // cut the fragment
+ BreakMap(
+ loc, // cut loc
+ consider_min_len_flag ? auto_curation_state.auto_cut_smallest_frag_size_in_pixel:1); // ignore length
+ UpdateContigsFromMapState();
+ }
+ Redisplay = 1;
+}
- case GLFW_KEY_Q:
- if (Edit_Mode || Select_Sort_Area_Mode)
- {
- UndoMapEdit();
- }
- else
- {
- keyPressed = 0;
- }
- break;
- case GLFW_KEY_R:
- if (mods == GLFW_MOD_CONTROL)
- {
- Loading = 1;
- }
- else if (Extension_Mode && Extensions.head)
- {
- TraverseLinkedList(Extensions.head, extension_node)
- {
- switch (node->type)
- {
- case extension_graph:
- {
- graph *gph = (graph *)node->extension;
- if (strcmp((char *)gph->name, "repeat_density") == 0)
- {
- gph->on = !gph->on;
- break;
- }
- }
- }
- }
- break;
- }
- else
- {
- keyPressed = 0;
- }
- break;
+void AutoCurationFromFragsOrder(
+ const FragsOrder* frags_order_,
+ contigs* contigs_,
+ map_state* map_state_,
+ SelectArea* select_area)
+{
+ u08 using_select_area = (select_area && select_area->select_flag)? 1 : 0;
+ u32 num_frags = contigs_->numberOfContigs;
+ if (!using_select_area )
+ {
+ if ( num_frags != frags_order_->get_num_frags())
+ {
+ fprintf(stderr, "[AutoCurationFromFragsOrder::error]: Number of contigs(%d) and fragsOrder.num_frags(%d) does not match.\n", num_frags, frags_order_->get_num_frags());
+ assert(0);
+ }
+ }
+ else
+ {
+ if (select_area->get_to_sort_frags_num() != frags_order_->get_num_frags())
+ {
+ fmt::print(
+ stderr,
+ "num_to_sort_contigs({}) != fragsOrder.num_frags({}), file {}, line {}\n", select_area->get_to_sort_frags_num(),
+ frags_order_->get_num_frags(),
+ __FILE__, __LINE__);
+ assert(0);
+ }
+ }
- case GLFW_KEY_S:
- if (Edit_Mode)
- {
- Edit_Pixels.snap = !Edit_Pixels.snap;
- }
- else if (mods & GLFW_MOD_SHIFT)
- {
- Scaffs_Always_Visible = Scaffs_Always_Visible ? 0 : 1;
- }
- else if (Select_Sort_Area_Mode)
- {
- auto_curation_state.clear(); // clear the selected area
- }
- else
- {
- keyPressed = ToggleScaffMode(window);
- }
- break;
+ u32 num_autoCurated_edits=0;
- case GLFW_KEY_T:
- if (Extension_Mode && Extensions.head)
- {
- TraverseLinkedList(Extensions.head, extension_node)
- {
- switch (node->type)
- {
- case extension_graph:
- {
+ // check the difference between the contigs, order and the new frags order
+ u32 start_loc = 0;
+ std::vector> current_order(num_frags); // [contig_id, contig_length]
+ std::vector predicted_order = frags_order_->get_order_without_chromosomeInfor(); // start from 1
+ if (using_select_area)
+ {
+ std::vector full_predicted_order(num_frags);
+ std::iota(full_predicted_order.begin(), full_predicted_order.end(), 1);
+ std::vector frags_id_to_sort = select_area->get_to_sort_frags_id(Contigs);
+ for (u32 i=0; i < frags_id_to_sort.size(); i++)
+ full_predicted_order[frags_id_to_sort[i]] = (predicted_order[i]>0?1:-1) * (frags_id_to_sort.front() + std::abs(predicted_order[i]));
+ predicted_order = full_predicted_order;
+ }
+ for (s32 i = 0; i < num_frags; ++i) current_order[i] = {i+1, contigs_->contigs_arr[i].length}; // start from 1
+ auto move_current_order_element = [¤t_order, &num_frags](u32 from, u32 to)
+ {
+ if (from >= num_frags || to >= num_frags)
+ {
+ fprintf(stderr, "Invalid from(%d) or to(%d), index should betwee [0, %d].\n", from, to, num_frags-1);
+ return;
+ }
+ if (from == to) return;
+ auto tmp = current_order[from];
+ if (from > to)
+ {
+ for (u32 i = from; i > to; --i) current_order[i] = current_order[i-1];
+ }
+ else // to > from
+ {
+ for (u32 i = from; i < to; ++i) current_order[i] = current_order[i+1];
+ }
+ current_order[to] = tmp;
+ };
+
+ // update the map state based on the new order
+ for (u32 i = 0; i < num_frags; ++i)
+ {
+ if (predicted_order[i] == current_order[i].first) // leave the contig unchanged
+ {
+ start_loc += current_order[i].second;
+ continue;
+ }
- graph *gph = (graph *)node->extension;
- if (strcmp((char *)gph->name, "telomere") == 0)
- {
- gph->on = !gph->on;
- break;
- }
- }
- }
- }
- break;
- }
- else
- {
- ToggleToolTip(window);
- }
- break;
+ // only invert
+ if (predicted_order[i] == -current_order[i].first)
+ {
+ u32 pixelFrom = start_loc, pixelEnd= start_loc + current_order[i].second - 1;
+ InvertMap(pixelFrom, pixelEnd);
+ AddMapEdit(0, {start_loc, start_loc + current_order[i].second - 1}, true);
+ current_order[i].first = -current_order[i].first;
+ start_loc += current_order[i].second;
+ printf("[Pixel Sort] (#%d) Invert contig %d.\n", ++num_autoCurated_edits, predicted_order[i]);
+ continue;
+ }
+ else if (
+ predicted_order[i] != current_order[i].first &&
+ predicted_order[i] != -current_order[i].first) // move the contig to the new position
+ {
- case GLFW_KEY_U:
- UI_On = !UI_On;
- ++NK_Device->lastContextMemory[0];
- Mouse_Move.x = Mouse_Move.y = -1;
- break;
+ bool is_curated_inverted = predicted_order[i] < 0;
- case GLFW_KEY_V:
- break;
+ // find the pixel range of the contig to move
+ u32 pixelFrom = 0, tmp_i = 0; // tmp_i is the index of the current contig, which is going to be processed
+ while (std::abs(predicted_order[i])!=std::abs(current_order[tmp_i].first))
+ {
+ if (tmp_i >= num_frags)
+ {
+ char buff[256];
+ snprintf(buff, sizeof(buff), "Error: contig %d not found in the current order.\n", current_order[i].first);
+ MY_CHECK(buff);
+ assert(0);
+ }
+ pixelFrom += current_order[tmp_i].second; // length updated based on the current order
+ if (pixelFrom>=Number_of_Pixels_1D)
+ {
+ char buff[256];
+ snprintf(buff, sizeof(buff), "Error: pixelFrom(%d) >= Number_of_Pixels_1D(%d).\n", pixelFrom, Number_of_Pixels_1D);
+ MY_CHECK(buff);
+ assert(0);
+ }
+ ++tmp_i;
+ }
+ u32 pixelEnd = pixelFrom + current_order[tmp_i].second - 1;
+ if (is_curated_inverted)
+ {
+ InvertMap(pixelFrom, pixelEnd);
+ current_order[tmp_i].first = -current_order[tmp_i].first;
+ }
+ s32 delta = start_loc - pixelFrom;
+ RearrangeMap(pixelFrom, pixelEnd, delta);
+ AddMapEdit(delta, {(u32)((s32)pixelFrom + delta), (u32)((s32)pixelEnd + delta)}, is_curated_inverted);
- case GLFW_KEY_W:
- if (Edit_Mode || Select_Sort_Area_Mode)
- {
- RedoMapEdit();
- }
- else
- {
- keyPressed = ToggleWaypointMode(window);
- }
- break;
+ // update the current order, insert the contig to the new position
+ move_current_order_element(tmp_i, i); // move element from tmp_i to i
+ start_loc += current_order[i].second; // update start_loc after move fragments
+ if (is_curated_inverted)
+ {
+ printf("[Pixel Sort] (#%d) Invert and Move contig %d to %d, start_loc:%d.\n", ++num_autoCurated_edits, predicted_order[i], i, start_loc);
+ }
+ else printf("[Pixel Sort] (#%d) Move contig %d to %d, start_loc:%d.\n", ++num_autoCurated_edits, predicted_order[i], i, start_loc);
+ continue;
+ }
+ else
+ {
+ fprintf(stderr, "Unknown error, predicted_order[%d] = %d, current[%d] = %d.\n", i, predicted_order[i], i, current_order[i].first);
+ continue;
+ }
+ }
+ printf("[Pixel Sort] finished with %d edits\n", num_autoCurated_edits);
- case GLFW_KEY_X:
- keyPressed = ToggleExtensionMode(window);
- break;
+ return ;
+}
+
+
+global_function
+void
+auto_cut_func(
+ char * currFileName,
+ memory_arena* arena = nullptr,
+ std::string file_save_name = std::string("/auto_curation_tmp")
+)
+{
+ if (!currFileName || !auto_cut_state) return;
+
+ if (auto_cut_state == 2) // restore the cutted frags within the selected area
+ {
+ u32 start = auto_curation_state.get_start();
+ u32 end = auto_curation_state.get_end();
+ if (start < 0 || end < 0)
+ {
+ fmt::print(
+ stdout,
+ "Error: no area selected. start({}) or end({}) is less than 0\n",
+ start, end);
+ return ;
+ }
+ fmt::print(stdout, "[Pixel cut] restoring the cutted frags within the selected area: [{}, {}]\n", start, end);
+ Map_State->restore_cutted_contigs( start, end );
+ UpdateContigsFromMapState();
+ Redisplay = 1;
+ return ;
+ }
+
+ // classic cut
+ {
+ SelectArea selected_area;
+ auto_curation_state.get_selected_fragments(
+ selected_area,
+ Map_State,
+ Number_of_Pixels_1D,
+ Contigs);
+ glBindBuffer(GL_TEXTURE_BUFFER, Contact_Matrix->pixelRearrangmentLookupBuffer);
+ const u32 *pixel_rearrange_index = (const u32 *)glMapBufferRange(GL_TEXTURE_BUFFER, 0, Number_of_Pixels_1D * sizeof(u32), GL_MAP_READ_BIT);
+ std::vector cut_locs_pixel = frag_cut_cal_ptr->get_cut_locs_pixel(
+ auto_curation_state,
+ pixel_rearrange_index, // pixel_rearrangement_buffer
+ Contigs,
+ &selected_area
+ );
+ glUnmapBuffer(GL_TEXTURE_BUFFER);
+
+ fmt::print(stdout, "[Pixel cut] cut locs in pixel: [");
+ for (auto & i : cut_locs_pixel) fmt::print(stdout, "{} ", i);
+ fmt::print(stdout, "]\n");
+
+ // cut the contigs
+ cut_frags(cut_locs_pixel);
+ }
+
+ // AI cutting
+ // generate figures
+ if (0)
+ {
+ fprintf(stdout, "[Pixel cut] generating hic figures...\n");
+ Hic_Figure hic_figure(
+ Total_Genome_Length,
+ file_save_name,
+ textures_array_ptr );
+ hic_figure.generate_hic_figures();
+
+ // run ai model with python script
+ run_ai_detection();
+
+ // restore the error info via reading the error json
+ HIC_Problems hic_problems("/auto_curation_tmp/auto_cut_output/infer_result/infer_result.json", (f32) Total_Genome_Length / (f32)Number_of_Pixels_1D );
+ std::vector> problem_loc = hic_problems.get_problem_loci();
+
+ // cut the contigs
+ // cut_frags();
+ }
+
+ return ;
+}
+
+
+global_function
+std::unordered_map> collect_hap_cluster(
+ AutoCurationState& auto_curation_state,
+ const SelectArea& selected_area
+)
+{
+ std::unordered_map> hap_cluster;
+ if (!auto_curation_state.hap_cluster_flag) return hap_cluster;
+
+ for (const auto& i : selected_area.selected_frag_ids)
+ {
+ std::string original_contig_name = std::string((char*)(Original_Contigs+((Contigs->contigs_arr+i)->get_original_contig_id()))->name);
+ std::transform(original_contig_name.begin(), original_contig_name.end(), original_contig_name.begin(),
+ [](unsigned char c) { return std::tolower(c); });
+ if (original_contig_name.find("hap") != std::string::npos)
+ {
+ s32 hap_loc = original_contig_name.find("hap");
+ s32 hap_id = std::stoi(
+ original_contig_name.substr(
+ hap_loc + 3, original_contig_name.find_first_of("_", hap_loc + 3) - hap_loc - 3));
+ if (hap_cluster.find(hap_id) == hap_cluster.end())
+ {
+ hap_cluster[hap_id] = std::vector();
+ }
+ hap_cluster[hap_id].push_back(i - selected_area.selected_frag_ids[0]);
+ }else
+ {
+ fmt::print(
+ stdout,
+ "[Pixel Sort::Warning]: haplotig cluster is selected but the original contig name does not contain 'hap'.\n");
+ auto_curation_state.hap_cluster_flag = false;
+ break;
+ }
+ }
+ return hap_cluster;
+}
+
+
+
+
+global_function
+void
+auto_sort_func(char* currFileName)
+{
+ if (!currFileName || !auto_sort_state) return;
+
+ fprintf(stdout, "========================\n");
+ fprintf(stdout, "[Pixel Sort] start...\n");
+ fprintf(stdout, "[Pixel Sort] smallest_frag_size_in_pixel: %d\n", auto_curation_state.smallest_frag_size_in_pixel);
+ fprintf(stdout, "[Pixel Sort] link_score_threshold: %.3f\n", auto_curation_state.link_score_threshold);
+ fprintf(stdout, "[Pixel Sort] Sort mode: %s\n", auto_curation_state.get_sort_mode_name().c_str());
+ fmt::print(stdout, "[Pixel Sort] num_clusters: {}\n", auto_curation_state.num_clusters);
+
+ // compress the HiC data
+ // prepare before reading textures
+ f32 original_color_control_points[3];
+ prepare_before_copy(original_color_control_points);
+ textures_array_ptr->copy_buffer_to_textures_dynamic(
+ Contact_Matrix,
+ false // show_flag
+ );
+ restore_settings_after_copy(original_color_control_points);
+
+ // check if select the area for sorting
+ SelectArea selected_area;
+ auto_curation_state.get_selected_fragments( // consider wheather include the sink and source while calculating the selected area
+ selected_area,
+ Map_State,
+ Number_of_Pixels_1D,
+ Contigs
+ );
+
+ std::unordered_map> hap_cluster = collect_hap_cluster(auto_curation_state, selected_area);
+
+ bool hap_cluster_flag = (hap_cluster.size() > 1 && auto_curation_state.hap_cluster_flag);
+ // NOTE: if hap_cluster is selected, then the kmeans cluster is not needed
+ if (hap_cluster_flag) auto_curation_state.num_clusters = 1;
+ else auto_curation_state.hap_cluster_flag = false;
+ bool kmeans_cluster_flag = selected_area.selected_frag_ids.size() > std::max(auto_curation_state.min_frag_num_for_cluster, (s32)auto_curation_state.num_clusters)
+ && auto_curation_state.num_clusters > 1
+ && !hap_cluster_flag;
+
+ // correct the selected_area, wheather use or not use the source and sink
+ if ( hap_cluster_flag || kmeans_cluster_flag )
+ {
+ selected_area.source_frag_id = -1;
+ selected_area.sink_frag_id = -1;
+ }
+
+ if (auto_curation_state.get_start() >=0 && auto_curation_state.get_end() >= 0 && selected_area.selected_frag_ids.size() > 0)
+ {
+ fprintf(stdout, "[Pixel Sort] local sort within selected area\n");
+ fprintf(stdout, "[Pixel Sort] Selected pixel range: %d ~ %d\n", auto_curation_state.get_start(), auto_curation_state.get_end());
+ std::stringstream ss;
+ ss << selected_area.selected_frag_ids[0];
+ for (u32 i = 1; i < selected_area.selected_frag_ids.size(); ++i)
+ ss << ", " << selected_area.selected_frag_ids[i];
+ fmt::print(stdout, "[Pixel Sort] Selected fragments ({}): {}\n\n", selected_area.selected_frag_ids.size(), ss.str().c_str());
+ selected_area.select_flag = true;
+ selected_area.start_pixel = auto_curation_state.get_start();
+ selected_area.end_pixel = auto_curation_state.get_end();
+ }
+
+ textures_array_ptr->cal_compressed_hic(
+ Contigs,
+ Extensions,
+ false, // is_extension_required
+ false, // is_mass_center_required
+ &selected_area
+ );
+ std::vector exclude_tags = {"haplotig", "unloc"};
+ std::vector exclude_meta_tag_idx = get_exclude_metaData_idx(exclude_tags);
+
+ // cluster and sort
+ // 1. clustering
+ if (hap_cluster_flag || kmeans_cluster_flag )
+ {
+ std::vector> clusters;
+ if (kmeans_cluster_flag) // kmeans cluster
+ {
+ fmt::print(stdout,
+ "[Pixel Sort] kmeans: num of clusters: {}, num of selected fragments: {}\n", auto_curation_state.num_clusters,
+ selected_area.selected_frag_ids.size());
+ #ifdef PYTHON_SCOPED_INTERPRETER
+ if (kmeans_cluster && kmeans_cluster->is_init)
+ {
+ fmt::print(stdout, "[Pixel Sort] cluster with Python module.\n");
+ clusters = kmeans_cluster->kmeans_func(
+ auto_curation_state.num_clusters,
+ textures_array_ptr->get_compressed_hic());
+ } else
+ {
+ fmt::print(stdout, "[Pixel Sort::warning] Python clustering module initializing failed. Clustering with Eigen-based algorithm.\n");
+ clusters = spectral_clustering(*(textures_array_ptr->get_compressed_hic()), auto_curation_state.num_clusters);
+ }
+ #else
+ fmt::print(stdout, "[Pixel Sort::warning] Python clustering module initializing failed. Clustering with Eigen-based algorithm.\n");
+ clusters = spectral_clustering(*(textures_array_ptr->get_compressed_hic()), auto_curation_state.num_clusters);
+ #endif // PYTHON_SCOPED_INTERPRETER
+ } else // hap cluster
+ {
+ fmt::print(stdout,
+ "[Pixel Sort] haplotig cluster: num of haps: {}, num of selected fragments: {}\n",
+ hap_cluster.size(), selected_area.selected_frag_ids.size());
+ clusters.clear();
+ for (const auto& i : hap_cluster)
+ {
+ clusters.push_back(i.second);
+ }
+ }
+
+ // create the frag4compress object for sorting within the clusters
+ std::vector clusters_frags(clusters.size());
+ for (u32 i = 0; i < clusters.size(); ++i)
+ {
+ std::sort(clusters[i].begin(), clusters[i].end());
+ clusters_frags[i].re_allocate_mem(
+ Contigs,
+ clusters[i]);
+ }
+
+ #ifdef DEBUG
+ fmt::print(stdout, "[Pixel Sort]: Kmeans clusters size: {} \n", clusters.size());
+ for (u32 i = 0; i < clusters.size(); ++i)
+ {
+ auto& tmp = clusters[i];
+ fmt::print(stdout, "\t[{} ({})]: ", i, clusters[i].size());
+ if (tmp.size() > 0)
+ {
+ for (auto& tmp1 : tmp) fmt::print(stdout, "{}, ", tmp1);
+ }
+ fmt::print(stdout, "\n");
+ }
+ fmt::print(stdout, "\n");
+ #endif // DEBUG
+
+ // 3. sort within the clusters
+ std::vector frags_order_list;
+ for (u32 i = 0; i < clusters.size(); ++i)
+ {
+ frags_order_list.push_back(FragsOrder(clusters[i].size()));
+ }
+ for (u32 i = 0; i < clusters.size(); ++i)
+ {
+ // every cluster forms a likelihood table
+ if (clusters[i].size() < 2)
+ continue;
+ auto tmp_likelihood_table = LikelihoodTable(
+ &clusters_frags[i],
+ textures_array_ptr->get_compressed_hic(),
+ (f32)auto_curation_state.smallest_frag_size_in_pixel / ((f32)Number_of_Pixels_1D + 1.f),
+ exclude_meta_tag_idx,
+ Number_of_Pixels_1D,
+ &clusters[i]
+ );
+ frag_sort_method->sort_method_mask(
+ tmp_likelihood_table,
+ frags_order_list[i],
+ selected_area,
+ auto_curation_state,
+ &clusters_frags[i],
+ true
+ );
+ }
+ // merge all clusters
+ FragsOrder merged_frags_order(frags_order_list, clusters);
+
+ #ifdef DEBUG
+ merged_frags_order.print_order() ;
+ #endif // DEBUG
+
+ AutoCurationFromFragsOrder(
+ &merged_frags_order,
+ Contigs,
+ Map_State,
+ &selected_area);
+
+ // evaluate the compressed hic between all of the clusters
+
+ // 4. sort the clusters
+ }
+ else // sort without clustering
+ {
+ if (auto_curation_state.num_clusters == 1)
+ {
+ fmt::print(stdout, "[Pixel Sort] sort without clustering.\n");
+ } else // (selected_area.selected_frag_ids.size() <= std::max(auto_curation_state.min_frag_num_for_cluster, (s32)auto_curation_state.num_clusters) )
+ {
+ fmt::print(
+ stdout,
+ "[Pixel Sort] num_cluster({})>1 but selected fragments({}) <= max(min_num_frags_for_cluster {}, num_cluster {})\n",
+ auto_curation_state.num_clusters,
+ selected_area.selected_frag_ids.size(),
+ auto_curation_state.min_frag_num_for_cluster,
+ auto_curation_state.num_clusters);
+ }
+
+ FragsOrder frags_order(textures_array_ptr->get_num_frags()); // intilize the frags_order with the number of fragments including the filtered out ones
+ // exclude the fragments with first two tags during the auto curation
+ LikelihoodTable likelihood_table(
+ textures_array_ptr->get_frags(),
+ textures_array_ptr->get_compressed_hic(),
+ (f32)auto_curation_state.smallest_frag_size_in_pixel / ((f32)Number_of_Pixels_1D + 1.f),
+ exclude_meta_tag_idx,
+ Number_of_Pixels_1D);
+
+ #ifdef DEBUG_OUTPUT_LIKELIHOOD_TABLE
+ likelihood_table.output_fragsInfo_likelihoodTable("frags_info_likelihood_table.txt", textures_array_ptr->get_compressed_hic());
+ #endif // DEBUG_OUTPUT_LIKELIHOOD_TABLE
+
+ // use the compressed_hic to calculate the frags_order directly
+ frag_sort_method->sort_method_mask(
+ likelihood_table,
+ frags_order,
+ selected_area,
+ auto_curation_state,
+ textures_array_ptr->get_frags(),
+ true // sort chromosomes according length
+ );
+
+ AutoCurationFromFragsOrder(
+ &frags_order,
+ Contigs,
+ Map_State,
+ &selected_area
+ );
+ }
+
+ std::cout << std::endl;
+ auto_sort_state = 0;
+
+ // clear mem for textures and compressed hic
+ textures_array_ptr->clear_textures();
+ textures_array_ptr->clear_compressed_hic();
+ return;
+}
+
+
+// set the vertex array for the contact matrix
+// copy_flag: if true, set vaos to [-1, 1, -1, 1] for copying tiles from opengl buffer to cpu memory
+global_function
+void setContactMatrixVertexArray(
+ contact_matrix* Contact_Matrix_,
+ bool copy_flag,
+ bool regenerate_flag)
+{
+ glUseProgram(Contact_Matrix_->shaderProgram);
+ GLuint posAttrib = (GLuint)glGetAttribLocation(Contact_Matrix_->shaderProgram, "position");
+ GLuint texAttrib = (GLuint)glGetAttribLocation(Contact_Matrix_->shaderProgram, "texcoord");
+
+ /*
+ 从左上到右下开始遍历,见上述编号
+ */
+ f32 x = -0.5f;
+ f32 y = 0.5f;
+ f32 quadSize = 1.0f / (f32)Number_of_Textures_1D; // 1.0 / 32.f = 0.03125
+ f32 allCornerCoords[2][2] = {{0.0f, 1.0f}, {1.0f, 0.0f}};
+
+ if (regenerate_flag) // first delete the generated vertex array objects and buffers
+ {
+ glDeleteVertexArrays((GLsizei)(Number_of_Textures_1D * Number_of_Textures_1D), Contact_Matrix->vaos);
+ glDeleteBuffers((GLsizei)(Number_of_Textures_1D * Number_of_Textures_1D), Contact_Matrix->vbos);
+ }
+
+ u32 ptr = 0;
+ ForLoop(Number_of_Textures_1D)
+ {
+ ForLoop2(Number_of_Textures_1D)
+ {
+ tex_vertex textureVertices[4];
+
+ glGenVertexArrays( // 生成对象的名称,
+ 1, // 生成的个数
+ Contact_Matrix_->vaos + ptr); // 存储位置的指针
+ glBindVertexArray(Contact_Matrix_->vaos[ptr]); // 绑定顶点名称
+
+ f32 *cornerCoords = allCornerCoords[index2 >= index ? 0 : 1]; // 包含对角线的上三角的时候取第一行{0, 1},否则取第二行{1, 0} 为了解决关于对角线对称
+
+ u32 min = my_Min(index, index2);
+ u32 max = my_Max(index, index2);
+ /*
+ 对称性编号
+ [[ 0 1 2 3 4 5 6 7 8 9]
+ [ 1 10 11 12 13 14 15 16 17 18]
+ [ 2 11 19 20 21 22 23 24 25 26]
+ [ 3 12 20 27 28 29 30 31 32 33]
+ [ 4 13 21 28 34 35 36 37 38 39]
+ [ 5 14 22 29 35 40 41 42 43 44]
+ [ 6 15 23 30 36 41 45 46 47 48]
+ [ 7 16 24 31 37 42 46 49 50 51]
+ [ 8 17 25 32 38 43 47 50 52 53]
+ [ 9 18 26 33 39 44 48 51 53 54]]
+ */
+ f32 texture_index_symmetric = (f32)((min * (Number_of_Textures_1D - 1))
+ - (((min-1) * min) >> 1 )
+ + max) ;
+
+ /*
+ 3 2
+ 0 1
+ */
+ f32 half_len = 1.0f;
+ textureVertices[0].x = !copy_flag? x : -half_len; // x -> [-0.5, 0.5]
+ textureVertices[0].y = !copy_flag? y - quadSize : -half_len; // y -> [-0.5, 0.5]
+ textureVertices[0].s = !copy_flag? cornerCoords[0] : 0.f; // s表示texture的水平分量
+ textureVertices[0].t = !copy_flag? cornerCoords[1] : 0.f; // t表示texture的垂直分量
+ textureVertices[0].u = texture_index_symmetric;
- case GLFW_KEY_Y:
- break;
+ textureVertices[1].x = !copy_flag? x + quadSize : half_len;
+ textureVertices[1].y = !copy_flag? y - quadSize : -half_len;
+ textureVertices[1].s = !copy_flag? 1.0f : 1.f;
+ textureVertices[1].t = !copy_flag? 1.0f : 0.f;
+ textureVertices[1].u = texture_index_symmetric;
- case GLFW_KEY_Z:
- if (Select_Sort_Area_Mode)
- {
- auto_cut_state = 2; // restore the cutted frags within the selected area
- }
- break;
+ textureVertices[2].x = !copy_flag? x + quadSize : half_len;
+ textureVertices[2].y = !copy_flag? y : half_len;
+ textureVertices[2].s = !copy_flag? cornerCoords[1] : 1.f;
+ textureVertices[2].t = !copy_flag? cornerCoords[0] : 1.f;
+ textureVertices[2].u = texture_index_symmetric;
- case GLFW_KEY_SPACE:
- if (Edit_Mode && !Edit_Pixels.editing && action == GLFW_PRESS)
- {
- Edit_Pixels.selecting = 1;
- Edit_Pixels.selectPixels = Edit_Pixels.pixels;
- f64 x, y;
- glfwGetCursorPos(window, &x, &y);
- MouseMove(window, x, y);
- }
- else if (Edit_Mode && !Edit_Pixels.editing && action == GLFW_RELEASE)
- {
- Edit_Pixels.editing = 1;
- Edit_Pixels.selecting = 0;
- f64 x, y;
- glfwGetCursorPos(window, &x, &y);
- MouseMove(window, x, y);
- }
- else if (Edit_Mode && Edit_Pixels.editing && action == GLFW_PRESS)
- {
- InvertMap(Edit_Pixels.pixels.x, Edit_Pixels.pixels.y);
- Global_Edit_Invert_Flag = !Global_Edit_Invert_Flag;
- }
- else if (Waypoint_Edit_Mode && Selected_Waypoint && action == GLFW_PRESS)
- {
- f64 x, y;
- glfwGetCursorPos(window, &x, &y);
- RemoveWayPoint(Selected_Waypoint);
- MouseMove(window, x, y);
- }
- else if (Scaff_Edit_Mode && (action == GLFW_PRESS || action == GLFW_RELEASE))
- {
- f64 x, y;
- glfwGetCursorPos(window, &x, &y);
- Scaff_Painting_Flag = action == GLFW_PRESS ? 2 : 0;
- MouseMove(window, x, y);
- if (action == GLFW_RELEASE) UpdateScaffolds();
- }
- else if (MetaData_Edit_Mode && (action == GLFW_PRESS || action == GLFW_RELEASE))
- {
- f64 x, y;
- glfwGetCursorPos(window, &x, &y);
- MetaData_Edit_State = action == GLFW_PRESS ? 2 : 0;
- MouseMove(window, x, y);
- }
- else if (Select_Sort_Area_Mode && action == GLFW_PRESS)
- {
- u32 selected_frag_num = auto_curation_state.get_selected_fragments_num(Map_State, Number_of_Pixels_1D);
- if (selected_frag_num >= 2)
- {
- auto_sort_state = 1;
- }
- }
- else
- {
- keyPressed = 0;
- }
- break;
-
- case GLFW_KEY_LEFT_SHIFT:
- if (Scaff_Edit_Mode)
- {
- if (action != GLFW_RELEASE) Scaff_FF_Flag |= 2;
- else Scaff_FF_Flag &= ~2;
- }
- else if (Edit_Mode) Edit_Pixels.scaffSelecting = action != GLFW_RELEASE;
- else keyPressed = 0;
- break;
+ textureVertices[3].x = !copy_flag? x : -half_len;
+ textureVertices[3].y = !copy_flag? y : half_len;
+ textureVertices[3].s = !copy_flag? 0.0f : 0.f;
+ textureVertices[3].t = !copy_flag? 0.0f : 1.f;
+ textureVertices[3].u = texture_index_symmetric;
- case GLFW_KEY_LEFT:
- if (MetaData_Edit_Mode)
- {
- u32 nextActive = MetaData_Active_Tag;
- ForLoop(ArrayCount(Meta_Data->tags))
- {
- if (--nextActive > (ArrayCount(Meta_Data->tags) - 1)) nextActive = ArrayCount(Meta_Data->tags) - 1;
- if (strlen((const char *)Meta_Data->tags[nextActive]))
- {
- MetaData_Active_Tag = nextActive;
- break;
- }
- }
+ glGenBuffers( // 生成buffer的名字 存储在contact_matrix->vbos+ptr 对应的地址上
+ 1, // 个数
+ Contact_Matrix_->vbos + ptr); // 指针,存储生成的名字
+ glBindBuffer( // 绑定到一个已经命名的buffer对象上
+ GL_ARRAY_BUFFER, // 绑定的对象,gl_array_buffer 一般是绑定顶点的信息
+ Contact_Matrix_->vbos[ptr]); // 通过输入buffer的名字将其绑定到gl_array_buffer
+ glBufferData( // 创建、初始化存储数据的buffer
+ GL_ARRAY_BUFFER, // 绑定的对象,gl_array_buffer 一般是绑定顶点的信息
+ 4 * sizeof(tex_vertex), // 对象的大小(bytes)
+ textureVertices, // 即将绑定到gl_array_buffer的数据的指针
+ GL_STATIC_DRAW); // 绑定后的数据是用于干什么的
+
+ // tell GL how to interpret the data in the GL_ARRAY_BUFFER
+ glEnableVertexAttribArray(posAttrib);
+ glVertexAttribPointer( // 定义一个数组存储所有的通用顶点属性
+ posAttrib, // 即将修改属性的索引
+ 2, // 定义每个属性的参数的个数, 只能为1 2 3 4中的一个,初始值为4
+ GL_FLOAT, // 定义该属性的数据类型,则数据为4个字节, 占用两个的话,则一共为8字节
+ GL_FALSE, // normalized, 是否要在取用的时候规范化这些数
+ sizeof(tex_vertex), // stride 定义从一个信息的指针下一个信息指针的bytes的间隔, 一个信息包到下一个信息包的长度
+ 0); // const void* 指定当前与 GL_ARRAY_BUFFER 绑定的缓冲区数据头指针偏移多少个到 第一个通用顶点属性的第一个特征开始的位置。 初始值为 0。因为此处想要读取的信息为 x 和 y
+ glEnableVertexAttribArray(texAttrib); //
+ glVertexAttribPointer(
+ texAttrib,
+ 3,
+ GL_FLOAT, // 定义每个属性的数据类型
+ GL_FALSE, // GL_FALSE, GL_TRUE
+ sizeof(tex_vertex),
+ (void *)(3 * sizeof(GLfloat))); // 偏移量为3,因为前三个为x, y and pad, 想要读取的数据为 s, t and u
- }
- else if (Select_Sort_Area_Mode)
- {
- auto_curation_state.change_sort_mode(-1);
- }
- else AdjustColorMap(-1);
- break;
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Quad_EBO);
- case GLFW_KEY_RIGHT:
- if (MetaData_Edit_Mode)
- {
- u32 nextActive = MetaData_Active_Tag;
- ForLoop(ArrayCount(Meta_Data->tags))
- {
- if (++nextActive == ArrayCount(Meta_Data->tags)) nextActive = 0;
- if (strlen((const char *)Meta_Data->tags[nextActive]))
- {
- MetaData_Active_Tag = nextActive;
- break;
- }
- }
- }
- else if (Select_Sort_Area_Mode)
- {
- auto_curation_state.change_sort_mode(1);
- }
- else AdjustColorMap(1);
- break;
+ x += quadSize; // next column
+ ++ptr; // ptr for current texture
+ }
- case GLFW_KEY_UP:
- if (Select_Sort_Area_Mode)
- {
- auto_curation_state.adjust_cut_threshold(1);
- }
- else NextColorMap(1);
- break;
+ y -= quadSize; // next row
+ x = -0.5f; // from column 0
+ }
+}
- case GLFW_KEY_DOWN:
- if (Select_Sort_Area_Mode)
- {
- auto_curation_state.adjust_cut_threshold(-1);
- }
- else
- NextColorMap(-1);
- break;
-#ifdef Internal
- case GLFW_KEY_ESCAPE:
- if (!mods)
- {
- glfwSetWindowShouldClose(window, GLFW_TRUE);
- }
- break;
-#endif
- case GLFW_KEY_ENTER:
- if (mods == GLFW_MOD_ALT)
- {
- if (glfwGetWindowMonitor(window))
- {
- glfwSetWindowMonitor(window, NULL,
- Windowed_Xpos, Windowed_Ypos,
- Windowed_Width, Windowed_Height, 0);
- }
- else
- {
- GLFWmonitor* monitor = glfwGetPrimaryMonitor();
- if (monitor)
- {
- const GLFWvidmode* mode = glfwGetVideoMode(monitor);
- glfwGetWindowPos(window, &Windowed_Xpos, &Windowed_Ypos);
- glfwGetWindowSize(window, &Windowed_Width, &Windowed_Height);
- glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
- }
- }
- }
- else
- {
- keyPressed = 0;
- }
- break;
- default:
- keyPressed = 0;
- }
+global_function
+void
+prepare_before_copy(f32 *original_color_control_points)
+{
+ // prepare before reading textures
+ glActiveTexture(GL_TEXTURE1);
- if (keyPressed)
- {
- Redisplay = 1;
- }
- }
- }
+ glBindTexture(GL_TEXTURE_BUFFER, Color_Maps->maps[Color_Maps->nMaps-1]); // 绑定到颜色映射的最后一个颜色
+ glActiveTexture(GL_TEXTURE0);
+ for (u32 i = 0; i < 3 ; i ++ )
+ original_color_control_points[i] = Color_Maps->controlPoints[i];
+ Color_Maps->controlPoints[0] = 0.0f;
+ Color_Maps->controlPoints[1] = 0.5f;
+ Color_Maps->controlPoints[2] = 1.0f;
+ glUseProgram(Contact_Matrix->shaderProgram);
+ glUniform3fv( Color_Maps->cpLocation, 1, Color_Maps->controlPoints);
+ setContactMatrixVertexArray(Contact_Matrix, true, true); // set the vertex for copying
+ return ;
}
+
global_function
-void
-ErrorCallback(s32 error, const char *desc)
+void
+restore_settings_after_copy(const f32 *original_color_control_points)
{
- (void)error;
- fprintf(stderr, "Error: %s\n", desc);
+ // restore settings
+ setContactMatrixVertexArray(Contact_Matrix, false, true); // restore the vertex array for rendering
+ for (u32 i = 0 ; i < 3 ; i ++ )
+ Color_Maps->controlPoints[i] = original_color_control_points[i];
+ glUseProgram(Contact_Matrix->shaderProgram);
+ glUniform3fv( Color_Maps->cpLocation, 1, Color_Maps->controlPoints);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_BUFFER, Color_Maps->maps[Color_Maps->currMap]);
+ glActiveTexture(GL_TEXTURE0);
}
-// File Browser
-// from nuklear file browser example
-/* ===============================================================
- *
- * GUI
- *
- * ===============================================================*/
-struct
-icons
-{
- struct nk_image home;
- struct nk_image computer;
- struct nk_image directory;
- struct nk_image default_file;
- struct nk_image img_file;
-};
+static f32 camera_pos_before_jump[] = {-1000.f, -1000.f};
-enum
-file_groups
-{
- FILE_GROUP_DEFAULT,
- FILE_GROUP_PRETEXT,
- FILE_GROUP_MAX
-};
-enum
-file_types
-{
- FILE_DEFAULT,
- FILE_PRETEXT,
- FILE_PSTM,
- FILE_MAX
-};
+global_function void
+JumpToDiagonal(GLFWwindow *window)
+{
+ // save the current camera position before jumping
+ camera_pos_before_jump[0] = Camera_Position.x;
+ camera_pos_before_jump[1] = Camera_Position.y;
+ // jump to the diagonal position
+ Camera_Position.x = -Camera_Position.y;
+ ClampCamera();
+ Redisplay = 1;
+}
-struct
-file_group
+global_function void
+jump_back_pos_before_jump(GLFWwindow *window)
{
- enum file_groups group;
- u32 pad;
- const char *name;
- struct nk_image *icon;
-};
+ if (camera_pos_before_jump[0] > -999.f && camera_pos_before_jump[1] > -999.f) {
+ Camera_Position.x = camera_pos_before_jump[0];
+ Camera_Position.y = camera_pos_before_jump[1];
+ ClampCamera();
+ Redisplay = 1;
+ }
+ else {
+ fmt::print(stderr, "[Jump::warning] No saved position to jump back.\n");
+ }
+}
-struct
-file
-{
- enum file_types type;
- enum file_groups group;
- const char *suffix;
-};
-struct
-media
+global_function
+u32
+ToggleEditMode(GLFWwindow* window)
{
- int font;
- int icon_sheet;
- struct icons icons;
- struct file_group group[FILE_GROUP_MAX];
- struct file files[FILE_MAX];
-};
+ u32 result = 1;
-#define MAX_PATH_LEN 512
-struct
-file_browser
+ if (Edit_Mode && !Edit_Pixels.editing)
+ {
+ Edit_Pixels.scaffSelecting = 0;
+ Global_Mode = mode_normal;
+ if (Tool_Tip->on)
+ {
+ f64 mousex, mousey;
+ glfwGetCursorPos(window, &mousex, &mousey);
+ MouseMove(window, mousex, mousey);
+ }
+ }
+ else if (Normal_Mode || Select_Sort_Area_Mode || MetaData_Edit_Mode)
+ {
+ Global_Mode = mode_edit;
+ }
+ else
+ {
+ result = 0;
+ }
+
+ return(result);
+}
+
+
+global_function
+ u32
+ ToggleExtensionMode(GLFWwindow *window)
{
- /* path */
- char file[MAX_PATH_LEN];
- char home[MAX_PATH_LEN];
- char directory[MAX_PATH_LEN];
+ u32 result = 1;
- /* directory content */
- char **files;
- char **directories;
- size_t file_count;
- size_t dir_count;
- struct media *media;
-};
+ if (Extension_Mode)
+ {
+ Global_Mode = mode_normal;
+ }
+ else if (Normal_Mode)
+ {
+ Global_Mode = mode_extension;
+ }
+ else
+ {
+ result = 0;
+ }
-#if defined __unix__ || defined __APPLE__
-#include
-#include
-#endif
+ return result;
+}
-#ifndef _WIN32
-#include
-#endif
global_function
-char*
-StrDuplicate(const char *src)
+u32
+ToggleWaypointMode(GLFWwindow* window)
{
- char *ret;
- size_t len = strlen(src);
- if (!len) return 0;
- ret = (char*)malloc(len+1);
- if (!ret) return 0;
- memcpy(ret, src, len);
- ret[len] = '\0';
- return ret;
+ u32 result = 1;
+
+ if (Waypoint_Edit_Mode)
+ {
+ Global_Mode = mode_normal;
+ if (Tool_Tip->on)
+ {
+ f64 mousex, mousey;
+ glfwGetCursorPos(window, &mousex, &mousey);
+ MouseMove(window, mousex, mousey);
+ }
+ }
+ else if (Normal_Mode)
+ {
+ Global_Mode = mode_waypoint_edit;
+ f64 mousex, mousey;
+ glfwGetCursorPos(window, &mousex, &mousey);
+ MouseMove(window, mousex, mousey);
+ }
+ else
+ {
+ result = 0;
+ }
+
+ return(result);
}
global_function
-void
-DirFreeList(char **list, size_t size)
+u32
+ToggleScaffMode(GLFWwindow* window)
{
- size_t i;
- for (i = 0; i < size; ++i)
- free(list[i]);
- free(list);
+ u32 result = 1;
+
+ if (Scaff_Edit_Mode && !Scaff_Painting_Flag)
+ {
+ Global_Mode = mode_normal;
+ Scaff_Painting_Flag = 0;
+ Scaff_Painting_Id = 0;
+ Scaff_FF_Flag = 0;
+ if (Tool_Tip->on)
+ {
+ f64 mousex, mousey;
+ glfwGetCursorPos(window, &mousex, &mousey);
+ MouseMove(window, mousex, mousey);
+ }
+ }
+ else if (Normal_Mode)
+ {
+ Global_Mode = mode_scaff_edit;
+ f64 mousex, mousey;
+ glfwGetCursorPos(window, &mousex, &mousey);
+ MouseMove(window, mousex, mousey);
+ }
+ else
+ {
+ result = 0;
+ }
+
+ return(result);
}
global_function
u32
-StringIsLexBigger(char *string, char *toCompareTo)
+ToggleMetaDataMode(GLFWwindow* window)
+{
+ u32 result = 1;
+
+ if (MetaData_Edit_Mode)
+ {
+ Global_Mode = mode_normal;
+ if (Tool_Tip->on)
+ {
+ f64 mousex, mousey;
+ glfwGetCursorPos(window, &mousex, &mousey);
+ MouseMove(window, mousex, mousey);
+ }
+ }
+ else if (Normal_Mode || (Edit_Mode && !Edit_Pixels.editing) || Select_Sort_Area_Mode)
+ {
+ Global_Mode = mode_meta_edit;
+ f64 mousex, mousey;
+ glfwGetCursorPos(window, &mousex, &mousey);
+ MouseMove(window, mousex, mousey);
+ }
+ else
+ {
+ result = 0;
+ }
+
+ return(result);
+}
+
+
+global_function
+u32
+ToggleSelectSortAreaMode(GLFWwindow* window)
{
- u32 result;
- u32 equal;
+ u32 result = 1;
- do
+ if (Select_Sort_Area_Mode)
{
- equal = *string == *toCompareTo;
- result = *string > *(toCompareTo++);
- } while (equal && (*(string++) != '\0'));
+ Global_Mode = mode_normal;
+ if (Tool_Tip->on)
+ {
+ f64 mousex, mousey;
+ glfwGetCursorPos(window, &mousex, &mousey);
+ MouseMove(window, mousex, mousey);
+ }
+ }
+ else if (Normal_Mode || (Edit_Mode && !Edit_Pixels.editing) || MetaData_Edit_Mode)
+ {
+ Global_Mode = mode_select_sort_area;
+ f64 mousex, mousey;
+ glfwGetCursorPos(window, &mousex, &mousey);
+ MouseMove(window, mousex, mousey);
+ }
+ else
+ {
+ result = 0;
+ }
return(result);
+
}
+
+
global_function
void
-CharArrayBubbleSort(char **list, u32 size)
+ToggleToolTip(GLFWwindow* window)
{
- while (size > 1)
+ Tool_Tip->on = !Tool_Tip->on;
+ if (Tool_Tip->on)
{
- u32 newSize = 0;
- ForLoop(size - 1)
- {
- if (StringIsLexBigger(list[index], list[index + 1]))
- {
- char *tmp = list[index];
- list[index] = list[index + 1];
- list[index + 1] = tmp;
- newSize = index + 1;
- }
- }
- size = newSize;
+ f64 mousex, mousey;
+ glfwGetCursorPos(window, &mousex, &mousey);
+ MouseMove(window, mousex, mousey);
}
}
-global_function
-char**
-DirList(const char *dir, u32 return_subdirs, size_t *count)
+#if 0
+enum
+MouseButon
{
- size_t n = 0;
- char buffer[MAX_PATH_LEN];
- char **results = NULL;
-#ifndef _WIN32
- const DIR *none = NULL;
- DIR *z;
-#else
- WIN32_FIND_DATA ffd;
- HANDLE hFind = INVALID_HANDLE_VALUE;
- char dirBuff[MAX_PATH_LEN];
-#endif
- size_t capacity = 32;
- size_t size;
+ left,
+ right,
+ middle,
+};
- Assert(dir);
- Assert(count);
- strncpy(buffer, dir, MAX_PATH_LEN);
- n = strlen(buffer);
+struct
+KeyBindings
+{
+ s32 ui;
+ s32 editMode;
+ s32 waypointMode;
+ s32 undoEdit;
+ s32 redoEdit;
+ s32 selectWholeSeq_key;
+ MouseButon selectWholeSeq_mouse;
-#ifndef _WIN32
- if (n > 0 && (buffer[n-1] != '/'))
- buffer[n++] = '/';
-#else
- if (n > 0 && (buffer[n-1] != '\\'))
- buffer[n++] = '\\';
+};
#endif
- size = 0;
+global_variable
+s32
+Windowed_Xpos, Windowed_Ypos, Windowed_Width, Windowed_Height;
-#ifndef _WIN32
- z = opendir(dir);
-#else
- strncpy(dirBuff, buffer, MAX_PATH_LEN);
- dirBuff[n] = '*';
- hFind = FindFirstFile(dirBuff, &ffd);
-#endif
-
-#ifndef _WIN32
- if (z != none)
-#else
- if (hFind != INVALID_HANDLE_VALUE)
+#if 0
+struct
+GLFWKeyAndScancode
+{
+ s32 key;
+ s32 scancode;
+};
+
+global_variable
+GLFWKeyAndScancode
+LastPressedKey = {0, 0};
#endif
+
+global_variable
+nk_keys
+NK_Pressed_Keys[1024] = {};
+
+global_variable
+u32
+NK_Pressed_Keys_Ptr = 0;
+
+global_variable
+u32
+GatheringTextInput = 0;
+
+global_function
+void
+KeyBoard(GLFWwindow* window, s32 key, s32 scancode, s32 action, s32 mods)
+{
+ if (!Loading && !auto_sort_state && !auto_cut_state && (action != GLFW_RELEASE || key == GLFW_KEY_SPACE || key == GLFW_KEY_A || key == GLFW_KEY_LEFT_SHIFT))
{
-#ifndef _WIN32
- u32 nonempty = 1;
- struct dirent *data = readdir(z);
- nonempty = (data != NULL);
- if (!nonempty) return NULL;
-#endif
- do
+ if (UI_On)
{
-#ifndef _WIN32
- DIR *y;
-#endif
- char *p;
- u32 is_subdir;
-#ifndef _WIN32
- if (data->d_name[0] == '.')
+#if 0
+ LastPressedKey.key = key;
+ LastPressedKey.scancode = scancode;
#else
- if (ffd.cFileName[0] == '.')
+ (void)scancode;
#endif
- continue;
-#ifndef _WIN32
- strncpy(buffer + n, data->d_name, MAX_PATH_LEN-n);
- y = opendir(buffer);
- is_subdir = (y != NULL);
- if (y != NULL) closedir(y);
-#else
- strncpy(buffer + n, ffd.cFileName, MAX_PATH_LEN-n);
- is_subdir = ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
+ if (key == GLFW_KEY_ENTER && mods == GLFW_MOD_ALT)
+ {
+ if (glfwGetWindowMonitor(window))
+ {
+ glfwSetWindowMonitor(window, NULL,
+ Windowed_Xpos, Windowed_Ypos,
+ Windowed_Width, Windowed_Height, 0);
+ }
+ else
+ {
+ GLFWmonitor* monitor = glfwGetPrimaryMonitor();
+ if (monitor)
+ {
+ const GLFWvidmode* mode = glfwGetVideoMode(monitor);
+ glfwGetWindowPos(window, &Windowed_Xpos, &Windowed_Ypos);
+ glfwGetWindowSize(window, &Windowed_Width, &Windowed_Height);
+ glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
+ }
+ }
+ }
+#ifdef Internal
+ else if (key == GLFW_KEY_ESCAPE && !mods)
+ {
+ glfwSetWindowShouldClose(window, GLFW_TRUE);
+ }
#endif
+ /*nk_input_key(NK_Context, NK_KEY_DEL, glfwGetKey(window, GLFW_KEY_DELETE) == GLFW_PRESS);
+ nk_input_key(NK_Context, NK_KEY_ENTER, glfwGetKey(window, GLFW_KEY_ENTER) == GLFW_PRESS);
+ nk_input_key(NK_Context, NK_KEY_TAB, glfwGetKey(window, GLFW_KEY_TAB) == GLFW_PRESS);
+ nk_input_key(NK_Context, NK_KEY_BACKSPACE, glfwGetKey(window, GLFW_KEY_BACKSPACE) == GLFW_PRESS);
+ nk_input_key(NK_Context, NK_KEY_LEFT, glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS);
+ nk_input_key(NK_Context, NK_KEY_RIGHT, glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS);
+ nk_input_key(NK_Context, NK_KEY_UP, glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS);
+ nk_input_key(NK_Context, NK_KEY_DOWN, glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS);
+
+ if (glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS || glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS)
+ {
+ nk_input_key(NK_Context, NK_KEY_COPY, glfwGetKey(window, GLFW_KEY_C) == GLFW_PRESS);
+ nk_input_key(NK_Context, NK_KEY_PASTE, glfwGetKey(window, GLFW_KEY_P) == GLFW_PRESS);
+ nk_input_key(NK_Context, NK_KEY_CUT, glfwGetKey(window, GLFW_KEY_X) == GLFW_PRESS);
+ nk_input_key(NK_Context, NK_KEY_CUT, glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS);
+ nk_input_key(NK_Context, NK_KEY_SHIFT, 1);
+ }
+ else
+ {
+ nk_input_key(NK_Context, NK_KEY_COPY, 0);
+ nk_input_key(NK_Context, NK_KEY_PASTE, 0);
+ nk_input_key(NK_Context, NK_KEY_CUT, 0);
+ nk_input_key(NK_Context, NK_KEY_SHIFT, 0);
+ }*/
+
+
+ else if (key == GLFW_KEY_U)
+ {
+ Deferred_Close_UI = 1;
+ }
+ else if (action != GLFW_RELEASE && !GatheringTextInput)
+ {
+ nk_keys addKey = NK_KEY_NONE;
+ switch (key)
+ {
+ case GLFW_KEY_DELETE:
+ addKey = NK_KEY_DEL;
+ break;
+
+ case GLFW_KEY_ENTER:
+ addKey = NK_KEY_ENTER;
+ break;
+
+ case GLFW_KEY_TAB:
+ addKey = NK_KEY_TAB;
+ break;
+
+ case GLFW_KEY_BACKSPACE:
+ addKey = NK_KEY_BACKSPACE;
+ break;
+
+ case GLFW_KEY_LEFT:
+ addKey = NK_KEY_LEFT;
+ break;
+
+ case GLFW_KEY_RIGHT:
+ addKey = NK_KEY_RIGHT;
+ break;
+
+ case GLFW_KEY_UP:
+ addKey = NK_KEY_UP;
+ break;
+
+ case GLFW_KEY_DOWN:
+ addKey = NK_KEY_DOWN;
+ break;
+ }
- if ((return_subdirs && is_subdir) || (!is_subdir && !return_subdirs))
- {
- if (!size)
- {
- results = (char**)calloc(sizeof(char*), capacity);
- }
- else if (size >= capacity)
+ if (addKey != NK_KEY_NONE)
{
- void *old = results;
- capacity = capacity * 2;
- results = (char**)realloc(results, capacity * sizeof(char*));
- Assert(results);
- if (!results) free(old);
+ NK_Pressed_Keys[NK_Pressed_Keys_Ptr++] = addKey;
+ if (NK_Pressed_Keys_Ptr == ArrayCount(NK_Pressed_Keys)) NK_Pressed_Keys_Ptr = 0;
}
-#ifndef _WIN32
- p = StrDuplicate(data->d_name);
-#else
- p = StrDuplicate(ffd.cFileName);
-#endif
- results[size++] = p;
}
-#ifndef _WIN32
- } while ((data = readdir(z)) != NULL);
-#else
- } while (FindNextFile(hFind, &ffd) != 0);
-#endif
- }
+ }
+ else // not UI_On
+ {
+ u32 keyPressed = 1;
-#ifndef _WIN32
- if (z) closedir(z);
-#else
- FindClose(hFind);
-#endif
- *count = size;
-
- CharArrayBubbleSort(results, (u32)size);
-
- return results;
-}
+ switch (key)
+ {
+
+ case GLFW_KEY_A:
+ if (Scaff_Edit_Mode)
+ {
+ if (action != GLFW_RELEASE) Scaff_FF_Flag |= 1;
+ else Scaff_FF_Flag &= ~1;
+ }
+ else keyPressed = 0;
+ break;
-global_function
-struct file_group
-FILE_GROUP(enum file_groups group, const char *name, struct nk_image *icon)
-{
- struct file_group fg;
- fg.group = group;
- fg.name = name;
- fg.icon = icon;
- return fg;
-}
+ case GLFW_KEY_B:
+ Scale_Bars->on = !Scale_Bars->on;
+ break;
-global_function
-struct file
-FILE_DEF(enum file_types type, const char *suffix, enum file_groups group)
-{
- struct file fd;
- fd.type = type;
- fd.suffix = suffix;
- fd.group = group;
- return fd;
-}
+ case GLFW_KEY_C:
+ if (Select_Sort_Area_Mode && auto_curation_state.get_selected_fragments_num(Map_State, Number_of_Pixels_1D) > 0) // local area break
+ {
+ auto_cut_state = 1;
+ }
+ else // open "coverage" extension
+ {
+ if (!Extensions.head) break;
+ TraverseLinkedList(Extensions.head, extension_node)
+ {
+ switch (node->type)
+ {
+ case extension_graph:
+ {
-global_function
-struct nk_image*
-MediaIconForFile(struct media *media, const char *file)
-{
- u32 i = 0;
- const char *s = file;
- char suffix[16];
- u32 found = 0;
- memset(suffix, 0, sizeof(suffix));
+ graph *gph = (graph *)node->extension;
+ if (strcmp((char *)gph->name, "coverage") == 0)
+ {
+ gph->on = !gph->on;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ break;
- /* extract suffix .xxx from file */
- while (*s++ != '\0')
- {
- if (found && i < (sizeof(suffix)-1))
- suffix[i++] = *s;
+ case GLFW_KEY_D:
+ if (Scaff_Edit_Mode && (mods & GLFW_MOD_SHIFT))
+ {
+ ForLoop(Contigs->numberOfContigs) (Contigs->contigs_arr + index)->scaffId = 0;
+ UpdateScaffolds();
+ }
+ else if (MetaData_Edit_Mode && (mods & GLFW_MOD_SHIFT)) memset(Map_State->metaDataFlags, 0, Number_of_Pixels_1D * sizeof(u64));
+ else keyPressed = 0;
+ break;
- if (*s == '.')
- {
- if (found)
- {
- found = 0;
- break;
- }
- found = 1;
- }
- }
+ case GLFW_KEY_E:
+ keyPressed = ToggleEditMode(window);
+ break;
- /* check for all file definition of all groups for fitting suffix*/
- for ( i = 0;
- i < FILE_MAX && found;
- ++i)
- {
- struct file *d = &media->files[i];
- {
- const char *f = d->suffix;
- s = suffix;
- while (f && *f && *s && *s == *f)
- {
- s++; f++;
- }
+ case GLFW_KEY_F:
+ keyPressed = ToggleSelectSortAreaMode(window);
+ break;
- /* found correct file definition so */
- if (f && *s == '\0' && *f == '\0')
- return media->group[d->group].icon;
- }
- }
- return &media->icons.default_file;
-}
+ case GLFW_KEY_G:
+ if (!Extensions.head) break;
+ TraverseLinkedList(Extensions.head, extension_node)
+ {
+ switch (node->type)
+ {
+ case extension_graph:
+ {
-global_function
-void
-MediaInit(struct media *media)
-{
- /* file groups */
- struct icons *icons = &media->icons;
- media->group[FILE_GROUP_DEFAULT] = FILE_GROUP(FILE_GROUP_DEFAULT,"default",&icons->default_file);
- media->group[FILE_GROUP_PRETEXT] = FILE_GROUP(FILE_GROUP_PRETEXT, "pretext", &icons->img_file);
+ graph *gph = (graph *)node->extension;
+ if (strcmp((char *)gph->name, "gap") == 0)
+ {
+ gph->on = !gph->on;
+ break;
+ }
+ }
+ }
+ }
+ break;
- /* files */
- media->files[FILE_DEFAULT] = FILE_DEF(FILE_DEFAULT, NULL, FILE_GROUP_DEFAULT);
- media->files[FILE_PRETEXT] = FILE_DEF(FILE_PRETEXT, "pretext", FILE_GROUP_PRETEXT);
- media->files[FILE_PSTM] = FILE_DEF(FILE_PSTM, "pstm", FILE_GROUP_PRETEXT);
-}
+ case GLFW_KEY_H:
+ if (Select_Sort_Area_Mode)
+ {
+ auto_curation_state.hap_cluster_flag = !auto_curation_state.hap_cluster_flag;
+ }
+ else keyPressed = 0;
+ break;
-global_function
-void
-FileBrowserReloadDirectoryContent(struct file_browser *browser, const char *path)
-{
- strncpy(browser->directory, path, MAX_PATH_LEN);
- DirFreeList(browser->files, browser->file_count);
- DirFreeList(browser->directories, browser->dir_count);
- browser->files = DirList(path, 0, &browser->file_count);
- browser->directories = DirList(path, 1, &browser->dir_count);
-}
+ case GLFW_KEY_I:
+ Contig_Ids->on = !Contig_Ids->on;
+ break;
+
+ case GLFW_KEY_J:
+ JumpToDiagonal(window);
+ break;
+
+ case GLFW_KEY_K:
+ jump_back_pos_before_jump(window);
+ break;
+
+ case GLFW_KEY_L:
+ if (Waypoint_Edit_Mode)
+ {
+ Long_Waypoints_Mode = (Long_Waypoints_Mode +1) % 3;
+ }
+ else
+ {
+ Grid->on = !Grid->on;
+ }
+ break;
+
+ case GLFW_KEY_M:
+ keyPressed = ToggleMetaDataMode(window);
+ break;
+
+ case GLFW_KEY_N:
+ Contig_Name_Labels->on = !Contig_Name_Labels->on;
+ break;
+
+ case GLFW_KEY_O:
+ if (Select_Sort_Area_Mode)
+ auto_curation_state.auto_cut_with_extension = !auto_curation_state.auto_cut_with_extension;
+ else keyPressed = 0;
+ break;
+
+ case GLFW_KEY_P:
+ break;
+
+ case GLFW_KEY_Q:
+ if (Edit_Mode || Select_Sort_Area_Mode)
+ {
+ UndoMapEdit();
+ }
+ else
+ {
+ keyPressed = 0;
+ }
+ break;
-global_function
-void
-FileBrowserInit(struct file_browser *browser, struct media *media)
-{
- memset(browser, 0, sizeof(*browser));
- browser->media = media;
- {
- /* load files and sub-directory list */
- const char *home = getenv("HOME");
-#ifdef _WIN32
- if (!home) home = getenv("USERPROFILE");
-#else
- if (!home) home = getpwuid(getuid())->pw_dir;
-#endif
- {
- size_t l;
- strncpy(browser->home, home, MAX_PATH_LEN);
- l = strlen(browser->home);
-#ifdef _WIN32
- char *sep = (char *)"\\";
-#else
- char *sep = (char *)"/";
-#endif
- strcpy(browser->home + l, sep);
- strcpy(browser->directory, browser->home);
- }
-
- browser->files = DirList(browser->directory, 0, &browser->file_count);
- browser->directories = DirList(browser->directory, 1, &browser->dir_count);
- }
-}
+ case GLFW_KEY_R:
+ if (mods == GLFW_MOD_CONTROL)
+ {
+ Loading = 1;
+ }
+ else if (Extension_Mode && Extensions.head)
+ {
+ TraverseLinkedList(Extensions.head, extension_node)
+ {
+ switch (node->type)
+ {
+ case extension_graph:
+ {
+ graph *gph = (graph *)node->extension;
+ if (strcmp((char *)gph->name, "repeat_density") == 0)
+ {
+ gph->on = !gph->on;
+ break;
+ }
+ }
+ }
+ }
+ break;
+ }
+ else
+ {
+ keyPressed = 0;
+ }
+ break;
-global_variable
-char
-Save_State_Name_Buffer[1024] = {0};
+ case GLFW_KEY_S:
+ if (Edit_Mode)
+ {
+ Edit_Pixels.snap = !Edit_Pixels.snap;
+ }
+ else if (mods & GLFW_MOD_SHIFT)
+ {
+ Scaffs_Always_Visible = Scaffs_Always_Visible ? 0 : 1;
+ }
+ else if (Select_Sort_Area_Mode)
+ {
+ auto_curation_state.clear(); // clear the selected area
+ }
+ else
+ {
+ keyPressed = ToggleScaffMode(window);
+ }
+ break;
-global_variable
-char
-AGP_Name_Buffer[1024] = {0};
+ case GLFW_KEY_T:
+ if (Extension_Mode && Extensions.head)
+ {
+ TraverseLinkedList(Extensions.head, extension_node)
+ {
+ switch (node->type)
+ {
+ case extension_graph:
+ {
-global_function
-void
-SetSaveStateNameBuffer(char *name)
-{
- u32 ptr = 0;
- while (*name)
- {
- AGP_Name_Buffer[ptr] = *name;
- Save_State_Name_Buffer[ptr++] = *name++;
- }
-
- u32 ptr1 = ptr;
- name = (char *)".savestate_1";
- while (*name) Save_State_Name_Buffer[ptr++] = *name++;
- Save_State_Name_Buffer[ptr] = 0;
+ graph *gph = (graph *)node->extension;
+ if (strcmp((char *)gph->name, "telomere") == 0)
+ {
+ gph->on = !gph->on;
+ break;
+ }
+ }
+ }
+ }
+ break;
+ }
+ else
+ {
+ ToggleToolTip(window);
+ }
+ break;
- ptr = ptr1;
- name = (char *)".agp_1";
- while (*name) AGP_Name_Buffer[ptr++] = *name++;
- AGP_Name_Buffer[ptr] = 0;
-}
+ case GLFW_KEY_U:
+ UI_On = !UI_On;
+ ++NK_Device->lastContextMemory[0];
+ Mouse_Move.x = Mouse_Move.y = -1;
+ break;
-global_function
-u08
-FileBrowserRun(const char *name, struct file_browser *browser, struct nk_context *ctx, u32 show, u08 save = 0)
-{
-#ifndef _WIN32
- char pathSep = '/';
-#else
- char pathSep = '\\';
-#endif
-
- struct nk_window *window = nk_window_find(ctx, name);
- u32 doesExist = window != 0;
+ case GLFW_KEY_V:
+ break;
- if (!show && !doesExist)
- {
- return(0);
- }
+ case GLFW_KEY_W:
+ if (Edit_Mode || Select_Sort_Area_Mode)
+ {
+ RedoMapEdit();
+ }
+ else
+ {
+ keyPressed = ToggleWaypointMode(window);
+ }
+ break;
- if (show && doesExist && (window->flags & NK_WINDOW_HIDDEN))
- {
- window->flags &= ~(nk_flags)NK_WINDOW_HIDDEN;
- FileBrowserReloadDirectoryContent(browser, browser->directory);
- }
+ case GLFW_KEY_X:
+ keyPressed = ToggleExtensionMode(window);
+ break;
- u08 ret = 0;
- struct media *media = browser->media;
- struct nk_rect total_space;
+ case GLFW_KEY_Y:
+ break;
- if (nk_begin(ctx, name, nk_rect(Screen_Scale.x * 50, Screen_Scale.y * 50, Screen_Scale.x * 800, Screen_Scale.y * 700),
- NK_WINDOW_BORDER|NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_MOVABLE|NK_WINDOW_TITLE|NK_WINDOW_CLOSABLE))
- {
- static f32 ratio[] = {0.25f, NK_UNDEFINED};
- f32 spacing_x = ctx->style.window.spacing.x;
- nk_style_set_font(ctx, &NK_Font_Browser->handle);
+ case GLFW_KEY_Z:
+ if (Select_Sort_Area_Mode)
+ {
+ auto_cut_state = 2; // restore the cutted frags within the selected area
+ }
+ break;
- /* output path directory selector in the menubar */
- ctx->style.window.spacing.x = 0;
- nk_menubar_begin(ctx);
- {
- char *d = browser->directory;
- char *begin = d + 1;
- nk_layout_row_dynamic(ctx, Screen_Scale.y * 25.0f, 6);
- while (*d++)
- {
- if (*d == pathSep)
- {
- *d = '\0';
- if (nk_button_label(ctx, begin))
+ case GLFW_KEY_SPACE:
+ if (Edit_Mode && !Edit_Pixels.editing && action == GLFW_PRESS)
+ {
+ Edit_Pixels.selecting = 1;
+ Edit_Pixels.selectPixels = Edit_Pixels.pixels;
+ f64 x, y;
+ glfwGetCursorPos(window, &x, &y);
+ MouseMove(window, x, y);
+ }
+ else if (Edit_Mode && !Edit_Pixels.editing && action == GLFW_RELEASE)
+ {
+ Edit_Pixels.editing = 1;
+ Edit_Pixels.selecting = 0;
+ f64 x, y;
+ glfwGetCursorPos(window, &x, &y);
+ MouseMove(window, x, y);
+ }
+ else if (Edit_Mode && Edit_Pixels.editing && action == GLFW_PRESS)
+ {
+ InvertMap(Edit_Pixels.pixels.x, Edit_Pixels.pixels.y);
+ Global_Edit_Invert_Flag = !Global_Edit_Invert_Flag;
+ }
+ else if (Waypoint_Edit_Mode && Selected_Waypoint && action == GLFW_PRESS)
+ {
+ f64 x, y;
+ glfwGetCursorPos(window, &x, &y);
+ RemoveWayPoint(Selected_Waypoint);
+ MouseMove(window, x, y);
+ }
+ else if (Scaff_Edit_Mode && (action == GLFW_PRESS || action == GLFW_RELEASE))
+ {
+ f64 x, y;
+ glfwGetCursorPos(window, &x, &y);
+ Scaff_Painting_Flag = action == GLFW_PRESS ? 2 : 0;
+ MouseMove(window, x, y);
+ if (action == GLFW_RELEASE) UpdateScaffolds();
+ }
+ else if (MetaData_Edit_Mode && (action == GLFW_PRESS || action == GLFW_RELEASE))
+ {
+ f64 x, y;
+ glfwGetCursorPos(window, &x, &y);
+ MetaData_Edit_State = action == GLFW_PRESS ? 2 : 0;
+ MouseMove(window, x, y);
+ }
+ else if (Select_Sort_Area_Mode && action == GLFW_PRESS)
+ {
+ u32 selected_frag_num = auto_curation_state.get_selected_fragments_num(Map_State, Number_of_Pixels_1D);
+ if (selected_frag_num >= 2)
+ {
+ auto_sort_state = 1;
+ }
+ }
+ else
+ {
+ keyPressed = 0;
+ }
+ break;
+
+ case GLFW_KEY_LEFT_SHIFT:
+ if (Scaff_Edit_Mode)
{
- *d++ = pathSep; *d = '\0';
- FileBrowserReloadDirectoryContent(browser, browser->directory);
- break;
+ if (action != GLFW_RELEASE) Scaff_FF_Flag |= 2;
+ else Scaff_FF_Flag &= ~2;
}
- *d = pathSep;
- begin = d + 1;
- }
- }
- }
- nk_menubar_end(ctx);
- ctx->style.window.spacing.x = spacing_x;
-
- /* window layout */
- f32 endSpace = save ? 100.0f : 0; // Resolved: end space is clipped as the space is not enough
- total_space = nk_window_get_content_region(ctx);
- nk_layout_row(ctx, NK_DYNAMIC, total_space.h - endSpace, 2, ratio);
- nk_group_begin(ctx, "Special", NK_WINDOW_NO_SCROLLBAR);
- {
- struct nk_image home = media->icons.home;
- struct nk_image computer = media->icons.computer;
-
- nk_layout_row_dynamic(ctx, Screen_Scale.y * 40.0f, 1);
- if (nk_button_image_label(ctx, home, "home", NK_TEXT_CENTERED))
- FileBrowserReloadDirectoryContent(browser, browser->home);
- if (nk_button_image_label(ctx,computer,"computer",NK_TEXT_CENTERED))
-#ifndef _WIN32
- FileBrowserReloadDirectoryContent(browser, "/");
-#else
- FileBrowserReloadDirectoryContent(browser, "C:\\");
-#endif
- nk_group_end(ctx);
- }
-
- /* output directory content window */
- nk_group_begin(ctx, "Content", 0);
- {
- s32 index = -1;
- size_t i = 0, j = 0;//, k = 0;
- size_t rows = 0, cols = 0;
- size_t count = browser->dir_count + browser->file_count;
- f32 iconRatio[] = {0.05f, NK_UNDEFINED};
+ else if (Edit_Mode) Edit_Pixels.scaffSelecting = action != GLFW_RELEASE;
+ else if (Select_Sort_Area_Mode && action == GLFW_PRESS) // num_cluster descrease
+ {
+ auto_curation_state.num_clusters = auto_curation_state.num_clusters >= 2 ? auto_curation_state.num_clusters - 1 : 1;
+ }
+ else keyPressed = 0;
+ break;
- cols = 1;
- rows = count / cols;
- for ( i = 0;
- i <= rows;
- i += 1)
- {
- {
- size_t n = j + cols;
- nk_layout_row(ctx, NK_DYNAMIC, Screen_Scale.y * 25.0f, 2, iconRatio);
- for ( ;
- j < count && j < n;
- ++j)
+ case GLFW_KEY_LEFT:
+ if (MetaData_Edit_Mode)
{
- /* draw one row of icons */
- if (j < browser->dir_count)
- {
- /* draw and execute directory buttons */
- if (nk_button_image(ctx,media->icons.directory))
- index = (s32)j;
- nk_label(ctx, browser->directories[j], NK_TEXT_LEFT);
- }
- else
+ u32 nextActive = MetaData_Active_Tag;
+ ForLoop(ArrayCount(Meta_Data->tags))
{
- /* draw and execute files buttons */
- struct nk_image *icon;
- size_t fileIndex = ((size_t)j - browser->dir_count);
- icon = MediaIconForFile(media,browser->files[fileIndex]);
- if (nk_button_image(ctx, *icon))
+ if (--nextActive > (ArrayCount(Meta_Data->tags) - 1)) nextActive = ArrayCount(Meta_Data->tags) - 1;
+ if (strlen((const char *)Meta_Data->tags[nextActive]))
{
- if (save)
- {
- strncpy(save == 2 ? AGP_Name_Buffer : Save_State_Name_Buffer, browser->files[fileIndex], sizeof(save == 2 ? AGP_Name_Buffer : Save_State_Name_Buffer));
- }
- else
- {
- strncpy(browser->file, browser->directory, MAX_PATH_LEN);
- n = strlen(browser->file);
- strncpy(browser->file + n, browser->files[fileIndex], MAX_PATH_LEN - n);
- ret = 1;
- }
+ MetaData_Active_Tag = nextActive;
+ break;
}
- nk_label(ctx,browser->files[fileIndex],NK_TEXT_LEFT);
}
- }
- }
- }
-
- if (index != -1)
- {
- size_t n = strlen(browser->directory);
- strncpy(browser->directory + n, browser->directories[index], MAX_PATH_LEN - n);
- n = strlen(browser->directory);
- if (n < MAX_PATH_LEN - 1)
- {
- browser->directory[n] = pathSep;
- browser->directory[n+1] = '\0';
- }
- FileBrowserReloadDirectoryContent(browser, browser->directory);
- }
-
- nk_group_end(ctx);
- }
-
- if (save)
- {
- Deferred_Close_UI = 0;
-
- nk_layout_row(ctx, NK_DYNAMIC, endSpace - 5.0f, 1, ratio + 1);
- nk_group_begin(ctx, "File", NK_WINDOW_NO_SCROLLBAR);
- {
- f32 fileRatio[] = {0.8f, 0.1f, NK_UNDEFINED};
- f32 fileRatio2[] = {0.45f, 0.1f, 0.18f, 0.17f, NK_UNDEFINED};
- nk_layout_row(ctx, NK_DYNAMIC, Screen_Scale.y * 35.0f, save == 2 ? 5 : 3, save == 2 ? fileRatio2 : fileRatio);
-
- u08 saveViaEnter = (nk_edit_string_zero_terminated(ctx, NK_EDIT_FIELD | NK_EDIT_SIG_ENTER, save == 2 ? AGP_Name_Buffer : Save_State_Name_Buffer, sizeof(save == 2 ? AGP_Name_Buffer : Save_State_Name_Buffer), 0) & NK_EDIT_COMMITED) ? 1 : 0;
-
- static u08 overwrite = 0;
- overwrite = (u08)nk_check_label(ctx, "Override", overwrite);
-
- static u08 singletons = 0;
- if (save == 2) singletons = (u08)nk_check_label(ctx, "Format Singletons", singletons);
- static u08 preserveOrder = 0;
- if (save == 2) preserveOrder = (u08)nk_check_label(ctx, "Preserve Order", preserveOrder);
-
- if (nk_button_label(ctx, "Save") || saveViaEnter)
- {
- strncpy(browser->file, browser->directory, MAX_PATH_LEN);
- size_t n = strlen(browser->file);
- strncpy(browser->file + n, save == 2 ? AGP_Name_Buffer : Save_State_Name_Buffer, MAX_PATH_LEN - n);
- ret = 1 | (overwrite ? 2 : 0) | (singletons ? 4 : 0) | (preserveOrder ? 8 : 0);
- }
-
- nk_group_end(ctx);
- }
- }
-
- nk_style_set_font(ctx, &NK_Font->handle);
- }
- nk_end(ctx);
-
- return(ret);
-}
-
-global_function
-void
-MetaTagsEditorRun(struct nk_context *ctx, u08 show)
-{
- const char *name = "Meta Data Tag Editor";
- struct nk_window *window = nk_window_find(ctx, name);
-
- u08 doesExist = window != 0;
- if (!show && !doesExist) return;
- if (show && doesExist && (window->flags & NK_WINDOW_HIDDEN)) window->flags &= ~(nk_flags)NK_WINDOW_HIDDEN;
-
- if (nk_begin(ctx, name, nk_rect(Screen_Scale.x * 50, Screen_Scale.y * 50, Screen_Scale.x * 800, Screen_Scale.y * 600),
- NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE|NK_WINDOW_NO_SCROLLBAR))
- {
- Deferred_Close_UI = 0;
- struct nk_rect total_space = nk_window_get_content_region(ctx);
- f32 ratio[] = {0.05f, NK_UNDEFINED};
- nk_layout_row(ctx, NK_DYNAMIC, total_space.h, 1, ratio + 1);
+ }
+ else if (Select_Sort_Area_Mode)
+ {
+ auto_curation_state.change_sort_mode(-1);
+ }
+ else AdjustColorMap(-1);
+ break;
- nk_group_begin(ctx, "Content", 0);
- {
- nk_layout_row(ctx, NK_DYNAMIC, Screen_Scale.y * 35.0f, 2, ratio);
+ case GLFW_KEY_RIGHT_SHIFT: // num_cluster increase
+ if (Select_Sort_Area_Mode)
+ {
+ auto_curation_state.num_clusters = my_Min(auto_curation_state.num_clusters + 1, 200) ;
+ }
+ else keyPressed = 0;
+ break;
- ForLoop(ArrayCount(Meta_Data->tags))
- {
- char buff[4];
- stbsp_snprintf(buff, sizeof(buff), "%u:", index + 1);
- nk_label(ctx, buff, NK_TEXT_LEFT);
- if (nk_edit_string_zero_terminated(ctx, NK_EDIT_FIELD, (char *)Meta_Data->tags[index], sizeof(Meta_Data->tags[index]), 0) & NK_EDIT_ACTIVE)
- {
- if (!strlen((const char *)Meta_Data->tags[index]))
+ case GLFW_KEY_RIGHT:
+ if (MetaData_Edit_Mode)
{
- ForLoop2(Number_of_Pixels_1D) Map_State->metaDataFlags[index2] &= ~(1 << index);
- u32 nextActive = index;
- ForLoop2((ArrayCount(Meta_Data->tags) - 1))
+ u32 nextActive = MetaData_Active_Tag;
+ ForLoop(ArrayCount(Meta_Data->tags))
{
if (++nextActive == ArrayCount(Meta_Data->tags)) nextActive = 0;
if (strlen((const char *)Meta_Data->tags[nextActive]))
@@ -8505,112 +8941,107 @@ MetaTagsEditorRun(struct nk_context *ctx, u08 show)
}
}
}
- else if (!strlen((const char *)Meta_Data->tags[MetaData_Active_Tag])) MetaData_Active_Tag = index;
- }
- }
-
- nk_group_end(ctx);
- }
- }
- nk_end(ctx);
-}
-
-global_function
-void
-AboutWindowRun(struct nk_context *ctx, u32 show)
-{
- struct nk_window *window = nk_window_find(ctx, "About");
- u32 doesExist = window != 0;
-
- if (!show && !doesExist)
- {
- return;
- }
-
- if (show && doesExist && (window->flags & NK_WINDOW_HIDDEN))
- {
- window->flags &= ~(nk_flags)NK_WINDOW_HIDDEN;
- }
-
- enum windowMode {showAcknowledgements, showLicence, showThirdParty};
-
- static windowMode mode = showAcknowledgements;
-
- if (nk_begin_titled(ctx, "About", PretextView_Version, nk_rect(Screen_Scale.x * 50, Screen_Scale.y * 50, Screen_Scale.x * 870, Screen_Scale.y * 610),
- NK_WINDOW_BORDER|NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_MOVABLE|NK_WINDOW_TITLE|NK_WINDOW_CLOSABLE))
- {
- nk_menubar_begin(ctx);
- {
- nk_layout_row_dynamic(ctx, Screen_Scale.y * 35.0f, 3);
- if (nk_button_label(ctx, "Acknowledgements"))
- {
- mode = showAcknowledgements;
- }
- if (nk_button_label(ctx, "Licence"))
- {
- mode = showLicence;
- }
- if (nk_button_label(ctx, "Third Party Software"))
- {
- mode = showThirdParty;
- }
- }
- nk_menubar_end(ctx);
-
- struct nk_rect total_space = nk_window_get_content_region(ctx);
- f32 one = NK_UNDEFINED;
- nk_layout_row(ctx, NK_DYNAMIC, total_space.h, 1, &one);
-
- nk_group_begin(ctx, "About_Content", 0);
- {
- if (mode == showThirdParty)
- {
- u08 text[] = R"text(PretextView was made possible thanks to the following third party libraries and
-resources, click each entry to view its licence.)text";
-
- nk_layout_row_static(ctx, Screen_Scale.y * 60, (s32)(Screen_Scale.x * 820), 1);
- s32 len = sizeof(text);
- nk_edit_string(ctx, NK_EDIT_READ_ONLY | NK_EDIT_NO_CURSOR | NK_EDIT_SELECTABLE | NK_EDIT_MULTILINE, (char *)text, &len, len, 0);
-
- ForLoop(Number_of_ThirdParties)
- {
- u32 nameIndex = 2 * index;
- u32 licenceIndex = nameIndex + 1;
- s32 *sizes = ThirdParty_Licence_Sizes[index];
+ else if (Select_Sort_Area_Mode)
+ {
+ auto_curation_state.change_sort_mode(1);
+ }
+ else AdjustColorMap(1);
+ break;
- if (nk_tree_push_id(NK_Context, NK_TREE_TAB, (const char *)ThirdParty[nameIndex], NK_MINIMIZED, (s32)index))
+ case GLFW_KEY_UP:
+ if (Select_Sort_Area_Mode)
{
- nk_layout_row_static(ctx, Screen_Scale.y * (f32)sizes[0], (s32)(Screen_Scale.x * (f32)sizes[1]), 1);
- len = (s32)StringLength(ThirdParty[licenceIndex]);
- nk_edit_string(ctx, NK_EDIT_READ_ONLY | NK_EDIT_NO_CURSOR | NK_EDIT_SELECTABLE | NK_EDIT_MULTILINE, (char *)ThirdParty[licenceIndex], &len, len, 0);
- nk_tree_pop(NK_Context);
+ auto_curation_state.adjust_cut_threshold(1);
}
- }
- }
- else if (mode == showAcknowledgements)
- {
- nk_layout_row_static(ctx, Screen_Scale.y * 500, (s32)(Screen_Scale.x * 820), 1);
- s32 len = sizeof(Acknowledgements);
- nk_edit_string(ctx, NK_EDIT_READ_ONLY | NK_EDIT_NO_CURSOR | NK_EDIT_SELECTABLE | NK_EDIT_MULTILINE, (char *)Acknowledgements, &len, len, 0);
+ else NextColorMap(1);
+ break;
+
+ case GLFW_KEY_DOWN:
+ if (Select_Sort_Area_Mode)
+ {
+ auto_curation_state.adjust_cut_threshold(-1);
+ }
+ else
+ NextColorMap(-1);
+ break;
+#ifdef Internal
+ case GLFW_KEY_ESCAPE:
+ if (!mods)
+ {
+ glfwSetWindowShouldClose(window, GLFW_TRUE);
+ }
+ break;
+#endif
+ case GLFW_KEY_ENTER:
+ if (mods == GLFW_MOD_ALT)
+ {
+ if (glfwGetWindowMonitor(window))
+ {
+ glfwSetWindowMonitor(window, NULL,
+ Windowed_Xpos, Windowed_Ypos,
+ Windowed_Width, Windowed_Height, 0);
+ }
+ else
+ {
+ GLFWmonitor* monitor = glfwGetPrimaryMonitor();
+ if (monitor)
+ {
+ const GLFWvidmode* mode = glfwGetVideoMode(monitor);
+ glfwGetWindowPos(window, &Windowed_Xpos, &Windowed_Ypos);
+ glfwGetWindowSize(window, &Windowed_Width, &Windowed_Height);
+ glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
+ }
+ }
+ }
+ else
+ {
+ keyPressed = 0;
+ }
+ break;
+
+ case GLFW_KEY_EQUAL:
+ if (mods == GLFW_MOD_CONTROL && action == GLFW_PRESS){
+ text_box_size.increase_size();
+ Redisplay = 1;
+ }
+ else keyPressed = 0;
+ break;
+ case GLFW_KEY_MINUS:
+ if (mods == GLFW_MOD_CONTROL && action == GLFW_PRESS){
+ text_box_size.decrease_size();
+ Redisplay = 1;
+ }
+ else keyPressed = 0;
+ break;
+ case GLFW_KEY_0:
+ if (mods == GLFW_MOD_CONTROL && action == GLFW_PRESS){
+ text_box_size.defult_size();
+ Redisplay = 1;
+ }
+ else keyPressed = 0;
+ break;
+
+ default:
+ keyPressed = 0;
}
- else
+
+ if (keyPressed)
{
- nk_layout_row_static(ctx, Screen_Scale.y * 500, (s32)(Screen_Scale.x * 820), 1);
- s32 len = sizeof(Licence);
- nk_edit_string(ctx, NK_EDIT_READ_ONLY | NK_EDIT_NO_CURSOR | NK_EDIT_SELECTABLE | NK_EDIT_MULTILINE, (char *)Licence, &len, len, 0);
+ Redisplay = 1;
}
-
- nk_group_end(ctx);
}
}
-
- nk_end(ctx);
}
+global_function
+void
+ErrorCallback(s32 error, const char *desc)
+{
+ (void)error;
+ fprintf(stderr, "Error: %s\n", desc);
+}
-global_function void
-UserSaveState(const char *, u08, char *);
global_function
void
@@ -10054,6 +10485,98 @@ LoadState(u64 headerHash, char *path)
return(0);
}
+/*
+ load the .agp file to restore the curated state
+ NOTE: please make sure to clear the cache before loading the agp file.
+ which means after clearing the cache, all edits will be lost. if you want
+ to keep the edits, please try to change the file name and reopen that. as
+ the cache is automatically named as the hash of the file name.
+*/
+void Load_AGP(const std::string& agp_path)
+{
+ fmt::print("Load AGP file: {}\n", agp_path);
+ try
+ {
+ AssemblyAGP assembly_agp(agp_path, Original_Contigs, Number_of_Original_Contigs, Meta_Data);
+ fmt::println("{}", assembly_agp.__str__());
+
+ // do curations to achieve the map_state
+ // 1. split the original contigs according to the curation agp
+ std::vector> split_points_frags(Number_of_Original_Contigs);
+ for (int i = 0; i < assembly_agp.frags.size(); i++)
+ {
+ auto& frag = assembly_agp.frags[i];
+ if (frag.start > 1) // skip the start bp of one contig
+ split_points_frags[frag.orig_contig_id].insert(frag.start);
+ }
+ // merge the split points
+ int ptr_bp = 0;
+ std::vector merged_split_points;
+ std::string contig_name_tmp;
+ for (int i = 0; i < Number_of_Original_Contigs; i ++ )
+ {
+ for (auto it = split_points_frags[i].begin(); it != split_points_frags[i].end(); ++it)
+ merged_split_points.push_back((int)((double)(*it + ptr_bp) / assembly_agp.bp_per_pixel));
+ contig_name_tmp = std::string((char*)Original_Contigs[i].name);
+ if (assembly_agp.original_contigs.find(contig_name_tmp) != assembly_agp.original_contigs.end())
+ ptr_bp += assembly_agp.original_contigs[contig_name_tmp].len;
+ else
+ fmt::print("[Load AGP::error]: Original_Contig name ({}) not found in the assembly_agp.original_contigs.\n", contig_name_tmp);
+ }
+ // cut the at the split points
+ cut_frags( merged_split_points, false, false);
+ // check if the number of contigs between contigs_agp and contigs are the same
+ // after cutting, this should be the same
+ if (Contigs->numberOfContigs != assembly_agp.frags.size())
+ {
+ fmt::print("[Load AGP::error]: The number of contigs between contigs_agp and contigs are not the same.\n");
+ throw std::runtime_error(fmt::format("[Load AGP::error]: The number of contigs between Contigs({}) and contigs_agp({}) are not the same.\n", Contigs->numberOfContigs, assembly_agp.frags.size()));
+ }
+
+ // vector to save frag's local order within orignal contig
+ std::vector global_frag_start_Contigs(Number_of_Original_Contigs, 0);
+ for (int i = 1; i < Number_of_Original_Contigs; i++)
+ global_frag_start_Contigs[i] = global_frag_start_Contigs[i-1] + Original_Contigs[i-1].nContigs;
+
+ // 2. reorder them
+ // call the auto_curation func to reorder the contigs globally
+ std::vector contigs_order_agp(assembly_agp.frags.size()); // restore the order in agp
+ for (int i = 0; i < assembly_agp.frags.size(); i++)
+ {
+ auto& frag = assembly_agp.frags[i];
+ contigs_order_agp[i] = ( global_frag_start_Contigs[frag.orig_contig_id] + frag.local_index + 1 ) * (frag.is_reverse?-1:1);
+ }
+ FragsOrder frags_order_agp(contigs_order_agp);
+ // curation globally
+ AutoCurationFromFragsOrder( &frags_order_agp, Contigs, Map_State, nullptr );
+
+ // add scaff id to restore the painted scaffID and meta tags
+ int pix_ptr = 0, contig_start_pix_ptr = 0;
+ for (int i =0 ; i < Contigs->numberOfContigs;i++)
+ {
+ auto& frag = assembly_agp.frags[i];
+ while (pix_ptr < Number_of_Pixels_1D && pix_ptr < contig_start_pix_ptr + Contigs->contigs_arr[i].length)
+ {
+ Map_State->scaffIds[pix_ptr] = frag.is_painted? frag.scaff_id + 1 : 0; // scaff_id
+ Map_State->metaDataFlags[pix_ptr++] = frag.meta_data_flag ; // meta data flag
+ }
+ contig_start_pix_ptr += Contigs->contigs_arr[i].length;
+ }
+ UpdateContigsFromMapState();
+ }
+ catch (const std::exception& e)
+ {
+ fmt::print("Exception: {}\n", e.what());
+ fmt::print("[Load AGP]: Failed.\n");
+ return;
+ }
+
+
+
+
+ return ;
+}
+
// restore the state before curation
global_function
@@ -10381,8 +10904,9 @@ default_user_profile_settings()
}
+
global_function void
-UserSaveState(const char *headerHash = "userprofile", u08 overwrite = 1, char *path = 0)
+UserSaveState(const char *headerHash, u08 overwrite , char *path)
{
if (!UserSaveState_Path)
@@ -10489,11 +11013,28 @@ UserSaveState(const char *headerHash = "userprofile", u08 overwrite = 1, char *p
fwrite(&invert_mouse_tmp, sizeof(bool), 1, file);
}
- // END of SAVE user profile settings
+ // finished (shaoheng) save default file browser directory
+ const char* placeholder = "fdpc"; // placeholder for File Directory Path Cache
+ for (int i = 0; i < 4; i ++ ) fwrite(&placeholder[i], sizeof(char), 1, file);
+ for (const file_browser& browser_tmp : { browser, saveBrowser, loadBrowser, saveAGPBrowser, loadAGPBrowser }) {
+ if (browser_tmp.directory[0]!='\0') {
+ u32 dir_len = strlen(browser_tmp.directory);
+ fwrite(&dir_len, sizeof(dir_len), 1, file);
+ fwrite(browser_tmp.directory, sizeof(char), dir_len, file);
+ }
+ else {
+ u32 dir_len = 0;
+ fwrite(&dir_len, sizeof(dir_len), 1, file);
+ }
+ }
+
+ // END of SAVE user profile settings
fclose(file);
- printf("[UserProfile]: Saved to: %s\n", path);
+ #ifdef DEBUG
+ printf("[UserProfile]: Saved to: %s\n", path);
+ #endif // DEBUG
}
global_function
@@ -10604,35 +11145,58 @@ global_function
// load selected area color
f32 tmp_mask_color[4];
- if (fread(tmp_mask_color, sizeof(tmp_mask_color), 1, file) == 1)
- {
+ if (fread(tmp_mask_color, sizeof(tmp_mask_color), 1, file) == 1) {
auto_curation_state.set_mask_color(tmp_mask_color);
}
- else
- {
+ else {
auto_curation_state.set_mask_color(auto_curation_state.mask_color_default);
+ fmt::println("[UserLoadState::warning]: userProfile loading stops as there is no 1 byte left for tmp_mask_color. The left part will not be restored from the userProfile cache. File: {}, line: {}", __FILE__, __LINE__);
+ return 1;
}
// load grey out flags
int32_t grey_out_flags[64];
- if (fread(grey_out_flags, sizeof(int32_t), 64, file) == 64)
- {
- if (Grey_Out_Settings)
- {
+ if (fread(grey_out_flags, sizeof(int32_t), 64, file) == 64) {
+ if (Grey_Out_Settings) {
memcpy(Grey_Out_Settings->grey_out_flags, grey_out_flags, 64 * sizeof(int32_t));
}
}
+ else {
+ fmt::println("[UserLoadState::warning]: userProfile loading stops as there is no 64 byte left for grey_out_flags. The left part will not be restored from the userProfile cache. File: {}, line: {}", __FILE__, __LINE__);
+ return 1;
+ }
// load user profile settings
bool invert_mouse_tmp;
- if (fread(&invert_mouse_tmp, sizeof(bool), 1, file) == 1)
- {
- if (user_profile_settings_ptr)
- {
- user_profile_settings_ptr->invert_mouse = invert_mouse_tmp;
- }
+ if (fread(&invert_mouse_tmp, sizeof(bool), 1, file) == 1) {
+ if (user_profile_settings_ptr) user_profile_settings_ptr->invert_mouse = invert_mouse_tmp;
+ }
+ else {
+ if (user_profile_settings_ptr) user_profile_settings_ptr->invert_mouse = false;
+ fmt::println("[UserLoadState::warning]: userProfile loading stops as there is no 1 byte left for invertMouse setting. The left part will not be restored from the userProfile cache. File: {}, line: {}", __FILE__, __LINE__);
+ return 1;
}
+ // file directory path cache
+ char lable[4];
+ if (fread(lable, sizeof(char), 4, file) == 4 && strncmp(lable, "fdpc", 4) == 0) {
+ std::vector browsers = { &browser, &saveBrowser, &loadBrowser, &saveAGPBrowser, &loadAGPBrowser };
+ for (file_browser* browser_ptr : browsers) {
+ u32 dir_len;
+ if (fread(&dir_len, sizeof(dir_len), 1, file) == 1 && dir_len > 0) {
+ char *dir = (char *)malloc(dir_len + 1);
+ if (fread(dir, sizeof(char), dir_len, file) == dir_len ) {
+ dir[dir_len] = '\0'; // Null-terminate the string
+ FileBrowserReloadDirectoryContent(browser_ptr, dir);
+ }
+ free(dir);
+ }
+ }
+ }
+ else {
+ fmt::println("[UserLoadState::warning]: userProfile loading stops as the 4 byte left is not \'fdpc\' for the file directory path cache. The left part will not be restored from the userProfile cache. File: {}, line: {}", __FILE__, __LINE__);
+ return 1;
+ }
fclose(file);
@@ -10750,16 +11314,23 @@ GenerateAGP(char *path, u08 overwrite, u08 formatSingletons, u08 preserveOrder)
u32 scaffId_unPainted = 0;
if (preserveOrder) ForLoop(Contigs->numberOfContigs) scaffId_unPainted = my_Max(scaffId_unPainted, (Contigs->contigs_arr + index)->scaffId);
- for ( u08 type = 0;
- type < (preserveOrder ? 1 : 2);
- ++type)
+ for ( u08 type = 0;
+ type < (preserveOrder ? 1 : 2); // two round: 1st round for painted scaffs, 2nd round for unpainted
+ ++type)
{
ForLoop(Contigs->numberOfContigs)
{
contig *cont = Contigs->contigs_arr + index;
- u08 invert = IsContigInverted(index);
+ u08 invert = IsContigInverted( index );
u32 startCoord = cont->startCoord - (invert ? (cont->length - 1) : 0);
-
+
+ /*
+ set invert to 0 if:
+ - formatSingletons is False and
+ - contig is not painted
+ - contig is just 1 pixel long
+ - contig is the first or last contig in the genome
+ */
invert = (!formatSingletons && (!cont->scaffId || (index && (index < (Contigs->numberOfContigs - 1)) && (cont->scaffId != ((cont + 1)->scaffId)) && (cont->scaffId != ((cont - 1)->scaffId))) || (!index && (cont->scaffId != ((cont + 1)->scaffId))) || ((index == (Contigs->numberOfContigs - 1)) && (cont->scaffId != ((cont - 1)->scaffId))))) ? 0 : invert;
u64 contRealStartCoord = (u64)((f64)startCoord / (f64)Number_of_Pixels_1D * (f64)Total_Genome_Length) + 1;
@@ -10768,13 +11339,13 @@ GenerateAGP(char *path, u08 overwrite, u08 formatSingletons, u08 preserveOrder)
char *contName = (char *)((Original_Contigs + cont->get_original_contig_id())->name);
- if (cont->scaffId && !type)
+ if (cont->scaffId && !type) // painted scaff
{
if (cont->scaffId != scaffId)
{
scaffId = cont->scaffId;
scaffCoord_Start = 1;
- scaffPart = 0;
+ scaffPart = 0; // index within the scaffold
}
u64 scaffCoord_End;
@@ -10795,7 +11366,9 @@ GenerateAGP(char *path, u08 overwrite, u08 formatSingletons, u08 preserveOrder)
{
ForLoop2(ArrayCount(Meta_Data->tags))
{
- if (*cont->metaDataFlags & (1 << index2))
+ if (*cont->metaDataFlags & (1ULL << index2) && // NOTE: please make sure the 1ULL, or after index2 >= 32 there will be unexpected behaviour
+ Grey_Out_Settings->paint_tags.count(std::string((char*)Meta_Data->tags[index2])) == 0 // make sure this is not tag used for vertical horizontal or cross painting
+ )
{
stbsp_snprintf(buffer, sizeof(buffer), "\t%s", (char *)Meta_Data->tags[index2]);
fwrite(buffer, 1, strlen(buffer), file);
@@ -10805,7 +11378,7 @@ GenerateAGP(char *path, u08 overwrite, u08 formatSingletons, u08 preserveOrder)
fwrite("\n", 1, 1, file);
scaffCoord_Start = scaffCoord_End + 1;
}
- else if (!cont->scaffId && (preserveOrder || type))
+ else if (!cont->scaffId && (preserveOrder || type)) // unpainted
{
stbsp_snprintf(buffer, sizeof(buffer), "Scaffold_%u\t1\t%" PRIu64 "\t1\tW\t%s\t%" PRIu64 "\t%" PRIu64 "\t%s", (preserveOrder ? ++scaffId_unPainted : ++scaffId), contRealSize, contName, contRealStartCoord, contRealEndCoord, invert ? "-" : "+");
fwrite(buffer, 1, strlen(buffer), file);
@@ -10813,7 +11386,9 @@ GenerateAGP(char *path, u08 overwrite, u08 formatSingletons, u08 preserveOrder)
{
ForLoop2(ArrayCount(Meta_Data->tags))
{
- if (*cont->metaDataFlags & (1 << index2))
+ if (*cont->metaDataFlags & (1ULL << index2) && // NOTE: please make sure the 1ULL, or after index2 >= 32 there will be unexpected behaviour
+ Grey_Out_Settings->paint_tags.count(std::string((char*)Meta_Data->tags[index2])) == 0 // make sure this is not tag used for vertical horizontal or cross painting
+ )
{
stbsp_snprintf(buffer, sizeof(buffer), "\t%s", (char *)Meta_Data->tags[index2]);
fwrite(buffer, 1, strlen(buffer), file);
@@ -10915,7 +11490,16 @@ void SortMapByMetaTags(u64 tagMask)
MainArgs
-{
+{
+
+ Stuck_Problem_Check_Debug
+
+ #ifdef PYTHON_SCOPED_INTERPRETER
+ // START Python interpreter
+ py::scoped_interpreter guard{};
+ kmeans_cluster = new KmeansClusters(); // import the kmeans module
+ #endif // PYTHON_SCOPED_INTERPRETER
+
u32 initWithFile = 0; // initialization with .map file or not
u08 currFile[256]; // save the name of file inputed
u08 *currFileName = 0;
@@ -10927,6 +11511,8 @@ MainArgs
printf("Read from file: %s\n", currFile);
}
+ Stuck_Problem_Check_Debug
+
Mouse_Move.x = -1.0; // intialize the mouse position
Mouse_Move.y = -1.0;
@@ -10942,7 +11528,7 @@ MainArgs
Edit_Pixels.editing = 0;
Edit_Pixels.selecting = 0;
Edit_Pixels.scaffSelecting = 0;
- Edit_Pixels.snap = 0;
+ Edit_Pixels.snap = 1; // change the default to snap mode on
Camera_Position.x = 0.0f; // 0.0f
Camera_Position.y = 0.0f; // 0.0f
@@ -10951,6 +11537,8 @@ MainArgs
CreateMemoryArena(Working_Set, MegaByte(256));
Thread_Pool = ThreadPoolInit(&Working_Set, 3);
+ Stuck_Problem_Check_Debug
+
glfwSetErrorCallback(ErrorCallback);
if (!glfwInit())
{
@@ -10958,6 +11546,8 @@ MainArgs
exit(EXIT_FAILURE);
}
+ Stuck_Problem_Check_Debug
+
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_DOUBLEBUFFER, GLFW_TRUE);
@@ -10974,12 +11564,16 @@ MainArgs
exit(EXIT_FAILURE);
}
+ Stuck_Problem_Check_Debug
+
glfwMakeContextCurrent(window);
NK_Context = PushStruct(Working_Set, nk_context);
glfwSetWindowUserPointer(window, NK_Context);
gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);
glfwSwapInterval(1);
+ Stuck_Problem_Check_Debug
+
glfwSetFramebufferSizeCallback(window, GLFWChangeFrameBufferSize);
glfwSetWindowSizeCallback(window, GLFWChangeWindowSize);
glfwSetCursorPosCallback(window, MouseMove);
@@ -11017,8 +11611,12 @@ MainArgs
GLFWcursor *arrowCursor = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
GLFWcursor *crossCursor = glfwCreateStandardCursor(GLFW_CROSSHAIR_CURSOR);
+ Stuck_Problem_Check_Debug
+
Setup();
+ Stuck_Problem_Check_Debug
+
if (initWithFile)
{
UI_On = LoadFile((const char *)currFile, Loading_Arena, (char **)&currFileName, &headerHash) == ok ? 0 : 1;
@@ -11045,11 +11643,8 @@ MainArgs
// }
// }
- // file browser
- struct file_browser browser;
- struct file_browser saveBrowser;
- struct file_browser loadBrowser;
- struct file_browser saveAGPBrowser;
+ Stuck_Problem_Check_Debug
+
u32 showClearCacheScreen = 0;
@@ -11065,8 +11660,11 @@ MainArgs
FileBrowserInit(&saveBrowser, &media);
FileBrowserInit(&loadBrowser, &media);
FileBrowserInit(&saveAGPBrowser, &media);
+ FileBrowserInit(&loadAGPBrowser, &media);
}
+ Stuck_Problem_Check_Debug
+
{
f64 mousex, mousey;
glfwGetCursorPos(window, &mousex, &mousey);
@@ -11078,9 +11676,8 @@ MainArgs
Redisplay = 1;
- char searchbuf[256] = {0};
- s32 caseSensitive_search_sequences = 0;
-
+ Stuck_Problem_Check_Debug
+
while (!glfwWindowShouldClose(window))
{
if (Redisplay)
@@ -11089,6 +11686,7 @@ MainArgs
glfwSwapBuffers(window);
Redisplay = 0;
if (currFileName) SaveState(headerHash);
+ Stuck_Problem_Check_Debug
}
if (Loading)
@@ -11129,6 +11727,8 @@ MainArgs
GatheringTextInput = 1;
glfwPollEvents();
+ Stuck_Problem_Check_Debug
+
/*nk_input_key(NK_Context, NK_KEY_DEL, glfwGetKey(window, GLFW_KEY_DELETE) == GLFW_PRESS);
nk_input_key(NK_Context, NK_KEY_ENTER, glfwGetKey(window, GLFW_KEY_ENTER) == GLFW_PRESS);
nk_input_key(NK_Context, NK_KEY_TAB, glfwGetKey(window, GLFW_KEY_TAB) == GLFW_PRESS);
@@ -11181,6 +11781,7 @@ MainArgs
s32 showSaveStateScreen = 0;
s32 showLoadStateScreen = 0;
s32 showSaveAGPScreen = 0;
+ s32 showLoadAGPScreen = 0;
s32 showMetaDataTagEditor = 0;
s32 showUserProfileScreen = 0;
static u32 currGroup1 = 0;
@@ -11218,6 +11819,7 @@ MainArgs
showSaveStateScreen = nk_button_label(NK_Context, "Save State");
showLoadStateScreen = nk_button_label(NK_Context, "Load State");
showSaveAGPScreen = nk_button_label(NK_Context, "Generate AGP");
+ showLoadAGPScreen = nk_button_label(NK_Context, "Load AGP");
if (nk_button_label(NK_Context, "Clear Cache")) showClearCacheScreen = 1; // used to clear cache for current opened sample
}
showUserProfileScreen = nk_button_label(NK_Context, "User Profile");
@@ -11275,81 +11877,100 @@ MainArgs
// Pixel Cut
{
bounds = nk_widget_bounds(NK_Context);
- auto_cut_button = nk_button_label(NK_Context, "Pixel Cut");
+ auto_cut_button = nk_button_label(NK_Context, "Pixel Cut") || auto_cut_button ;
- if (auto_cut_button && currFileName)
- {
- auto_cut_state = 1;
- auto_curation_state.clear(); // if click the button, the sort/cut will be applied globally
- }
// window to set the parameters for cut
- if (nk_contextual_begin(NK_Context, 0, nk_vec2(Screen_Scale.x * 480, Screen_Scale.y * 800), bounds))
+ if (auto_cut_button)
{
- nk_layout_row_dynamic(NK_Context, Screen_Scale.y * 30.0f, 1);
-
- nk_label(NK_Context, "Cut threshold (default: 0.05)", NK_TEXT_LEFT);
- nk_edit_string_zero_terminated(
- NK_Context,
- NK_EDIT_FIELD,
- (char*)auto_curation_state.auto_cut_threshold_buf,
- sizeof(auto_curation_state.auto_cut_threshold_buf),
- nk_filter_float);
-
- nk_label(NK_Context, "Pixel_mean window size (default: 8)", NK_TEXT_LEFT); // 见鬼了,见鬼了,这个地方,如果我使用 "Pixel_mean windows (default: 8)" 点击弹出的窗口外面程序就会卡死,但是使用"Pixel_mean window size (default: 8)" 就不会卡死
- nk_edit_string_zero_terminated(
- NK_Context,
- NK_EDIT_FIELD,
- (char*)auto_curation_state.auto_cut_diag_window_for_pixel_mean_buf,
- sizeof(auto_curation_state.auto_cut_diag_window_for_pixel_mean_buf),
- nk_filter_decimal);
-
- nk_label(NK_Context, "Smallest frag size (default: 8)", NK_TEXT_LEFT);
- nk_edit_string_zero_terminated(
- NK_Context,
- NK_EDIT_FIELD,
- (char*)auto_curation_state.auto_cut_smallest_frag_size_in_pixel_buf,
- sizeof(auto_curation_state.auto_cut_smallest_frag_size_in_pixel_buf),
- nk_filter_decimal);
+ static struct nk_rect popup_rect = nk_rect(Screen_Scale.x * 100, Screen_Scale.y * 100, Screen_Scale.x * 480, Screen_Scale.y * 300);
+ if (nk_popup_begin(NK_Context, NK_POPUP_STATIC, "Pixel Cut Parameters",
+ NK_WINDOW_CLOSABLE|NK_WINDOW_BORDER, popup_rect)) {
+
+ nk_layout_row_dynamic(NK_Context, Screen_Scale.y * 30.0f, 1);
- nk_layout_row_dynamic(NK_Context, Screen_Scale.y * 30.0f, 2);
- if (nk_button_label(NK_Context, "Cancel"))
- {
- printf("[Pixel Cut] Cancel button clicked\n");
- auto_curation_state.set_buf();
- nk_contextual_close(NK_Context);
- }
- if (nk_button_label(NK_Context, "Apply"))
- {
- // Apply changes
- // Convert text to integer and float
- auto_curation_state.update_value_from_buf(); // todo 这里还有问题,因为设置了pixel_mean之后 并没有重新计算 pixel_density...
+ nk_label(NK_Context, "Cut threshold (default: 0.05)", NK_TEXT_LEFT);
+ nk_edit_string_zero_terminated(
+ NK_Context,
+ NK_EDIT_FIELD,
+ (char*)auto_curation_state.auto_cut_threshold_buf,
+ sizeof(auto_curation_state.auto_cut_threshold_buf),
+ nk_filter_float);
- nk_contextual_close(NK_Context);
+ nk_label(NK_Context, "Pixel_mean window size (default: 8)", NK_TEXT_LEFT); // 见鬼了,见鬼了,这个地方,如果我使用 "Pixel_mean windows (default: 8)" 点击弹出的窗口外面程序就会卡死,但是使用"Pixel_mean window size (default: 8)" 就不会卡死
+ nk_edit_string_zero_terminated(
+ NK_Context,
+ NK_EDIT_FIELD,
+ (char*)auto_curation_state.auto_cut_diag_window_for_pixel_mean_buf,
+ sizeof(auto_curation_state.auto_cut_diag_window_for_pixel_mean_buf),
+ nk_filter_decimal);
+
+ nk_label(NK_Context, "Smallest frag size (default: 8)", NK_TEXT_LEFT);
+ nk_edit_string_zero_terminated(
+ NK_Context,
+ NK_EDIT_FIELD,
+ (char*)auto_curation_state.auto_cut_smallest_frag_size_in_pixel_buf,
+ sizeof(auto_curation_state.auto_cut_smallest_frag_size_in_pixel_buf),
+ nk_filter_decimal);
- auto_curation_state.set_buf();
- fmt::print("[Pixel Cut] cut_threshold: {:.3f}\n", auto_curation_state.auto_cut_threshold);
- fmt::print("[Pixel Cut] pixel mean window size: {}\n", auto_curation_state.auto_cut_diag_window_for_pixel_mean);
- fmt::print("[Pixel Cut] smallest_frag_size_in_pixel: {}\n", auto_curation_state.auto_cut_smallest_frag_size_in_pixel);
+ nk_layout_row_dynamic(NK_Context, Screen_Scale.y * 30.0f, 3);
+ if (nk_button_label(NK_Context, "Apply settings"))
+ {
+ // Apply changes
+ // Convert text to integer and float
+ auto_curation_state.update_value_from_buf(); // todo 这里还有问题,因为设置了pixel_mean之后 并没有重新计算 pixel_density...
+ auto_curation_state.set_buf();
+ fmt::print("[Pixel Cut] cut_threshold: {:.3f}\n", auto_curation_state.auto_cut_threshold);
+ fmt::print("[Pixel Cut] pixel mean window size: {}\n", auto_curation_state.auto_cut_diag_window_for_pixel_mean);
+ fmt::print("[Pixel Cut] smallest_frag_size_in_pixel: {}\n", auto_curation_state.auto_cut_smallest_frag_size_in_pixel);
+
+ // auto_cut_button = 0;
+ // nk_popup_close(NK_Context);
+ }
+ /* run cut 按钮 */
+ if (nk_button_label(NK_Context, "Run") && currFileName) {
+
+ // Convert text to integer and float
+ auto_curation_state.update_value_from_buf(); // todo 这里还有问题,因为设置了pixel_mean之后 并没有重新计算 pixel_density...
+ auto_curation_state.set_buf();
+ fmt::print("[Pixel Cut] cut_threshold: {:.3f}\n", auto_curation_state.auto_cut_threshold);
+ fmt::print("[Pixel Cut] pixel mean window size: {}\n", auto_curation_state.auto_cut_diag_window_for_pixel_mean);
+ fmt::print("[Pixel Cut] smallest_frag_size_in_pixel: {}\n", auto_curation_state.auto_cut_smallest_frag_size_in_pixel);
+
+ auto_cut_button = 0;
+ auto_cut_state = 1;
+ auto_curation_state.clear(); // click the button will run sort globally
+ nk_popup_close(NK_Context);
+ }
+
+ /* 关闭按钮 */
+ if (nk_button_label(NK_Context, "Close")) {
+ auto_cut_button = 0;
+ auto_curation_state.set_buf();
+ nk_popup_close(NK_Context);
+ }
+
+
+ nk_popup_end(NK_Context);
+ } else {
+ /* 如果用户点击了窗口外的区域,也关闭弹出窗口 */
+ auto_cut_button = 0;
+ #ifdef DEBUG
+ fmt::println("Outside of the popup window is clicked.");
+ #endif // debug
}
-
- nk_contextual_end(NK_Context);
-
-
}
}
// Pixel Sort button
bounds = nk_widget_bounds(NK_Context);
- auto_sort_button = nk_button_label(NK_Context, "Pixel Sort");
- {
- if (auto_sort_button && currFileName)
- {
- auto_sort_state = 1;
- auto_curation_state.clear(); // if click the button, the sort/cut will be applied globally
- }
+ auto_sort_button = nk_button_label(NK_Context, "Pixel Sort") ||auto_sort_button ;
+ if (auto_sort_button) {
// window to set the parameters for sort
- if (nk_contextual_begin(NK_Context, 0, nk_vec2(Screen_Scale.x * 480, Screen_Scale.y * 400), bounds))
- {
+ static struct nk_rect popup_rect = nk_rect(
+ Screen_Scale.x * 200, Screen_Scale.y * 100,
+ Screen_Scale.x * 480, Screen_Scale.y * 260);
+ if (nk_popup_begin(NK_Context, NK_POPUP_STATIC, "Pixel Sort Parameters",
+ NK_WINDOW_CLOSABLE|NK_WINDOW_BORDER, popup_rect)) {
nk_layout_row_dynamic(NK_Context, Screen_Scale.y * 30.0f, 1);
nk_label(NK_Context, "Smallest Frag Size (default: 2)", NK_TEXT_LEFT);
nk_edit_string_zero_terminated(
@@ -11369,45 +11990,49 @@ MainArgs
nk_layout_row_dynamic(NK_Context, Screen_Scale.y * 30.0f, 3);
if (nk_option_label(NK_Context, "UnionFind", auto_curation_state.sort_mode == 0))
- {
auto_curation_state.sort_mode = 0;
- }
if (nk_option_label(NK_Context, "Fuse", auto_curation_state.sort_mode == 1))
- {
auto_curation_state.sort_mode = 1;
- }
if (nk_option_label(NK_Context, "Deep Fuse", auto_curation_state.sort_mode == 2))
- {
auto_curation_state.sort_mode = 2;
- }
-
- // if (nk_option_label(NK_Context, "YaHS", auto_curation_state.sort_mode == 3))
- // {
- // auto_curation_state.sort_mode = 3;
- // }
- nk_layout_row_dynamic(NK_Context, Screen_Scale.y * 30.0f, 2);
- if (nk_button_label(NK_Context, "Cancel"))
- {
- printf("[Pixel Sort] Cancel button clicked\n");
- auto_curation_state.set_buf();
- nk_contextual_close(NK_Context);
- }
- if (nk_button_label(NK_Context, "Apply"))
+ nk_layout_row_dynamic(NK_Context, Screen_Scale.y * 30.0f, 3);
+ if (nk_button_label(NK_Context, "Apply settings"))
{
// Apply changes
// Convert text to integer and float
auto_curation_state.update_value_from_buf();
-
- nk_contextual_close(NK_Context);
-
auto_curation_state.set_buf();
fmt::print("[Pixel Sort] smallest_frag_size_in_pixel: {}\n", auto_curation_state.smallest_frag_size_in_pixel);
fmt::print("[Pixel Sort] link_score_threshold: {:.3f}\n", auto_curation_state.link_score_threshold);
fmt::print("[Pixel Sort] Sort mode: {}\n", auto_curation_state.get_sort_mode_name());
+ // auto_sort_button = 0;
+ // nk_popup_close(NK_Context);
+ }
+ /* run sort 按钮 */
+ if (nk_button_label(NK_Context, "Run") && currFileName) {
+
+ // Convert text to integer and float
+ auto_curation_state.update_value_from_buf();
+ auto_curation_state.set_buf();
+ fmt::print("[Pixel Sort] smallest_frag_size_in_pixel: {}\n", auto_curation_state.smallest_frag_size_in_pixel);
+ fmt::print("[Pixel Sort] link_score_threshold: {:.3f}\n", auto_curation_state.link_score_threshold);
+ fmt::print("[Pixel Sort] Sort mode: {}\n", auto_curation_state.get_sort_mode_name());
+
+ auto_sort_button = 0;
+ auto_sort_state = 1;
+ auto_curation_state.clear(); // click the button will run sort globally
+ nk_popup_close(NK_Context);
+ }
+ // 关闭按钮
+ if (nk_button_label(NK_Context, "Close")) {
+ auto_sort_button = 0;
+ auto_curation_state.set_buf();
+ nk_popup_close(NK_Context);
}
+ /*
// redo all the changes
if (!auto_curation_state.show_autoSort_redo_confirm_popup)
{
@@ -11456,7 +12081,16 @@ MainArgs
auto_curation_state.show_autoSort_erase_confirm_popup=false;
}
}
- nk_contextual_end(NK_Context);
+ */
+
+ nk_popup_end(NK_Context);
+
+ } else {
+ /* 如果用户点击了窗口外的区域,也关闭弹出窗口 */
+ auto_sort_button = 0;
+ #ifdef DEBUG
+ fmt::println("Outside of the popup window is clicked.");
+ #endif // debug
}
}
pop_nk_style(NK_Context, 3); // pop the style for Pixel Cut and Pixel Sort button
@@ -11585,8 +12219,8 @@ MainArgs
nk_contextual_end(NK_Context);
}
- if ((nk_option_label(NK_Context, "Select sort area", Global_Mode == mode_selectExclude_sort_area) ? 1 : 0) != (Global_Mode == mode_selectExclude_sort_area ? 1 : 0))
- Global_Mode = (Global_Mode == mode_selectExclude_sort_area ? mode_normal : mode_selectExclude_sort_area);
+ if ((nk_option_label(NK_Context, "Select sort area", Global_Mode == mode_select_sort_area) ? 1 : 0) != (Global_Mode == mode_select_sort_area ? 1 : 0))
+ Global_Mode = (Global_Mode == mode_select_sort_area ? mode_normal : mode_select_sort_area);
nk_layout_row_dynamic(NK_Context, Screen_Scale.y * 30.0f, 2);
Waypoints_Always_Visible = nk_check_label(NK_Context, "Waypoints Always Visible", (s32)Waypoints_Always_Visible) ? 1 : 0;
@@ -11768,7 +12402,8 @@ MainArgs
if (*Meta_Data->tags[i] == 0) break;
int tmp = ( MetaData_Active_Tag == i) ;
tmp = nk_check_label(NK_Context, (char*)Meta_Data->tags[i], tmp);
- if (tmp) MetaData_Active_Tag = i;
+ if (tmp)
+ MetaData_Active_Tag = i;
}
nk_tree_pop(NK_Context);
}
@@ -11780,12 +12415,19 @@ MainArgs
for (u32 i = 0; i < ArrayCount(Meta_Data->tags); i ++ )
{
if (*Meta_Data->tags[i] == 0) break;
- s32 tmp = Grey_Out_Settings->grey_out_flags[i];
- nk_checkbox_label(NK_Context, (char*)Meta_Data->tags[i], Grey_Out_Settings->grey_out_flags+i);
- if (tmp!=Grey_Out_Settings->grey_out_flags[i])
- {
- fmt::print("[UserPofile]: Grey out tags changed\n");
- UserSaveState();
+ if (Grey_Out_Settings->paint_tags.count(std::string((char*)Meta_Data->tags[i])) != 0 ){
+ s32 non = 0;
+ nk_checkbox_label(NK_Context, (char*)Meta_Data->tags[i], &non);
+ *(Grey_Out_Settings->grey_out_flags+i) = 0;
+ }
+ else{
+ s32 tmp = Grey_Out_Settings->grey_out_flags[i];
+ nk_checkbox_label(NK_Context, (char*)Meta_Data->tags[i], Grey_Out_Settings->grey_out_flags+i);
+ if (tmp!=Grey_Out_Settings->grey_out_flags[i])
+ {
+ fmt::print("[UserPofile]: Grey out tag {}({}) changed from {} to {}\n", (char*)Meta_Data->tags[i], i, tmp>0?"true":"false", *(Grey_Out_Settings->grey_out_flags+i)>0?"true":"false");
+ UserSaveState();
+ }
}
}
nk_tree_pop(NK_Context);
@@ -12098,7 +12740,7 @@ MainArgs
// Input Sequences
{
- std::string input_sequence_name = fmt::format("Input Sequences ({})", Number_of_Original_Contigs);
+ std::string input_sequence_name = fmt::format("Input Sequences ({} / Max:{})", Number_of_Original_Contigs, Max_Number_of_Contigs);
nk_layout_row_dynamic(NK_Context, Screen_Scale.y * 30.0f, 1);
if (nk_tree_push(NK_Context, NK_TREE_TAB, input_sequence_name.c_str(), NK_MINIMIZED))
{
@@ -12189,7 +12831,7 @@ MainArgs
contig *cont = Contigs->contigs_arr + index2;
f32 contLen = (f32)((f64)cont->length / (f64)Number_of_Pixels_1D);
- if (*cont->metaDataFlags & (1 << index))
+ if (*cont->metaDataFlags & (1ULL << index))
{
char buff[128];
u32 startCoord = cont->startCoord;
@@ -12356,6 +12998,10 @@ MainArgs
if (FileBrowserRun("Load State", &loadBrowser, NK_Context, (u32)showLoadStateScreen)) LoadState(headerHash, loadBrowser.file);
+ if (FileBrowserRun("Load AGP", &loadAGPBrowser, NK_Context, (u32)showLoadAGPScreen))
+ Load_AGP(loadAGPBrowser.file);
+
+
MetaTagsEditorRun(NK_Context, (u08)showMetaDataTagEditor);
}
@@ -12396,21 +13042,10 @@ MainArgs
}
if (!Redisplay) glfwWaitEvents();
+ Stuck_Problem_Check_Debug
}
if (currFileName) SaveState(headerHash);
-
- ThreadPoolWait(Thread_Pool);
- ThreadPoolDestroy(Thread_Pool);
- glfonsDelete(FontStash_Context);
- nk_font_atlas_clear(NK_Atlas);
- nk_free(NK_Context);
- nk_buffer_free(&NK_Device->cmds);
- glfwDestroyWindow(window);
- glfwTerminate();
-
- // free the memory allocated for the shader sources
- fprintf(stdout, "Memory freed for shader sources.\n");
// do we need to free anything else?
// for example the allocated memory arena
@@ -12445,9 +13080,28 @@ MainArgs
{
delete frag_sort_method; frag_sort_method = nullptr;
}
+ #ifdef PYTHON_SCOPED_INTERPRETER
+ if (kmeans_cluster)
+ {
+ delete kmeans_cluster; kmeans_cluster = nullptr;
+ }
+ #endif // PYTHON_SCOPED_INTERPRETER
+
+
+ ThreadPoolWait(Thread_Pool);
+ ThreadPoolDestroy(Thread_Pool);
+ glfonsDelete(FontStash_Context);
+ nk_font_atlas_clear(NK_Atlas);
+ nk_free(NK_Context);
+ nk_buffer_free(&NK_Device->cmds);
+ glfwDestroyWindow(window);
+ glfwTerminate();
+
+ // free the memory allocated for the shader sources
+ fprintf(stdout, "Memory freed: shader sources.\n");
ResetMemoryArenaP(Loading_Arena);
- fprintf(stdout, "Memory freed for the arena.\n");
+ fprintf(stdout, "Memory freed: the arena.\n");
EndMain;
}
diff --git a/include/stb_image_resize.h b/include/stb_image_resize.h
index bcca92c..a828fc1 100644
--- a/include/stb_image_resize.h
+++ b/include/stb_image_resize.h
@@ -385,7 +385,7 @@ STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int
#ifdef STBIR_DEBUG
#define STBIR__DEBUG_ASSERT STBIR_ASSERT
#else
-#define STBIR__DEBUG_ASSERT
+#define STBIR__DEBUG_ASSERT(x)
#endif
// If you hit this it means I haven't done it yet.
diff --git a/include/stb_image_write.h b/include/stb_image_write.h
index a19b548..6504811 100644
--- a/include/stb_image_write.h
+++ b/include/stb_image_write.h
@@ -740,7 +740,7 @@ static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, f
#ifdef __STDC_WANT_SECURE_LIB__
len = sprintf_s(buffer, sizeof(buffer), "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
#else
- len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
+ len = std::snprintf(buffer, sizeof(buffer), "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
#endif
s->func(s->context, buffer, len);
diff --git a/install b/install
old mode 100755
new mode 100644
diff --git a/install.cmake.sh b/install.cmake.sh
old mode 100755
new mode 100644
index 05efad3..38e524b
--- a/install.cmake.sh
+++ b/install.cmake.sh
@@ -90,6 +90,7 @@ CMAKE_OPTIONS=(
-DCMAKE_INSTALL_PREFIX="$install_path"
-DCMAKE_PREFIX_PATH="$cmake_prefix_path_tmp"
-DCMAKE_OSX_ARCHITECTURES=${ARCH}
+ -DPYTHON_SCOPED_INTERPRETER=OFF
)
if [[ "$OS" == "Darwin" ]]; then
if [[ "$FORCE_MAC_X86" == true ]]; then
diff --git a/install.sh b/install.sh
old mode 100755
new mode 100644
diff --git a/mac_dmg_generate.sh b/mac_dmg_generate.sh
old mode 100755
new mode 100644
diff --git a/make_macos_app_plist.sh b/make_macos_app_plist.sh
old mode 100755
new mode 100644
diff --git a/python/autoCut/models/swin/setup.py b/python/autoCut/models/swin/setup.py
old mode 100755
new mode 100644
diff --git a/python/frag_cluster/kmeans_utils.py b/python/frag_cluster/kmeans_utils.py
new file mode 100644
index 0000000..6602a5a
--- /dev/null
+++ b/python/frag_cluster/kmeans_utils.py
@@ -0,0 +1,134 @@
+
+import re
+from scipy.linalg import eigh
+from sklearn.cluster import KMeans, SpectralClustering
+from sklearn.metrics import silhouette_score
+import numpy as np
+
+"""
+ genome片段聚类分析:
+ 1. 读取基因组片段数据
+ 2. 计算拉普拉斯矩阵
+ 3. 谱聚类
+
+"""
+
+
+class Frags:
+ def __init__(self):
+ self.n = 0
+ self.frags_infos = np.zeros((self.n, 4))
+ self.adj_matrix = np.zeros((self.n, self.n, 5))
+
+ def ini_size(self, n:int):
+ self.n = n
+ self.frags_infos = np.zeros((self.n, 4))
+ self.adj_matrix = np.zeros((self.n, self.n, 5)) # 邻接矩阵
+
+ def read_frags_adj_matrix(self, frags_file):
+ """
+ 读取基因组片段数据
+ :param frags_file: 基因组片段文件
+ :return: None
+ """
+ with open(frags_file, 'r') as f:
+ while (line := f.readline()):
+ if re.match(r'# frags num:', line):
+ n = int(line.split(':')[1].strip())
+ self.ini_size(n)
+ elif re.match(r'# frags_index', line):
+ for i in range(self.n):
+ line_tmp = f.readline().strip().split()
+ self.frags_infos[i] = [int(j) for j in line_tmp]
+ elif re.match(r'# Matrix shape:', line):
+ shape = [int(j) for j in line.split(':')[1].strip().split()]
+ if shape[0] != self.n or shape[1] != self.n or shape[2] != 5:
+ raise ValueError("Matrix shape is not correct")
+ for layer_tmp in range(5):
+ line = f.readline().strip()
+ if not re.match(r'# layer:', line):
+ raise ValueError(f"Matrix shape is not correct, line: {line}")
+ for row_tmp in range(self.n):
+ line_tmp = f.readline().strip().split()
+ self.adj_matrix[row_tmp, :, layer_tmp] = [float(j) for j in line_tmp]
+ elif line == '\n': continue
+ else:
+ print(f"[Frags file reading :: Warning]: {line}")
+
+ print("[Frags file reading :: Status]: Read file successfully")
+
+
+ def kmeans_cluster(self, k, matrix:np.ndarray = None):
+ """
+ 计算特征值和特征向量
+ :return: None
+ """
+ if matrix is None:
+ raise ValueError("Matrix is None, please provide a matrix")
+ processed_adj_matrix = np.max(matrix[..., :4], axis=-1)
+ print(f"[KMeans]: original matrix shape = {matrix.shape} processed matrix shape = {processed_adj_matrix.shape}")
+ # 谱聚类
+ model = SpectralClustering(
+ n_clusters=k,
+ affinity='precomputed', # 相似度计算方式(高斯核或K近邻)
+ assign_labels='kmeans' # 低维空间用K-Means聚类
+ )
+ clusters = model.fit_predict(processed_adj_matrix)
+ return clusters
+
+ def auto_kmeans_cluster(self, k_range=range(2, 20), matrix: np.ndarray = None):
+ """
+ 自动选择最佳聚类数并聚类(基于轮廓系数)
+ """
+ if matrix is None:
+ matrix = self.adj_matrix
+ processed_adj_matrix = np.max(matrix[..., :4], axis=-1)
+ degrees = np.sum(processed_adj_matrix, axis=1)
+ D = np.diag(degrees)
+ lap_matrix = D - processed_adj_matrix
+
+ eigenvalues, eigenvectors = eigh(lap_matrix)
+
+ best_k = None
+ best_score = -1
+ best_labels = None
+
+ for k in k_range:
+ if k >= matrix.shape[0]: break
+ kmeans = KMeans(n_clusters=k, n_init=10, random_state=0)
+ labels = kmeans.fit_predict(eigenvectors[:, :k])
+ score = silhouette_score(eigenvectors[:, :k], labels)
+ if score > best_score:
+ best_k = k
+ best_score = score
+ best_labels = labels
+
+ print(f"[Auto-KMeans]: Best K = {best_k}, silhouette score = {best_score:.4f}")
+ return best_labels
+
+
+
+def run_kmeans(k = 6, matrix:np.ndarray = None):
+ """
+ 运行kmeans聚类
+ :return: None
+ """
+ frags = Frags()
+ if matrix is None:
+ raise ValueError("Matrix is None, please provide a matrix")
+ frags.read_frags_adj_matrix("/Users/sg35/PretextView/build_cmake/PretextViewAI.app/Contents/Resources/frags_info_likelihood_table.txt")
+
+ return frags.kmeans_cluster(k).astype(np.int32)
+ else:
+ return frags.kmeans_cluster(k, matrix).astype(np.int32)
+
+
+
+
+
+if __name__ == "__main__":
+ frags = Frags()
+ frags.read_frags_adj_matrix("/Users/sg35/PretextView/build_cmake/PretextViewAI.app/Contents/Resources/frags_info_likelihood_table.txt")
+ lables = frags.kmeans_cluster(10)
+ print(f"labels = {lables}")
+
diff --git a/src/Resources.cpp b/src/Resources.cpp
old mode 100755
new mode 100644
index 2423fa8..39b2ea6
--- a/src/Resources.cpp
+++ b/src/Resources.cpp
@@ -7,6 +7,7 @@
global_variable
u08
Licence[] = R"lic(Copyright (c) 2021 Ed Harry, Wellcome Sanger Institute
+ 2024 Shaoheng Guan, Wellcome Sanger Institute
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/src/aisort.cpp b/src/aisort.cpp
index 81a7c11..645ce6b 100644
--- a/src/aisort.cpp
+++ b/src/aisort.cpp
@@ -22,7 +22,7 @@ SOFTWARE.
*/
-#include
+#include "aisort.h"
/*
diff --git a/src/auto_curation_state.h b/src/auto_curation_state.h
index e1b8454..297538f 100644
--- a/src/auto_curation_state.h
+++ b/src/auto_curation_state.h
@@ -15,7 +15,7 @@ struct SelectArea
u32 end_pixel = 0;
s32 source_frag_id = -1;
s32 sink_frag_id = -1;
- std::vector selected_frag_ids;
+ std::vector selected_frag_ids;
void clearup()
@@ -28,21 +28,16 @@ struct SelectArea
this->selected_frag_ids.clear();
}
- /*
- first frag id, including the source fragment
- */
- u32 get_first_frag_id()
- {
- return this->source_frag_id >=0? this->source_frag_id : this->selected_frag_ids[0];
- }
-
/*
len in pixel, including the source and sink fragments
*/
- u32 get_selected_len(const contigs* Contigs) const
+ u32 get_selected_len(
+ const contigs* Contigs,
+ const bool used_for_cluster_flag=false
+ ) const
{
u32 len = 0;
- if (this->source_frag_id>=0)
+ if (this->source_frag_id>=0 && !used_for_cluster_flag)
{
len += Contigs->contigs_arr[this->source_frag_id].length;
}
@@ -50,7 +45,7 @@ struct SelectArea
{
len += Contigs->contigs_arr[frag_id].length;
}
- if (this->sink_frag_id>=0)
+ if (this->sink_frag_id>=0 && !used_for_cluster_flag)
{
len += Contigs->contigs_arr[this->sink_frag_id].length;
}
@@ -62,7 +57,7 @@ struct SelectArea
*/
u32 get_to_sort_frags_num()
{
- return this->selected_frag_ids.size() + (this->source_frag_id>=0) + (this->sink_frag_id>=0);
+ return (this->source_frag_id>=0) + this->selected_frag_ids.size() + (this->sink_frag_id>=0);
}
/*
@@ -71,7 +66,7 @@ struct SelectArea
std::vector get_to_sort_frags_id(const contigs* Contigs)
{
std::vector to_sort_frags;
- if (this->source_frag_id>=0)
+ if (this->source_frag_id>=0 )
{
to_sort_frags.push_back(this->source_frag_id);
}
@@ -79,7 +74,7 @@ struct SelectArea
{
to_sort_frags.push_back(frag_id);
}
- if (this->sink_frag_id>=0)
+ if (this->sink_frag_id>=0 )
{
to_sort_frags.push_back(this->sink_frag_id);
}
@@ -105,9 +100,16 @@ struct AutoCurationState
f32 link_score_threshold = 0.4f;
f32 auto_cut_threshold = 0.05f;
- u32 auto_cut_diag_window_for_pixel_mean= 8;
+ u32 auto_cut_diag_window_for_pixel_mean = 8;
u32 auto_cut_smallest_frag_size_in_pixel = 8;
+ // cluster according to the hap name
+ u08 hap_cluster_flag = 0;
+
+ // kmeans cluster
+ u32 num_clusters = 1;
+ const s32 min_frag_num_for_cluster = 4;
+
// Variables for the editing UI state
bool show_autoSort_erase_confirm_popup = false;
bool show_autoSort_redo_confirm_popup = false;
@@ -115,14 +117,16 @@ struct AutoCurationState
u32 sort_mode = 1; // 0: union find, 1: fuse union find, 2 deep fuse, 3 yahs
std::vector sort_mode_names = {"Union Find", "Fuse", "Deep Fuse"};
- // auto sort
+ // pixel sort
char frag_size_buf[16];
char score_threshold_buf[16];
- // auto cut
+ // pixel cut
char auto_cut_threshold_buf[16];
char auto_cut_diag_window_for_pixel_mean_buf[16];
char auto_cut_smallest_frag_size_in_pixel_buf[16];
+ bool auto_cut_with_extension = true; // considering the gap extension while cutting
+ s32 auto_cut_gap_loc_threshold = 3; // if the distance between the calculated cut loc and the gap is less than this value, the cut will be made at the gap
AutoCurationState()
{
@@ -282,13 +286,14 @@ struct AutoCurationState
map_state* Map_State,
u32 number_of_pixels_1D,
contigs* Contigs,
- u08 exclude_flag=false)
+ u08 exclude_flag=false
+ ) // return cluster_flag
{
if (this->start_pixel > number_of_pixels_1D || this->end_pixel > number_of_pixels_1D || this->start_pixel < 0 || this->end_pixel < 0)
{
- // char buff[128];
- // snprintf((char*)buff, 128, "start_pixel(%d) and end_pixel(%d) should be within [0, Number_of_Pixels_1D(%d)-1]", this->start_pixel, this->end_pixel, number_of_pixels_1D);
- // MY_CHECK((const char*) buff);
+ // fmt::println(stderr,
+ // "[AutoCurationState::get_selected_fragments]: start_pixel({}) should smaller than end_pixel({}), and they should be within [0, Number_of_Pixels_1D({})-1], file:{}, line:{}\n",
+ // this->start_pixel, this->end_pixel, number_of_pixels_1D, __FILE__, __LINE__);
return ;
}
if (this->start_pixel > this->end_pixel)
@@ -300,22 +305,7 @@ struct AutoCurationState
{
select_area.clearup();
}
-
- // define source frag
- if (this->start_pixel>0)
- {
- u32 frag_id = Map_State->contigIds[this->start_pixel-1];
- if (Contigs->contigs_arr[frag_id].length >= this->smallest_frag_size_in_pixel)
- {
- select_area.source_frag_id = frag_id;
- }
- else
- {
- select_area.source_frag_id = -1;
- fmt::print("The source_frag_len ({}) < smallest_length ({}), not set the source frag.\n", Contigs->contigs_arr[frag_id].length, this->smallest_frag_size_in_pixel);
- }
- }
-
+
// push the selected frag id into select_area
select_area.start_pixel = this->start_pixel;
select_area.end_pixel = this->end_pixel;
@@ -331,6 +321,21 @@ struct AutoCurationState
}
}
+ // define source frag
+ if (this->start_pixel>0 ) // if selected frags <= 5, still sort them together without clustering first.
+ {
+ u32 frag_id = Map_State->contigIds[this->start_pixel-1];
+ if (Contigs->contigs_arr[frag_id].length >= this->smallest_frag_size_in_pixel)
+ {
+ select_area.source_frag_id = frag_id;
+ }
+ else
+ {
+ select_area.source_frag_id = -1;
+ fmt::print("The source_frag_len ({}) < smallest_length ({}), not set the source frag.\n", Contigs->contigs_arr[frag_id].length, this->smallest_frag_size_in_pixel);
+ }
+ }
+
// define sink frag
if (this->end_pixel + 1 <= number_of_pixels_1D - 1)
{
@@ -347,6 +352,8 @@ struct AutoCurationState
}
// set the select_area to valid
if (!select_area.selected_frag_ids.empty()) select_area.select_flag = 1;
+
+ return;
}
void update_sort_area(
diff --git a/src/copy_texture.cpp b/src/copy_texture.cpp
index cab6001..770c178 100644
--- a/src/copy_texture.cpp
+++ b/src/copy_texture.cpp
@@ -24,7 +24,7 @@ SOFTWARE.
#include "copy_texture.h"
#include "shaderSource.h"
#include "utilsPretextView.h"
-#include "cmath"
+#include
Show_State::Show_State()
@@ -60,71 +60,71 @@ void get_linear_mask(std::vector& linear_array)
}
+#ifdef DEBUG
+ // Callback function for mouse scroll
+ void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
+ {
+ // pass the scroll event to the ImGui
+ ImGuiIO& io = ImGui::GetIO();
+ io.MouseWheelH += (f32)xoffset;
+ io.MouseWheel += (f32)yoffset;
-// Callback function for mouse scroll
-void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
-{
- // pass the scroll event to the ImGui
- ImGuiIO& io = ImGui::GetIO();
- io.MouseWheelH += (f32)xoffset;
- io.MouseWheel += (f32)yoffset;
-
- if (io.WantCaptureMouse) return ;
- auto* show_state = reinterpret_cast(glfwGetWindowUserPointer(window));
- if (show_state->show_menu_window) return;
- f32* zoomlevel = &show_state->zoomlevel;
- // Adjust the zoom level based on the scroll input
- *zoomlevel *= (1.0 - yoffset * 0.05f); // Change 0.1f to adjust sensitivity
-
- // Clamp the zoom level to prevent excessive zooming
- if (*zoomlevel < 1.0 / 32. / 4.) *zoomlevel = 1.0 / 32. / 4.;
- if (*zoomlevel > 1.0f) *zoomlevel = 1.f;
-}
+ if (io.WantCaptureMouse) return ;
+ auto* show_state = reinterpret_cast(glfwGetWindowUserPointer(window));
+ if (show_state->show_menu_window) return;
+ f32* zoomlevel = &show_state->zoomlevel;
+ // Adjust the zoom level based on the scroll input
+ *zoomlevel *= (1.0 - yoffset * 0.05f); // Change 0.1f to adjust sensitivity
+ // Clamp the zoom level to prevent excessive zooming
+ if (*zoomlevel < 1.0 / 32. / 4.) *zoomlevel = 1.0 / 32. / 4.;
+ if (*zoomlevel > 1.0f) *zoomlevel = 1.f;
+ }
-void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
-{
- // pass the mouse button event to the ImGui
- ImGuiIO& io = ImGui::GetIO();
- if (button >= 0 && button < IM_ARRAYSIZE(io.MouseDown)) {
- io.MouseDown[button] = (action == GLFW_PRESS);
- }
-
- if (io.WantCaptureMouse) return ;
- auto* show_state = reinterpret_cast(glfwGetWindowUserPointer(window));
- if (show_state->show_menu_window) return;
- if (button == GLFW_MOUSE_BUTTON_LEFT) {
- if (action == GLFW_PRESS) {
- show_state->isDragging = true;
- glfwGetCursorPos(window, &show_state->lastMouseX, &show_state->lastMouseY); // Initial cursor position
- } else if (action == GLFW_RELEASE) {
- show_state->isDragging = false;
+ void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
+ {
+ // pass the mouse button event to the ImGui
+ ImGuiIO& io = ImGui::GetIO();
+ if (button >= 0 && button < IM_ARRAYSIZE(io.MouseDown)) {
+ io.MouseDown[button] = (action == GLFW_PRESS);
+ }
+
+ if (io.WantCaptureMouse) return ;
+ auto* show_state = reinterpret_cast(glfwGetWindowUserPointer(window));
+ if (show_state->show_menu_window) return;
+ if (button == GLFW_MOUSE_BUTTON_LEFT) {
+ if (action == GLFW_PRESS) {
+ show_state->isDragging = true;
+ glfwGetCursorPos(window, &show_state->lastMouseX, &show_state->lastMouseY); // Initial cursor position
+ } else if (action == GLFW_RELEASE) {
+ show_state->isDragging = false;
+ }
}
}
-}
-void cursor_position_callback(GLFWwindow* window, double xpos, double ypos)
-{
- // pass the cursor position to the ImGui
- ImGuiIO& io = ImGui::GetIO();
- io.MousePos = ImVec2((f32)xpos, (f32)ypos);
+ void cursor_position_callback(GLFWwindow* window, double xpos, double ypos)
+ {
+ // pass the cursor position to the ImGui
+ ImGuiIO& io = ImGui::GetIO();
+ io.MousePos = ImVec2((f32)xpos, (f32)ypos);
- if (io.WantCaptureMouse) return ;
- auto* show_state = reinterpret_cast(glfwGetWindowUserPointer(window));
- if (show_state->show_menu_window) return;
+ if (io.WantCaptureMouse) return ;
+ auto* show_state = reinterpret_cast(glfwGetWindowUserPointer(window));
+ if (show_state->show_menu_window) return;
- if (show_state->isDragging) {
- double dx = xpos - show_state->lastMouseX;
- double dy = ypos - show_state->lastMouseY;
+ if (show_state->isDragging) {
+ double dx = xpos - show_state->lastMouseX;
+ double dy = ypos - show_state->lastMouseY;
- // Adjust the translation offset based on mouse movement (scale as needed)
- show_state->translationOffset.x += static_cast(dx) * 0.00175f * show_state->zoomlevel; // Adjust sensitivity with 0.01f
- show_state->translationOffset.y -= static_cast(dy) * 0.00175f * show_state->zoomlevel;
+ // Adjust the translation offset based on mouse movement (scale as needed)
+ show_state->translationOffset.x += static_cast(dx) * 0.00175f * show_state->zoomlevel; // Adjust sensitivity with 0.01f
+ show_state->translationOffset.y -= static_cast(dy) * 0.00175f * show_state->zoomlevel;
- show_state->lastMouseX = xpos;
- show_state->lastMouseY = ypos;
+ show_state->lastMouseX = xpos;
+ show_state->lastMouseY = ypos;
+ }
}
-}
+#endif // DEBUG
TexturesArray4AI::TexturesArray4AI(
@@ -268,10 +268,11 @@ TexturesArray4AI::~TexturesArray4AI()
if (this->hic_shader_initilised)
{
- glDeleteShader(this->shaderProgram);
+ // glDeleteShader(this->shaderProgram);
glDeleteBuffers(1, &this->vbo);
glDeleteBuffers(1, &this->ebo);
glDeleteVertexArrays(1, &this->vao);
+ glDeleteProgram(this->shaderProgram);
}
}
@@ -410,12 +411,10 @@ void TexturesArray4AI::copy_buffer_to_textures(
glBindTexture(GL_TEXTURE_2D, 0);
glDeleteTextures(1, &temptexture);
- if (show_flag)
- {
- // show_collected_texture();
- show_collected_textures();
- }
-
+ #ifdef DEBUG
+ if (show_flag) show_collected_textures();
+ #endif // DEBUG
+
// return back to the original viewport
glViewport(orignal_viewport[0], orignal_viewport[1], orignal_viewport[2], orignal_viewport[3]);
@@ -513,10 +512,9 @@ void TexturesArray4AI::copy_buffer_to_textures_dynamic(
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &framebuffer);
- if (show_flag)
- {
- show_collected_textures();
- }
+ #ifdef DEBUG
+ if (show_flag) show_collected_textures();
+ #endif // DEBUG
glViewport(orignal_viewport[0], orignal_viewport[1], orignal_viewport[2], orignal_viewport[3]);
return ;
@@ -701,151 +699,154 @@ void TexturesArray4AI::show_collected_texture()
return ;
}
-
-void TexturesArray4AI::show_collected_textures()
-{
- GLuint tmp_texture2d_array;
- this->prepare_tmp_texture2d_array(tmp_texture2d_array);
-
- GLFWwindow* window = glfwGetCurrentContext();
- if(!window) assert(0);
- glfwSwapInterval(1);
- glfwMakeContextCurrent(window);
- if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) assert(0);
- glfwSetWindowShouldClose(window, false);
-
- // Setup Dear ImGui context
- IMGUI_CHECKVERSION();
- ImGui::CreateContext();
- ImGuiIO& io = ImGui::GetIO(); (void)io;
- io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
- io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
- // Setup Dear ImGui style
- ImGui::StyleColorsDark();
- //ImGui::StyleColorsLight();
- // Setup Platform/Renderer backends
- ImGui_ImplGlfw_InitForOpenGL(window, true);
- #ifdef __EMSCRIPTEN__
- ImGui_ImplGlfw_InstallEmscriptenCallbacks(window, "#canvas");
- #endif
- ImGui_ImplOpenGL3_Init((const char*)"#version 330");
- // Our state
- bool show_demo_window = false;
- bool show_another_window = false;
- glm::vec4 clear_color(0.45f, 0.55f, 0.60f, 1.00f);
- bool m_pressed = false;
-
- int width = 1080, height = 1080;
- glViewport(0, 0, width, height);
- glDisable(GL_CULL_FACE); // can also see the back face
- Show_State show_state;
-
- glfwSetWindowUserPointer(window, &show_state);
- // register the scroll and mouse move callback function
- glfwSetScrollCallback(window, scroll_callback);
- glfwSetMouseButtonCallback(window, mouse_button_callback);
- glfwSetCursorPosCallback(window, cursor_position_callback);
- glUseProgram(shaderProgram);
- GLcall(glUniform1i(glGetUniformLocation(shaderProgram, "texArray"), 0));
- glm::mat4 model_not_flipped = glm::scale( // 控制显示大小
- glm::mat4(1.0f),
- glm::vec3(
- 1.0f/(f32)num_textures_1d,
- -1.0f/(f32)num_textures_1d, // flipped on y axis
- 1.0f));
- glm::mat4 model_flipped = glm::scale( // 控制显示大小
- glm::rotate(model_not_flipped, glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f)),
- glm::vec3(1.0f, -1.0f, 1.0f));
- while (!glfwWindowShouldClose(window))
- {
- int viewport[4];
- glGetIntegerv(GL_VIEWPORT, viewport);
- f32 ratio_w_h = (f32)viewport[2] / (f32)viewport[3];
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
- glClear(GL_COLOR_BUFFER_BIT);
- glActiveTexture(GL_TEXTURE0);
- glBindBuffer(GL_TEXTURE_2D_ARRAY, tmp_texture2d_array);
-
- glBindVertexArray(vao);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
- glm::mat4 projection = glm::ortho( // 控制镜头远近
- -1.0f * ratio_w_h * show_state.zoomlevel, 1.0f * ratio_w_h * show_state.zoomlevel,
- -1.0f * show_state.zoomlevel, 1.0f * show_state.zoomlevel,
- -1.0f, 1.0f);
+#ifdef DEBUG
+ void TexturesArray4AI::show_collected_textures()
+ {
+ GLuint tmp_texture2d_array;
+ this->prepare_tmp_texture2d_array(tmp_texture2d_array);
- glm::mat4 model_tmp;
- for (int row = 0; row < num_textures_1d; row++ )// 显示所有的 tile
- {
- for (int column = 0; column < num_textures_1d; column ++ )
- {
- // if (row > column) continue;
- u32 layer = texture_id_cal((u32)row, (u32)column, num_textures_1d);
- GLcall(glUniform1i(glGetUniformLocation(shaderProgram, "layer"), (int)layer));
- model_tmp = glm::translate( // 控制显示位置
- glm::mat4(1.0f),
- glm::vec3(
- -1.0f + ((f32)column + 0.5f) * 2.0f / (f32)num_textures_1d + show_state.translationOffset.x,
- 1.0f - ((f32)row + 0.5f) * 2.0f / (f32)num_textures_1d + show_state.translationOffset.y,
- 0.0f)
- ) * (row>column?model_flipped:model_not_flipped);
- model_tmp = projection * model_tmp;
- GLcall(glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(model_tmp)));
- glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
+ GLFWwindow* window = glfwGetCurrentContext();
+ if(!window) assert(0);
+ glfwSwapInterval(1);
+ glfwMakeContextCurrent(window);
+ if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) assert(0);
+ glfwSetWindowShouldClose(window, false);
+
+ // Setup Dear ImGui context
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO(); (void)io;
+ io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
+ io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
+ // Setup Dear ImGui style
+ ImGui::StyleColorsDark();
+ //ImGui::StyleColorsLight();
+ // Setup Platform/Renderer backends
+ ImGui_ImplGlfw_InitForOpenGL(window, true);
+ #ifdef __EMSCRIPTEN__
+ ImGui_ImplGlfw_InstallEmscriptenCallbacks(window, "#canvas");
+ #endif
+ ImGui_ImplOpenGL3_Init((const char*)"#version 330");
+ // Our state
+ bool show_demo_window = false;
+ bool show_another_window = false;
+ glm::vec4 clear_color(0.45f, 0.55f, 0.60f, 1.00f);
+ bool m_pressed = false;
+
+ int width = 1080, height = 1080;
+ glViewport(0, 0, width, height);
+ glDisable(GL_CULL_FACE); // can also see the back face
+ Show_State show_state;
+
+ glfwSetWindowUserPointer(window, &show_state);
+ // register the scroll and mouse move callback function
+ glfwSetScrollCallback(window, scroll_callback);
+ glfwSetMouseButtonCallback(window, mouse_button_callback);
+ glfwSetCursorPosCallback(window, cursor_position_callback);
+ glUseProgram(shaderProgram);
+ GLcall(glUniform1i(glGetUniformLocation(shaderProgram, "texArray"), 0));
+ glm::mat4 model_not_flipped = glm::scale( // 控制显示大小
+ glm::mat4(1.0f),
+ glm::vec3(
+ 1.0f/(f32)num_textures_1d,
+ -1.0f/(f32)num_textures_1d, // flipped on y axis
+ 1.0f));
+ glm::mat4 model_flipped = glm::scale( // 控制显示大小
+ glm::rotate(model_not_flipped, glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f)),
+ glm::vec3(1.0f, -1.0f, 1.0f));
+ while (!glfwWindowShouldClose(window))
+ {
+ int viewport[4];
+ glGetIntegerv(GL_VIEWPORT, viewport);
+ f32 ratio_w_h = (f32)viewport[2] / (f32)viewport[3];
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glActiveTexture(GL_TEXTURE0);
+ glBindBuffer(GL_TEXTURE_2D_ARRAY, tmp_texture2d_array);
+
+ glBindVertexArray(vao);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
+ glm::mat4 projection = glm::ortho( // 控制镜头远近
+ -1.0f * ratio_w_h * show_state.zoomlevel, 1.0f * ratio_w_h * show_state.zoomlevel,
+ -1.0f * show_state.zoomlevel, 1.0f * show_state.zoomlevel,
+ -1.0f, 1.0f);
+
+ glm::mat4 model_tmp;
+ for (int row = 0; row < num_textures_1d; row++ )// 显示所有的 tile
+ {
+ for (int column = 0; column < num_textures_1d; column ++ )
+ {
+ // if (row > column) continue;
+ u32 layer = texture_id_cal((u32)row, (u32)column, num_textures_1d);
+ GLcall(glUniform1i(glGetUniformLocation(shaderProgram, "layer"), (int)layer));
+ model_tmp = glm::translate( // 控制显示位置
+ glm::mat4(1.0f),
+ glm::vec3(
+ -1.0f + ((f32)column + 0.5f) * 2.0f / (f32)num_textures_1d + show_state.translationOffset.x,
+ 1.0f - ((f32)row + 0.5f) * 2.0f / (f32)num_textures_1d + show_state.translationOffset.y,
+ 0.0f)
+ ) * (row>column?model_flipped:model_not_flipped);
+ model_tmp = projection * model_tmp;
+ GLcall(glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(model_tmp)));
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
+ }
}
- }
- if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true);
- if (glfwGetKey(window, GLFW_KEY_U) == GLFW_PRESS)
- {
- if (!m_pressed) show_state.show_menu_window = !show_state.show_menu_window;
- m_pressed = true;
- }
- if (glfwGetKey(window, GLFW_KEY_U) == GLFW_RELEASE) m_pressed = false;
-
- // Start the Dear ImGui frame
- ImGui_ImplOpenGL3_NewFrame();
- ImGui_ImplGlfw_NewFrame();
- ImGui::NewFrame();
-
- // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
- if (show_demo_window) ImGui::ShowDemoWindow(&show_demo_window);
- // 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
- if (show_state.show_menu_window )
- {
- ImGui::Begin("Main menu"); // Create a window called "Hello, world!" and append into it.
- ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
-
- ImGui::ColorEdit3("clear color", (f32*)&clear_color[0]); // Edit 3 floats representing a color
- ImGui::Text("Zoom level: %.4f", show_state.zoomlevel);
- ImGui::Text("Translation Offset: (%.2f, %.2f)", show_state.translationOffset.x, show_state.translationOffset.y);
- // ImGui::SameLine();
- ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
- ImGui::End();
- }
+ if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true);
+ if (glfwGetKey(window, GLFW_KEY_U) == GLFW_PRESS)
+ {
+ if (!m_pressed) show_state.show_menu_window = !show_state.show_menu_window;
+ m_pressed = true;
+ }
+ if (glfwGetKey(window, GLFW_KEY_U) == GLFW_RELEASE) m_pressed = false;
+
+ // Start the Dear ImGui frame
+ ImGui_ImplOpenGL3_NewFrame();
+ ImGui_ImplGlfw_NewFrame();
+ ImGui::NewFrame();
+
+ // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
+ if (show_demo_window) ImGui::ShowDemoWindow(&show_demo_window);
+ // 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
+ if (show_state.show_menu_window )
+ {
+ ImGui::Begin("Main menu"); // Create a window called "Hello, world!" and append into it.
+ ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
+
+ ImGui::ColorEdit3("clear color", (f32*)&clear_color[0]); // Edit 3 floats representing a color
+ ImGui::Text("Zoom level: %.4f", show_state.zoomlevel);
+ ImGui::Text("Translation Offset: (%.2f, %.2f)", show_state.translationOffset.x, show_state.translationOffset.y);
+ // ImGui::SameLine();
+ ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
+ ImGui::End();
+ }
- // 3. Show another simple window.
- if (show_another_window)
- {
- ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
- ImGui::Text("Hello from another window!");
- if (ImGui::Button("Close Me"))
- show_another_window = false;
- ImGui::End();
- }
+ // 3. Show another simple window.
+ if (show_another_window)
+ {
+ ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
+ ImGui::Text("Hello from another window!");
+ if (ImGui::Button("Close Me"))
+ show_another_window = false;
+ ImGui::End();
+ }
- // Rendering
- ImGui::Render();
- ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
-
- glfwSwapBuffers(window);
- glfwPollEvents();
- }
+ // Rendering
+ ImGui::Render();
+ ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
+
+ glfwSwapBuffers(window);
+ glfwPollEvents();
+ }
- glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
- glDeleteTextures(1, &tmp_texture2d_array);
- return ;
-}
+ glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
+ glDeleteTextures(1, &tmp_texture2d_array);
+ return ;
+ }
+#else
+ void TexturesArray4AI::show_collected_textures(){return ;}
+#endif // DEBUG
@@ -885,27 +886,37 @@ void TexturesArray4AI::cal_compressed_hic(
bool is_extension_required,
bool is_massCenter_required,
const SelectArea* select_area,
+ const AutoCurationState* auto_curation_state,
f32 D_hic_ratio,
u32 maximum_D,
f32 min_hic_density)
{
check_copied_from_buffer();
- u08 using_select_area = (select_area != nullptr && select_area->select_flag)?1:0;
- // clean the memory of compressed_hic_mx
- frags->re_allocate_mem(Contigs, select_area);
- if (frags->total_length != (using_select_area ? select_area->get_selected_len(Contigs) : num_pixels_1d))
+ u08 using_select_area = (select_area && select_area->select_flag)?1:0;
+
+ u08 cluster_flag = (auto_curation_state && auto_curation_state->num_clusters > 1)?1:0;
+
+ // re-calculate the frags selected within this area
+ frags->re_allocate_mem(
+ Contigs,
+ select_area,
+ false, // used for cut
+ cluster_flag);
+ if (frags->total_length != (using_select_area ? select_area->get_selected_len(Contigs, cluster_flag) : num_pixels_1d))
{
fmt::print(
- "\n[Compress Hic] warning: frags->total_length({}) != num_pixels_1d ({}) ({}). file:{}, line:{}\n\n",
+ "\n[Compress Hic] warning: frags->total_length({}) != num_pixels_1d ({}) ({}) ({}). file:{}, line:{}\n\n",
frags->total_length,
- (using_select_area? (select_area->end_pixel - select_area->start_pixel + 1): num_pixels_1d),
+ using_select_area ? select_area->get_selected_len(Contigs, cluster_flag) : num_pixels_1d,
(using_select_area?"selected area":"full area"),
+ cluster_flag?"clustering":"not clustering",
__FILE__,
__LINE__
);
assert(0);
}
+ // clean the memory of compressed_hic_mx
if (compressed_hic)
{
compressed_hic->re_allocate_mem(
@@ -1044,9 +1055,7 @@ f32 TexturesArray4AI::cal_diagonal_mean_within_fragments(int shift, const contig
return (f32)sum / (f32)std::max(cnt, 1u);
}
-/* todo
-windows: 编译错误,尝试访问 d
-*/
+
void TexturesArray4AI::get_interaction_score(
const u32& row,
const u32& column,
diff --git a/src/copy_texture.h b/src/copy_texture.h
index a13f6e8..17784e8 100644
--- a/src/copy_texture.h
+++ b/src/copy_texture.h
@@ -30,142 +30,16 @@ SOFTWARE.
#include "utilsPretextView.h"
#include "genomeData.h"
#include "auto_curation_state.h"
+#include "frag_for_compress.h"
#include
+#include "self_matrix.h"
-struct Frag4compress {
- u32 num;
- u32* frag_id = nullptr;
- u32* startCoord = nullptr; // global start coordinate
- u32* length = nullptr;
- bool* inversed = nullptr;
- u32 total_length;
- u64* metaDataFlags = nullptr;
-
- Frag4compress(const contigs* Contigs)
- : total_length(0)
- {
- re_allocate_mem(Contigs);
- }
-
- ~Frag4compress()
- {
- cleanup();
- }
-
- void re_allocate_mem(
- const contigs* Contigs,
- const SelectArea* select_area=nullptr,
- bool use_for_cut_flag=false)
- {
- cleanup();
- u08 using_select_area = (select_area != nullptr && select_area->select_flag)?1:0;
- this->num = Contigs->numberOfContigs;
- std::vector selected_frag_ids_tmp;
- if (using_select_area )
- {
- selected_frag_ids_tmp = select_area->selected_frag_ids;
- this->num = select_area->selected_frag_ids.size();
- if (this->num < 2 && !use_for_cut_flag)
- {
- fmt::print(
- stderr,
- "The number_of_select_fragments_for_sorting({}) should not be less than 2, file:{}, line:{}\n", this->num, __FILE__, __LINE__);
- assert(0);
- }
- if (select_area->source_frag_id >=0 && !use_for_cut_flag)
- {
- this->num ++;
- selected_frag_ids_tmp.insert(selected_frag_ids_tmp.begin(), select_area->source_frag_id);
- }
- if (select_area->sink_frag_id >=0 && !use_for_cut_flag)
- {
- this->num ++;
- selected_frag_ids_tmp.push_back(select_area->sink_frag_id);
- }
- }
- else // global area
- {
- selected_frag_ids_tmp.resize(this->num);
- std::iota(selected_frag_ids_tmp.begin(), selected_frag_ids_tmp.end(), 0);
- }
-
- frag_id = new u32[num];
- startCoord = new u32[num];
- length = new u32[num];
- inversed = new bool[num];
- metaDataFlags = new u64[num];
- total_length = 0;
-
- // Initialize the startCoord, length, and inversed
- frag_id[0] = selected_frag_ids_tmp[0];
- inversed[0] = false;
- startCoord[0] = 0;
- if (using_select_area)
- {
- s32 tmp = 0;
- while (tmp < frag_id[0])
- {
- startCoord[0] += Contigs->contigs_arr[tmp].length;
- tmp ++;
- }
- if (tmp>=Contigs->numberOfContigs)
- {
- fmt::print(
- stderr,
- "The frag_id[0]({}) should be less than the number_of_contigs({}), file:{}, line:{}\n",
- frag_id[0], Contigs->numberOfContigs, __FILE__, __LINE__);
- assert(0);
- }
- }
- length[0] = Contigs->contigs_arr[frag_id[0]].length;
- metaDataFlags[0] = (Contigs->contigs_arr[frag_id[0]].metaDataFlags == nullptr)?0:*(Contigs->contigs_arr[frag_id[0]].metaDataFlags);
- total_length = length[0];
-
- for (u32 i = 1; i < num; i++)
- {
- u32 contig_id = selected_frag_ids_tmp[i];
- frag_id[i] = contig_id;
- inversed[i] = false; // currently, this is not used
- startCoord[i] = startCoord[i-1] + length[i-1];
- length[i] = Contigs->contigs_arr[contig_id].length;
- metaDataFlags[i] = (Contigs->contigs_arr[contig_id].metaDataFlags == nullptr)?0:*(Contigs->contigs_arr[contig_id].metaDataFlags);
- total_length += length[i];
- }
- }
-
-private:
- void cleanup()
- {
- if (frag_id)
- {
- delete[] frag_id;
- frag_id = nullptr;
- }
-
- if (startCoord)
- {
- delete[] startCoord;
- startCoord = nullptr;
- }
- if (length)
- {
- delete[] length;
- length = nullptr;
- }
- if (inversed)
- {
- delete[] inversed;
- inversed = nullptr;
- }
- if (metaDataFlags)
- {
- delete[] metaDataFlags;
- metaDataFlags = nullptr;
- }
- total_length = 0;
- }
-};
+#ifdef DEBUG
+ #include
+ #include
+ #include
+#endif // DEBUG
void scroll_callback(GLFWwindow* window, f64 xoffset, f64 yoffset);
@@ -205,164 +79,6 @@ struct Show_State
void get_linear_mask(f32* linear_array, u32 length);
-template
-class Matrix2D
-{
-private:
- T* data = nullptr;
-public:
- u32 row_num, col_num, length;
- u32 shape[2];
- Matrix2D(u32 row_num_, u32 col_num_)
- : row_num(row_num_), col_num(col_num_)
- {
- shape[0] = row_num_;
- shape[1] = col_num_;
- if (row_num_ <= 0 || col_num_ <= 0)
- {
- fprintf(stderr, "The row_num(%d), col_num(%d) should be larger than 0\n", row_num_, col_num_);
- assert(0);
- }
- length = row_num * col_num;
- data = new T[length];
- memset(data, 0, length * sizeof(T));
- }
-
- ~Matrix2D()
- {
- if (data)
- {
- delete[] data;
- data = nullptr;
- }
- }
-
- void check_indexing(const u32& row, const u32& col) const
- {
- if (row >= row_num || col>= col_num)
- {
- fprintf(stderr, "Index [%d, %d] is out of the maximum [%d, %d]\n", row, col, row_num-1, col_num-1);
- assert(0);
- }
- return ;
- }
-
- // Access operator
- T& operator()(const u32& row, const u32& col)
- {
- check_indexing(row, col);
- return data[row * col_num + col];
- }
-
- const T& operator()(const u32& row, const u32& col) const
- {
- check_indexing(row, col);
- return data[row * col_num + col];
- }
-
- T* get_data_ptr() const
- {
- return data;
- }
-
-};
-
-
-
-template
-class Matrix3D
-{
-private:
- T* data = nullptr;
-public:
- u32 row_num, col_num, layer_num, length;
- u32 shape[3];
- Matrix3D(
- u32 row_num_,
- u32 col_num_,
- u32 layer_)
- {
- MY_CHECK(0);
- re_allocate_mem(row_num_, col_num_, layer_);
- }
-
- ~Matrix3D()
- {
- cleanup();
- }
-
- void cleanup()
- {
-
- if (data)
- {
- delete[] data;
- data = nullptr;
- }
- }
-
- void re_allocate_mem(u32 row_num_, u32 col_num_, u32 layer_)
- {
- cleanup();
- row_num = row_num_;
- col_num = col_num_;
- layer_num = layer_;
- shape[0] = row_num_;
- shape[1] = col_num_;
- shape[2] = layer_;
- length = row_num * col_num * layer_num;
-
- data = new T[length];
-
- memset(data, 0, length * sizeof(T));
- }
-
- void check_indexing(const u32& row, const u32& col, const u32& layer) const
- {
- if (row >= row_num || col>= col_num || layer >= layer_num)
- {
- fprintf(stderr, "Index [%d, %d, %d] is out of the maximum [%d, %d, %d]\n", row, col, layer, row_num-1, col_num-1, layer_num-1);
- assert(0);
- }
- return ;
- }
-
- // Access operator
- T& operator()(const u32& row, const u32& col, const u32& layer) {
- check_indexing(row, col, layer);
- return data[row * col_num * layer_num + col * layer_num + layer];
- }
-
- const T& operator()(const u32& row, const u32& col, const u32& layer) const {
- check_indexing(row, col, layer);
- return data[row * col_num * layer_num + col * layer_num + layer];
- }
-
- void set_one(const u32& row, const u32& col, const u32& layer, const T& value)
- {
- check_indexing(row, col, layer);
- data[row * col_num * layer_num + col* layer_num + layer] = value;
- }
-
- void output_to_file(FILE* fp) const
- {
- fmt::print(fp, "# Matrix shape: {} {} {}\n", row_num, col_num, layer_num);
- for (u32 l = 0; l < layer_num; l++)
- {
- fmt::print(fp, "# layer: {}\n", l);
- for (u32 i = 0; i < row_num; i++)
- {
- for (u32 j = 0; j < col_num; j++)
- {
- fmt::print(fp, "{:.4f} ", data[i * col_num * layer_num + j * layer_num + l]);
- }
- fmt::print(fp, "\n");
- }
- }
- }
-};
-
-
struct CompressedExtensions
{
u32 num; // number of extensions: 2 : coverage, repeat_density
@@ -698,6 +414,7 @@ class TexturesArray4AI
bool is_extension_required=true,
bool is_massCenter_required=true,
const SelectArea* select_area=nullptr,
+ const AutoCurationState* auto_curation_state=nullptr,
f32 D_hic_ratio=0.05f,
u32 maximum_D=5000,
f32 min_hic_density = 30.f);
diff --git a/src/frag_cut_calculation.h b/src/frag_cut_calculation.h
index 80023b6..fe165db 100644
--- a/src/frag_cut_calculation.h
+++ b/src/frag_cut_calculation.h
@@ -114,7 +114,7 @@ class FragCutCal
}
}
- std::vector get_cut_locs_pixel(
+ std::vector get_cut_locs_pixel(
const AutoCurationState& auto_curation_state,
const u32* pixel_rearrange_index_,
const contigs* Contigs,
@@ -129,7 +129,7 @@ class FragCutCal
// 在 select_area 中进行cut
this->frags->re_allocate_mem(Contigs, select_area, 1);
- std::vector cut_locs_pixel;
+ std::vector cut_locs_pixel;
for (u32 i = 0; i < this->frags->num; i++)
{
this->get_single_fragment_cut_locs(i, cut_locs_pixel);
@@ -141,7 +141,7 @@ class FragCutCal
void find_break_points(
const u32 start_pixel,
const std::vector& arr,
- std::vector& break_points)
+ std::vector& break_points)
{
const auto& windows_size = this->smallest_frag_size_in_pixel;
const auto& threshold = this->cut_threshold;
@@ -185,7 +185,7 @@ class FragCutCal
min_i = i;
}
}
- break_points.push_back(min_i + start_pixel);
+ break_points.push_back((int)(min_i + start_pixel));
i += windows_size ;
}
}
@@ -196,7 +196,7 @@ class FragCutCal
void get_single_fragment_cut_locs(
const u32& frag_id,
- std::vector& cut_locs)
+ std::vector& cut_locs)
{
// copy orginal to local
std::vector hic_pixel_density_tmp(this->hic_pixel_density.begin() + this->frags->startCoord[frag_id],
@@ -211,7 +211,6 @@ class FragCutCal
#ifdef DEBUG_OUTPUT_PIXEL_CUT_FILE // output the hic_pixel_density to text file
std::string filename = fmt::format("{}/current_id_{}.txt", this->file_save_dir, frag_id);
- fmt::print("[Pixel Cut]: output hic_pixel_density to {}\n", filename);
std::ofstream out(filename);
if (!out)
{
@@ -223,9 +222,10 @@ class FragCutCal
out << hic_pixel_density_tmp[i] << std::endl;
}
out.close();
+ fmt::print("[Pixel Cut]: output hic_pixel_density to {}\n", filename);
#endif // DEBUG_OUTPUT_PIXEL_CUT_FILE
- std::vector break_points(0);
+ std::vector break_points(0);
this->find_break_points(
this->frags->startCoord[frag_id],
hic_pixel_density_tmp,
diff --git a/src/frag_for_compress.h b/src/frag_for_compress.h
new file mode 100644
index 0000000..77618b3
--- /dev/null
+++ b/src/frag_for_compress.h
@@ -0,0 +1,201 @@
+
+#ifndef FRAG_FOR_COMPRESS_H
+#define FRAG_FOR_COMPRESS_H
+
+#include
+#include "utilsPretextView.h"
+#include "genomeData.h"
+#include "auto_curation_state.h"
+#include
+
+
+struct Frag4compress {
+ u32 num; // number of fragments
+ u32* frag_id = nullptr;
+ u32* startCoord = nullptr; // global start coordinate
+ u32* length = nullptr;
+ bool* inversed = nullptr;
+ u32 total_length;
+ u64* metaDataFlags = nullptr;
+
+ Frag4compress(const contigs* Contigs)
+ : total_length(0)
+ {
+ re_allocate_mem(Contigs);
+ }
+
+ Frag4compress()
+ : total_length(0){}
+
+ ~Frag4compress()
+ {
+ cleanup();
+ }
+
+ void re_allocate_mem( // re-initialize frags within the selected area
+ const contigs* Contigs,
+ const SelectArea* select_area=nullptr,
+ bool use_for_cut_flag=false,
+ bool cluster_flag=false
+ )
+ {
+ cleanup();
+ u08 using_select_area = (select_area != nullptr && select_area->select_flag) ? 1:0;
+
+ std::vector selected_frag_ids_tmp;
+ if (using_select_area )
+ {
+ selected_frag_ids_tmp = select_area->selected_frag_ids;
+ this->num = select_area->selected_frag_ids.size();
+ if (this->num < 2 && !use_for_cut_flag)
+ {
+ fmt::print(
+ stderr,
+ "The number_of_select_fragments_for_sorting({}) should not be less than 2, file:{}, line:{}\n", this->num, __FILE__, __LINE__);
+ assert(0);
+ }
+
+ // add the source and sink fragments to the the selected fragments
+ if (select_area->source_frag_id >=0 && !use_for_cut_flag && !cluster_flag)
+ {
+ this->num ++;
+ selected_frag_ids_tmp.insert(selected_frag_ids_tmp.begin(), select_area->source_frag_id);
+ }
+ if (select_area->sink_frag_id >=0 && !use_for_cut_flag && !cluster_flag)
+ {
+ this->num ++;
+ selected_frag_ids_tmp.push_back(select_area->sink_frag_id);
+ }
+ }
+ else // global sort or cut
+ {
+ this->num = Contigs->numberOfContigs;
+ selected_frag_ids_tmp.resize(this->num);
+ std::iota(selected_frag_ids_tmp.begin(), selected_frag_ids_tmp.end(), 0);
+ }
+
+ this->frag_id = new u32[num];
+ this->startCoord = new u32[num];
+ this->length = new u32[num];
+ this->inversed = new bool[num];
+ this->metaDataFlags = new u64[num];
+ this->total_length = 0;
+
+ // Initialize the startCoord, length, and inversed
+ frag_id[0] = selected_frag_ids_tmp[0];
+ inversed[0] = false;
+ startCoord[0] = 0;
+ if (using_select_area)
+ {
+ s32 tmp = 0;
+ while (tmp < frag_id[0])
+ {
+ if (tmp >= Contigs->numberOfContigs)
+ {
+ fmt::print(
+ stderr,
+ "The frag_id[0]({}) should be less than the number_of_contigs({}), file:{}, line:{}\n",
+ frag_id[0], Contigs->numberOfContigs, __FILE__, __LINE__);
+ assert(0);
+ }
+ startCoord[0] += Contigs->contigs_arr[tmp++].length;
+ }
+ }
+ length[0] = Contigs->contigs_arr[frag_id[0]].length;
+ metaDataFlags[0] = (Contigs->contigs_arr[frag_id[0]].metaDataFlags == nullptr)?
+ 0 : *(Contigs->contigs_arr[frag_id[0]].metaDataFlags);
+ total_length = length[0];
+
+ for (u32 i = 1; i < num; i++)
+ {
+ frag_id[i] = selected_frag_ids_tmp[i];
+ inversed[i] = false; // currently, this is not used
+ startCoord[i] = startCoord[i-1] + length[i-1];
+ length[i] = Contigs->contigs_arr[frag_id[i]].length;
+ metaDataFlags[i] = (Contigs->contigs_arr[frag_id[i]].metaDataFlags == nullptr)?
+ 0 : *(Contigs->contigs_arr[frag_id[i]].metaDataFlags);
+ total_length += length[i];
+ }
+ }
+
+ void re_allocate_mem( // re-initialize frags within selected fragments
+ const contigs* Contigs,
+ const std::vector& selected_frag_ids_tmp
+ )
+ {
+ cleanup();
+ this->num = selected_frag_ids_tmp.size();
+ if (this->num < 2)
+ {
+ fmt::print(
+ stderr,
+ "[Frag4compress::re_allocate_mem::warning]: number_of_select_fragments_for_sorting({}) should not < 2, file:{}, line:{}\n", this->num, __FILE__, __LINE__);
+ }
+
+ this->frag_id = new u32[num];
+ this->startCoord = new u32[num];
+ this->length = new u32[num];
+ this->inversed = new bool[num];
+ this->metaDataFlags = new u64[num];
+ this->total_length = 0;
+
+ // Initialize the startCoord, length, and inversed
+ s32 global_frag_index = 0;
+ for (s32 i = 0; i < num; i++)
+ {
+ frag_id[i] = selected_frag_ids_tmp[i];
+ inversed[i] = false;
+ length[i] = Contigs->contigs_arr[frag_id[i]].length;
+ total_length += length[i];
+ metaDataFlags[i] = (Contigs->contigs_arr[frag_id[i]].metaDataFlags == nullptr)?0:*(Contigs->contigs_arr[frag_id[i]].metaDataFlags);
+ while (global_frag_index < frag_id[i])
+ {
+ if (global_frag_index >= Contigs->numberOfContigs)
+ {
+ fmt::print(
+ stderr,
+ "The frag_id[0]({}) should be less than the number_of_contigs({}), file:{}, line:{}\n",
+ frag_id[0], Contigs->numberOfContigs, __FILE__, __LINE__);
+ assert(0);
+ }
+ startCoord[i] += Contigs->contigs_arr[global_frag_index++].length;
+ }
+ }
+ }
+
+
+private:
+ void cleanup()
+ {
+ if (frag_id)
+ {
+ delete[] frag_id;
+ frag_id = nullptr;
+ }
+
+ if (startCoord)
+ {
+ delete[] startCoord;
+ startCoord = nullptr;
+ }
+ if (length)
+ {
+ delete[] length;
+ length = nullptr;
+ }
+ if (inversed)
+ {
+ delete[] inversed;
+ inversed = nullptr;
+ }
+ if (metaDataFlags)
+ {
+ delete[] metaDataFlags;
+ metaDataFlags = nullptr;
+ }
+ total_length = 0;
+ num = 0;
+ }
+};
+
+#endif // FRAG4COMPRESS_H
\ No newline at end of file
diff --git a/src/frag_sort.cpp b/src/frag_sort.cpp
index b158388..8c385e5 100644
--- a/src/frag_sort.cpp
+++ b/src/frag_sort.cpp
@@ -436,7 +436,8 @@ void FragSortTool::sort_according_likelihood_unionFind(
SelectArea& select_area,
const f32 threshold,
const Frag4compress* frags,
- bool sort_according_len_flag) const
+ const bool sort_according_len_flag
+) const
{
// this is used to fix the source and sink during local sort
s32 source_frag_id = -1, source_chain_id = -1,
@@ -672,6 +673,12 @@ void FragSortTool::sort_according_likelihood_unionFind_doFuse(
// 计算的分位数
f32 threshold_val = percentile_cal(likelihood_table.data, likelihood_table.size, this->threshold_ratio);
+ if (threshold_val < 0)
+ {
+ fmt::print(stderr, "[Pixel Sort::error]: threshold at {}: {}, fixed_threshold: {}, using: {}, table.size={} \n", this->threshold_ratio, threshold_val, threshold, threshold_val, likelihood_table.size);
+ assert(0);
+ threshold_val = 0;
+ }
f32 threshold_using = std::min(threshold_val, threshold);
fmt::print(stderr, "[Pixel Sort]: link score threshold at {}: {}, fixed_threshold: {}, using: {}\n", this->threshold_ratio, threshold_val, threshold, threshold_using);
diff --git a/src/frag_sort.h b/src/frag_sort.h
index 9400d79..969f5b2 100644
--- a/src/frag_sort.h
+++ b/src/frag_sort.h
@@ -74,7 +74,7 @@ class FragSortTool
SelectArea& select_area,
const f32 threshold=-0.001,
const Frag4compress* frags=nullptr,
- bool sort_according_len_flag=true) const;
+ const bool sort_according_len_flag=true) const;
void sort_according_likelihood_unionFind_doFuse(
const LikelihoodTable& likelihood_table,
@@ -84,7 +84,7 @@ class FragSortTool
const Frag4compress* frags=nullptr,
const bool doStageOne=true,
const bool doStageTwo=false,
- bool sort_according_len_flag=true) const;
+ const bool sort_according_len_flag=true) const;
void sort_according_yahs(
const LikelihoodTable& likelihood_table,
@@ -92,6 +92,61 @@ class FragSortTool
SelectArea& select_area,
const f32 threshold=-0.001,
const Frag4compress* frags=nullptr) const;
+
+
+ void sort_method_mask(
+ const LikelihoodTable& likelihood_table,
+ FragsOrder& frags_order,
+ SelectArea& selected_area,
+ const AutoCurationState& auto_curation_state,
+ const Frag4compress* frags=nullptr,
+ const bool sort_according_len_flag=true
+ ) const
+ {
+ if (auto_curation_state.sort_mode == 0 || !selected_area.select_flag) // sort with union find if sorting the whole genome
+ {
+ this->sort_according_likelihood_unionFind(
+ likelihood_table,
+ frags_order,
+ selected_area,
+ auto_curation_state.link_score_threshold,
+ frags);
+ }
+ else if (auto_curation_state.sort_mode == 1)
+ {
+ this->sort_according_likelihood_unionFind_doFuse(
+ likelihood_table,
+ frags_order,
+ selected_area,
+ auto_curation_state.link_score_threshold,
+ frags, true, true);
+ }
+ else if (auto_curation_state.sort_mode == 2)
+ {
+ this->sort_according_likelihood_unionFind_doFuse(
+ likelihood_table,
+ frags_order,
+ selected_area,
+ auto_curation_state.link_score_threshold,
+ frags, false, true);
+ }
+ else if (auto_curation_state.sort_mode == 3) // not finished yet
+ {
+ this->sort_according_yahs(
+ likelihood_table,
+ frags_order,
+ selected_area,
+ auto_curation_state.link_score_threshold,
+ frags
+ );
+ }
+ else
+ {
+ fprintf(stderr, "[Pixel Sort] Error: Unknown sort mode (%d)\n", auto_curation_state.sort_mode);
+ assert(0);
+ }
+ }
+
};
diff --git a/src/frags_order.h b/src/frags_order.h
index ceaf93e..f49d231 100644
--- a/src/frags_order.h
+++ b/src/frags_order.h
@@ -8,37 +8,53 @@ struct FragsOrder
{
private:
u32 num_frags; // number of all the fragments
- u32 num_chromosomes;
- u32* num_frags_in_chromosomes = nullptr; // [num_chromosomes]
- s32** order = nullptr; // [num_chromosomes, num_frags_in_chromosomes], + - represents the direction of the fragment, start from 1
+ std::vector> order; // [num_chromosomes, num_frags_in_chromosomes], + - represents the direction of the fragment, start from 1
void cleanup()
{
- if (order)
- {
- for (u32 i = 0; i < num_chromosomes; i++)
+ num_frags = 0;
+ if (order.size() > 0)
+ {
+ for (u32 i = 0; i < order.size(); i++)
{
- if (order[i])
- {
- delete[] order[i];
- order[i] = nullptr;
- }
+ if (order[i].size() > 0) order[i].clear();
}
- delete[] order;
- order = nullptr;
- }
-
- if (num_frags_in_chromosomes)
- {
- delete[] num_frags_in_chromosomes;
- num_frags_in_chromosomes = nullptr;
+ order.clear();
}
- num_chromosomes = 0;
}
public:
FragsOrder(u32 num_frags_)
- :num_frags(num_frags_), num_chromosomes(0), num_frags_in_chromosomes(nullptr), order(nullptr)
- {}
+ {
+ cleanup();
+ num_frags = num_frags_;
+ order.push_back(std::vector(num_frags));
+ for (s32 i = 0; i < num_frags; i++) order[0][i] = i + 1;
+ return ;
+ }
+
+ FragsOrder(std::vector order) // order start from 1, +/- represents the direction of the fragment
+ {
+ cleanup();
+ num_frags = order.size();
+ this->order.push_back(std::vector(num_frags));
+ for (s32 i = 0; i < num_frags; i++) this->order[0][i] = order[i];
+ return ;
+ }
+
+ FragsOrder( // merge to build new fragsOrder
+ const std::vector& frags_order_list,
+ const std::vector>& clusters)
+ {
+ cleanup();
+ for (u32 i = 0; i < frags_order_list.size(); i++) // 遍历所有的cluster
+ {
+ this->num_frags += clusters[i].size();
+ auto tmp_order = frags_order_list[i].get_order_without_chromosomeInfor();
+ for (auto& tmp:tmp_order)
+ tmp = (clusters[i][std::abs(tmp)-1] + 1) * (tmp>0?1:-1);
+ this->order.push_back(std::move(tmp_order));
+ }
+ }
~FragsOrder()
{
@@ -47,71 +63,48 @@ struct FragsOrder
u32 get_num_frags() const {return num_frags;}
- void set_order(const std::vector> chromosomes)
+ void set_order(const std::vector>& chromosomes)
{
cleanup(); // make sure the memory is released
- u32 tmp = 0;
for (auto chromosome : chromosomes)
{
- if (chromosome.size()!=0) tmp += 1;
+ if (chromosome.size()==0) continue;
+ num_frags += chromosome.size();
+ order.emplace_back(chromosome.begin(), chromosome.end());
}
- num_chromosomes = tmp;
- num_frags_in_chromosomes = new u32[num_chromosomes];
- order = new s32*[num_chromosomes];
- u32 cnt= 0;
- for (u32 i = 0; i < chromosomes.size(); i++)
- {
- if (chromosomes[i].size() == 0) continue;
- num_frags_in_chromosomes[cnt] = chromosomes[i].size();
- order[cnt] = new s32[num_frags_in_chromosomes[cnt]];
- for (u32 j = 0; j < num_frags_in_chromosomes[cnt]; j++)
- {
- order[cnt][j] = chromosomes[i][j];
- if (order[cnt][j] == 0)
- {
- std::cerr << "Error: the order should not contain ("<< order[cnt][j] << ")." << std::endl;
- assert(0);
- }
- }
- cnt++ ;
- }
- if (cnt != num_chromosomes)
+ }
+
+ std::vector get_order_without_chromosomeInfor() const
+ {
+ if (num_frags == 0)
{
- fprintf(stderr, "The cnt(%d) != num_chromosomes(%d)\n", cnt, num_chromosomes);
+ std::cerr << "Error: the order is not set yet" << std::endl;
assert(0);
}
+ std::vector output;
+ for (auto& chromorsome:order) for (auto& frag: chromorsome) output.push_back(frag);
+ return output;
}
- std::vector get_order_without_chromosomeInfor() const
+ void print_order() const
{
- if (num_chromosomes == 0)
+ if (num_frags == 0)
{
std::cerr << "Error: the order is not set yet" << std::endl;
assert(0);
}
- std::vector output;
- for (u32 i = 0; i < num_chromosomes; i++)
+ std::cout << "[Pixel Sort::print_order] Sorting results \n";
+ for (u32 i = 0; i < order.size(); i++)
{
- for (u32 j = 0; j < num_frags_in_chromosomes[i]; j++)
+ std::cout << "\tChr [" << i+1 << "]: ";
+ for (u32 j = 0; j < order[i].size(); j++)
{
- output.push_back(order[i][j]);
+ std::cout << order[i][j] << " ";
}
+ std::cout << std::endl;
}
-
- #ifdef DEBUG // echo the results
- std::cout << "\n\nSorting results \n";
- for (u32 i = 0; i < num_chromosomes; i++)
- {
- std::cout << "Chr [" << i+1 << "]: ";
- for (u32 j = 0; j < num_frags_in_chromosomes[i]; j++)
- {
- std::cout << order[i][j] << " ";
- }
- std::cout << std::endl;
- }
- #endif //DEBUG
-
- return output;
+ std::cout << std::endl;
+ return ;
}
};
diff --git a/src/genomeData.h b/src/genomeData.h
index 7453bd4..a0e09b6 100644
--- a/src/genomeData.h
+++ b/src/genomeData.h
@@ -28,8 +28,8 @@ SOFTWARE.
#include "utilsPretextView.h"
#include "showWindowData.h"
-
-#define Max_Number_of_Contigs 4096
+// NOTE: if the number exceed this value, the contig counted as N % 16384, for example, contig 16384 will be counted as 0, 16385 1, 16386 as 2
+#define Max_Number_of_Contigs 16384 // 16384 // originally 4096
struct
file_atlas_entry
@@ -54,8 +54,7 @@ struct contact_matrix
};
-// one original contig
-// which may be split into multiple fragments
+// one original contig may be split into multiple fragments
struct original_contig
{
u32 name[16]; // contig name
@@ -130,6 +129,49 @@ struct map_state
originalContigIds[i] = originalContigIds[i] % Max_Number_of_Contigs;
}
}
+
+
+ map_state(int num_pixel_1d)
+ {
+ contigIds = new u32[num_pixel_1d];
+ originalContigIds = new u32[num_pixel_1d];
+ contigRelCoords = new u32[num_pixel_1d];
+ scaffIds = new u32[num_pixel_1d];
+ metaDataFlags = new u64[num_pixel_1d];
+ memset(contigIds, 0, num_pixel_1d * sizeof(u32));
+ memset(originalContigIds, 0, num_pixel_1d * sizeof(u32));
+ memset(contigRelCoords, 0, num_pixel_1d * sizeof(u32));
+ memset(scaffIds, 0, num_pixel_1d * sizeof(u32));
+ memset(metaDataFlags, 0, num_pixel_1d * sizeof(u64));
+ }
+ ~map_state()
+ {
+ if (contigIds)
+ {
+ delete[] contigIds;
+ contigIds = nullptr;
+ }
+ if (originalContigIds)
+ {
+ delete[] originalContigIds;
+ originalContigIds = nullptr;
+ }
+ if (contigRelCoords)
+ {
+ delete[] contigRelCoords;
+ contigRelCoords = nullptr;
+ }
+ if (scaffIds)
+ {
+ delete[] scaffIds;
+ scaffIds = nullptr;
+ }
+ if (metaDataFlags)
+ {
+ delete[] metaDataFlags;
+ metaDataFlags = nullptr;
+ }
+ }
};
@@ -229,6 +271,48 @@ extension_sentinel
}
return false;
}
+
+ /*
+ get the id of extension whose name including the tmp name
+ return: -1 if not found
+ id of the extension if found (return the first found id if multiple found)
+ */
+ s32 get_graph_id(const std::string name)
+ {
+ s32 id = 0;
+ TraverseLinkedList(this->head, extension_node)
+ {
+ if (node->type == extension_graph)
+ {
+ if (std::string((char*)((graph*)node->extension)->name).find(name) != std::string::npos)
+ {
+ fmt::println("[extension_sentinel] Found the Extension name: {}, id: {}", (char*)((graph*)node->extension)->name, id);
+ return id;
+ }
+ }
+ id++;
+ }
+ fmt::println("[extension_sentinel] Not found the Extension name: {}", name);
+ return -1;
+ }
+
+ const u32* get_graph_data_ptr(const std::string name)
+ {
+ s32 id = get_graph_id(name);
+ if (id < 0 ) return nullptr;
+ extension_node* node = this->head;
+ while ( id-- > 0 )
+ {
+ if (node && node->next) node = node->next;
+ else
+ {
+ fmt::println("[Pixel Cut::error]: The graph id is out of range");
+ assert(0);
+ }
+ }
+ return ((graph*)(node->extension))->data;
+ }
+
};
diff --git a/src/grey_out_settings.h b/src/grey_out_settings.h
index 4098ce7..8945a9f 100644
--- a/src/grey_out_settings.h
+++ b/src/grey_out_settings.h
@@ -11,6 +11,11 @@ struct GreyOutSettings
s32 n_flags = 64;
s32 grey_out_flags[64];
std::unordered_set default_grey_out_tag = {"FalseDuplicate", "Primary"};
+ std::unordered_set paint_tags = {
+ "vertPaint", // paint vertically
+ "horzPaint", // paint horizontally
+ "crossPaint", // paint with cross
+ };
GreyOutSettings()
{
@@ -61,6 +66,24 @@ struct GreyOutSettings
}
return "";
}
+
+ /* return:
+ 0: no grey out
+ 1: vertical grey out
+ 2: horizontal grey out
+ 3: corss grey out
+ */
+ u32 is_vert_horiz_grey_out(u64* meta_data_flags, meta_data* Meta_Data){
+ for (s32 i = 0; i < ArrayCount(Meta_Data->tags) ; i ++ ) {
+ if ((*meta_data_flags & ((u64)1 << i)) ){
+ if ( std::string((char*) Meta_Data->tags[i])=="vertPaint") return 1;
+ else if ( std::string((char*) Meta_Data->tags[i])=="horzPaint") return 2;
+ else if ( std::string((char*) Meta_Data->tags[i]) == "crossPaint") return 3;
+ }
+ }
+ return 0;
+ }
+
};
diff --git a/src/hic_figure.h b/src/hic_figure.h
index de1dd68..fa303a3 100644
--- a/src/hic_figure.h
+++ b/src/hic_figure.h
@@ -20,6 +20,7 @@
#include "utilsPretextView.h"
#include "copy_texture.h"
+
#ifndef STB_IMAGE_RESIZE_IMPLEMENTATION
#define STB_IMAGE_RESIZE_IMPLEMENTATION
#include "stb_image_resize.h"
diff --git a/src/kmeans_pybind.h b/src/kmeans_pybind.h
new file mode 100644
index 0000000..243249e
--- /dev/null
+++ b/src/kmeans_pybind.h
@@ -0,0 +1,124 @@
+#include
+#include
+#include
+#include
+#include
+#include "fmt/core.h"
+#include "likelihood_table.h"
+
+namespace py = pybind11;
+
+
+template
+py::array_t create_tensor(const int n, const int channel, const T* data_ptr) {
+ // 总元素个数
+ s32 total_size = n * n * channel;
+
+ // 指定 shape 和 strides
+ std::vector shape = {n, n, channel};
+ std::vector strides = {
+ static_cast(n * channel * sizeof(T)), // 跨 n 行
+ static_cast(channel * sizeof(T)), // 跨 n 列
+ static_cast(sizeof(T)) // 跨特征维
+ };
+
+ return py::array_t(shape, strides, data_ptr);
+}
+
+
+
+class KmeansClusters
+{
+ public:
+ bool is_init = false;
+ py::module kmeans_utils;
+ KmeansClusters()
+ {
+ try
+ {
+ // 将当前目录加入 Python 模块搜索路径
+ py::module sys = py::module::import("sys");
+ py::module os = py::module::import("os");
+ #ifdef DEBUG
+ sys.attr("path").attr("append")("./build_cmake");
+ #else // NDEBUG
+ #ifdef __APPLE__
+ sys.attr("path").attr("append")("./PretextViewAI.app/Contents/Resources");
+ #elif defined(__linux__)
+ sys.attr("path").attr("append")(".");
+ #else // _WIN32 _WIN64
+ sys.attr("path").attr("append")(".");
+ #endif
+ #endif // DEBUG
+ std::string current_dir = os.attr("getcwd")().cast();
+ fmt::print("Current dir: {}\n", current_dir);
+
+ fmt::print("PythonPaths: ");
+ auto python_paths = sys.attr("path");
+ for (auto& path : python_paths)
+ {
+ fmt::print("\t{}\n", path.cast());
+ }
+
+ // 导入 Python 模块
+ kmeans_utils = py::module::import("kmeans_utils");
+ fmt::print("Python kmeans module loaded successfully\n");
+ is_init = true;
+ }
+ catch(const std::exception& e)
+ {
+ std::cerr << e.what() << '\n';
+ }
+
+ }
+
+
+ void print_clusters(const std::vector>& clusters) const
+ {
+ for (int i = 0; i < clusters.size(); ++i)
+ {
+ if (clusters[i].empty()) continue;
+ fmt::print("cluster id: {}, size: {}, frags: \t", i, clusters[i].size());
+ for (auto& frag_id : clusters[i])
+ {
+ fmt::print("{}, ", frag_id);
+ }
+ fmt::print("\n");
+ }
+ }
+
+
+ std::vector> kmeans_func(const int k, const Matrix3D* mat3d=nullptr)
+ {
+ if (!is_init)
+ {
+ std::cerr << "Error: KmeansClusters not initialized" << std::endl;
+ assert(0);
+ }
+ py::array_t labels ;
+
+ // cal py function to get cluster labels
+ py::array_t adj_matrix = create_tensor(mat3d->row_num, mat3d->layer_num, mat3d->get_data_ptr());
+ labels = kmeans_utils.attr("run_kmeans")(k, adj_matrix);
+
+ // 解析 NumPy 数组结果
+ py::buffer_info buf = labels.request();
+ int* cluster_ids = static_cast(buf.ptr);
+ std::vector> clusters(k);
+ for (int i = 0; i < buf.size; ++i)
+ {
+ if (cluster_ids[i] < 0 || cluster_ids[i] >= k)
+ {
+ fmt::println(stderr, "Error: cluster id out of range");
+ assert(0);
+ }
+ clusters[cluster_ids[i]].push_back(i);
+ }
+ #ifdef DEBUG
+ this->print_clusters(clusters);
+ #endif // DEBUG
+ return clusters;
+ }
+
+
+};
\ No newline at end of file
diff --git a/src/likelihood_table.h b/src/likelihood_table.h
index 20d1713..fc9a9f8 100644
--- a/src/likelihood_table.h
+++ b/src/likelihood_table.h
@@ -19,11 +19,20 @@ struct LikelihoodTable
const Matrix3D* compressed_hic,
const f32 threshold=10.f/32769.f,
const std::vector& exclude_tag_idx=std::vector(),
- const u32 num_pixels_1d=32768)
- :num_frags(frags->num), frags(frags), data(nullptr)
+ const u32 num_pixels_1d=32768,
+ const std::vector* selected_frags_id=nullptr)
+ :num_frags(frags->num), frags(frags)
{
+ frags = frags;
+ num_frags = frags->num;
+ if (selected_frags_id && frags->num != selected_frags_id->size())
+ {
+ fmt::print(stderr, "Error: frags->num({}) != selected_frags_id.size({})\n", frags->num, selected_frags_id->size());
+ assert(0);
+ }
+
auto is_exclude_tag = [&](u32 idx) -> bool
- {
+ {
if ((f32)frags->length[idx]/(f32)num_pixels_1d <= threshold)
{
this->excluded_fragment_idx.insert(idx);
@@ -44,18 +53,29 @@ struct LikelihoodTable
size = num_frags * num_frags * 4;
data = new f32[size];
for (u32 i = 0; i frags->num / 2 )
+ {
+ fmt::print(stderr, "[LikelihoodTable::warning]: too many excluded fragments: {} / {}\n", excluded_fragment_idx.size(), frags->num);
+ }
+
+ return ;
}
~LikelihoodTable()
@@ -104,12 +124,11 @@ struct LikelihoodTable
{
fmt::print(
ofs,
- "{}\t{}\t{}\t{}\t{}\n",
+ "{}\t{}\t{}\t{}\n",
i,
frags->length[i],
0,
- 0,
- 0);
+ 0 );
}
fmt::print(ofs, "\n");
diff --git a/src/parse_agp.h b/src/parse_agp.h
new file mode 100644
index 0000000..50a082c
--- /dev/null
+++ b/src/parse_agp.h
@@ -0,0 +1,375 @@
+
+
+#ifndef parse_agp_h
+#define parse_agp_h
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "genomeData.h"
+
+
+
+struct Date
+{
+ int year;
+ int month;
+ int day;
+ int hour;
+ int minute;
+ int second;
+ Date()
+ : year(-1), month(-1), day(-1), hour(-1), minute(-1), second(-1) {}
+
+ Date(int y, int m, int d, int h, int min, int s)
+ : year(y), month(m), day(d), hour(h), minute(min), second(s) {}
+
+ Date(int y, int m, int d)
+ : year(y), month(m), day(d), hour(-1), minute(-1), second(-1) {}
+
+ Date(const Date& other)
+ : year(other.year), month(other.month), day(other.day),
+ hour(other.hour), minute(other.minute), second(other.second) {}
+
+ std::string to_string() const
+ {
+ if (second>=0 && minute>=0 && hour>=0)
+ return fmt::format("{:04d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}", year, month, day, hour, minute, second);
+ else if (year>=0 && month>=0 && day>=0)
+ return fmt::format("{:04d}-{:02d}-{:02d}", year, month, day);
+ else if (year>=0 && month>=0)
+ return fmt::format("{:04d}-{:02d}", year, month);
+ else if (year>=0)
+ return fmt::format("{:04d}", year);
+ else return "Unknown Date";
+ }
+};
+
+
+struct Original_Contig_agp
+{
+ int len; // len in bp
+ int num_frags;
+ std::vector starts; // record the start position of each fragment
+
+ Original_Contig_agp()
+ : len(0), num_frags(0) {}
+ Original_Contig_agp(int l, int n) : len(l), num_frags(n) {}
+
+};
+
+struct Scaff_agp
+{
+ int len; // len in bp
+ bool is_painted;
+ Scaff_agp( bool p)
+ : len(0), is_painted(p) {}
+};
+
+
+struct Frag
+{
+ const int orig_contig_id; // start from 0
+ const int scaff_id; // start from 0
+ const int start; // start position (bp) in the original contig
+ const int len; // len in bp
+ int local_index = -1; // index within orignal contig
+ const bool is_reverse;
+ const bool is_painted ;
+ const uint64_t meta_data_flag = 0;
+ Frag(const int oci, const int si, int s, int l, bool r, bool p, const uint64_t& m)
+ : orig_contig_id(oci), scaff_id(si), start(s), len(l), is_reverse(r), is_painted(p), meta_data_flag(m) {}
+};
+
+
+int get_scaff_id(const std::string& scaff_name)
+{
+ std::smatch match;
+ if (!std::regex_search(scaff_name, match, std::regex("^\\w+_(\\d+)$")))
+ {
+ fmt::print(stderr, "Error: scaff name {} not match ^\\w+_(\\d+)$ \n", scaff_name);
+ assert(0);
+ }
+ return std::stoi(match[1].str()) - 1;
+}
+
+
+class AssemblyAGP
+{
+public:
+ std::string sample_name;
+ std::string agp_version;
+ std::string description;
+ Date date;
+ double bp_per_pixel;
+
+ std::vector frags;
+ std::unordered_map original_contigs;
+ std::vector scaffs;
+ int total_bp = 0;
+
+
+ int get_num_painted_scaff() const
+ {
+ int num = 0;
+ for (const auto& scaff : scaffs)
+ {
+ if (scaff.is_painted) num++;
+ }
+ return num;
+ }
+
+ void add_frag(
+ const original_contig* Original_Contigs, const int& num_original_contigs,
+ const std::string& scaff_name,
+ const std::string& original_contig_name,
+ const int& start_local, const int& end_local,
+ bool is_reverse,
+ bool is_painted,
+ const uint64_t& meta_tags )
+ {
+ int original_contig_id = this->get_original_contig_id(Original_Contigs, num_original_contigs, original_contig_name);
+ if (original_contig_id < 0)
+ throw std::runtime_error(fmt::format("Error: original contig name {} not found in Original_Contigs. file: {}, line: {}\n", original_contig_name, __FILE__, __LINE__));
+ int scaff_id = get_scaff_id(scaff_name); // start from 0
+
+ if (this->original_contigs.find(original_contig_name) == this->original_contigs.end())
+ this->original_contigs[original_contig_name] = Original_Contig_agp(end_local, 1);
+ else {
+ this->original_contigs[original_contig_name].num_frags++;
+ this->original_contigs[original_contig_name].len = std::max(this->original_contigs[original_contig_name].len, end_local);
+ }
+ this->original_contigs[original_contig_name].starts.push_back(start_local);
+ this->frags.emplace_back(original_contig_id, scaff_id, start_local, std::abs(end_local- start_local) + 1, is_reverse, is_painted, meta_tags);
+
+ if (this->scaffs.size() <= frags.back().scaff_id)
+ this->scaffs.emplace_back(is_painted);
+
+ this->scaffs[this->frags.back().scaff_id].len += this->frags.back().len;
+ this->total_bp += this->frags.back().len;
+ }
+
+ /*
+ restore the assembly from the
+ - UN-CORRECTED .agp file
+ */
+ AssemblyAGP(
+ const std::string& agp_file,
+ const original_contig* Original_Contigs,
+ const int& num_original_contigs,
+ meta_data* Meta_Data // used to restore the meta data tag
+ )
+ {
+ std::ifstream file(agp_file);
+ if (!file.is_open())
+ {
+ fmt::print(stderr, "Failed to open AGP file: {}\n", agp_file);
+ return;
+ }
+
+ sample_name = agp_file.substr(agp_file.find_last_of("/\\") + 1);
+ sample_name = sample_name.substr(0, sample_name.find('.'));
+
+ std::string line;
+ while (std::getline(file, line))
+ {
+ std::smatch match;
+ if (line.empty() ) continue; // Skip empty lines and comments
+ else if (std::regex_search(line, match, std::regex("^##agp-version\\s*(\\d+.\\d+)\\s*$"))) // version
+ {
+ this->agp_version = match[1].str();
+ }
+ else if (std::regex_search(line, match, std::regex("^# DESCRIPTION:\\s*(.*)$"))) // descirption
+ {
+ this->description = match[1].str();
+ } else if (std::regex_search(line, match, std::regex("^# HiC MAP RESOLUTION:\\s*(\\d+.\\d*)\\s+bp/texel\\s*$")))
+ {
+ this->bp_per_pixel = std::stod(match[1].str());
+ } else if (std::regex_search(line, match, std::regex("^([\\w_]+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\w+)\\s+([\\w_]+)\\s+(\\d+)\\s+(\\d+)\\s+([+-])\\s*([Painted]*)\\s*(.*)$"))) // genome line
+ {
+ std::string scaff_name = match[1].str();
+ int scaff_start = std::stoi(match[2].str());
+ int scaff_end = std::stoi(match[3].str());
+ int scaff_frag_id = std::stoi(match[4].str());
+ bool is_gap = match[5].str() == "U";
+ std::string original_contig_name = match[6].str();
+ int start_local = std::stoi(match[7].str());
+ int end_local = std::stoi(match[8].str());
+ bool is_reverse = match[9].str() == "-";
+ bool is_painted = match[10].str() == "Painted";
+ uint64_t meta_tags = parse_tags(match[11].str(), Meta_Data);
+
+ this->add_frag(
+ Original_Contigs, num_original_contigs,
+ scaff_name, original_contig_name,
+ start_local, end_local,
+ is_reverse, is_painted, meta_tags
+ );
+ } else if (std::regex_search(line, match, std::regex("^([\\w_]+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\w+)\\s+(\\d+)\\s+([\\w_]+)\\s+(\\w+)\\s+([\\w_]+)(.+)$"))) // gap line
+ {
+ std::string scaff_name = match[1].str();
+ int scaff_start = std::stoi(match[2].str());
+ int scaff_end = std::stoi(match[3].str());
+ int scaff_frag_id = std::stoi(match[4].str());
+ bool is_gap = match[5].str() == "U";
+ int gap_length = std::stoi(match[6].str());
+ }
+ }
+ file.close();
+ this->sort_frags_local_index(Original_Contigs);
+ }
+
+ uint64_t parse_tags(const std::string tags_str, meta_data* Meta_Data)
+ {
+ if (tags_str.empty()) return 0;
+ uint64_t tags_u64 = 0;
+ std::istringstream iss(tags_str);
+ std::string tag;
+
+ // 使用流操作符按空格分割字符串
+ while (iss >> tag)
+ {
+ for (int i = 0 ; i<64 ; i ++ )
+ {
+ if (std::string((char*)Meta_Data->tags[i]).empty())
+ {
+ memcpy(Meta_Data->tags[i], tag.data(), tag.size() + 1);
+ tags_u64 |= (1ULL << i);
+ break;
+ }
+ else if (tag == std::string((char*)(Meta_Data->tags[i])))
+ {
+ tags_u64 |= (1ULL << i);
+ break;
+ }
+ }
+ }
+ return tags_u64;
+ }
+
+ /* validate the number of base pairs */
+ int cal_total_bp()
+ {
+ int total = 0;
+ for (const auto& frag : frags)
+ {
+ total += frag.len;
+ }
+
+ int total_bp_scaff = 0;
+ for (const auto& scaff : scaffs)
+ total_bp_scaff += scaff.len;
+ if (total != total_bp_scaff)
+ {
+ fmt::print(stderr, "Warning: total bp in frags ({}) != total bp in scaffs ({})\n", total, total_bp_scaff);
+ assert(total == total_bp_scaff);
+ return -1;
+ }
+ return total;
+ }
+
+ /*
+ restore the map_state from the assembly
+ - UN-CORRECTED .agp file
+ return: 0 if success, -1 if failed
+ */
+ int restore_map_state_from_agp(
+ const int& num_pix_1d,
+ map_state* Map_State,
+ const original_contig* Original_Contigs,
+ const int& num_original_contigs
+ )
+ {
+ int pixel_index;
+ double start_pixel_global = 0, len_pixel = 0, local_start_pixel;
+ for ( int i = 0 ; i < this->frags.size() ; i++ )
+ {
+ const Frag& frag = frags[i];
+ local_start_pixel = (double) frag.start / this->bp_per_pixel;
+ len_pixel = (double) frag.len / this->bp_per_pixel;
+ for (int j = 0; j < std::round(len_pixel); j ++ )
+ {
+ pixel_index = std::round(start_pixel_global) + j;
+ if ( pixel_index >= num_pix_1d )
+ {
+ fmt::print(stderr, "Warning: pixel index ({:.2f}) out of range [0, {}).\n", pixel_index, num_pix_1d);
+ assert(0);
+ return -1;
+ }
+ Map_State->contigIds[pixel_index] = i;
+ Map_State->originalContigIds[pixel_index] = frag.orig_contig_id;
+ Map_State->contigRelCoords[pixel_index] = frag.is_reverse ?
+ std::round(local_start_pixel + len_pixel) - j - 1:
+ std::round(local_start_pixel) + j;
+ Map_State->scaffIds[pixel_index] = frag.scaff_id;
+ pixel_index++;
+ }
+ start_pixel_global += len_pixel;
+ }
+ #ifdef DEBUG
+ int n = 2000;
+ fmt::print("[Load AGP::restore_map_state_from_agp]: Relative coordinates of the first {} pixels:\n", n);
+ for (int i = 0; i < n ; i++)
+ {
+ fmt::print("{}:{} ", Map_State->originalContigIds[i], Map_State->contigRelCoords[i]);
+ if (i % 40 == 39) fmt::print("\n");
+ }
+ fmt::print("\n");
+
+ #endif // DEBUG
+
+
+ return 0;
+ }
+
+ int get_original_contig_id(
+ const original_contig* Original_Contigs, const int& num_original_contigs, const std::string& name)
+ {
+ for (int i = 0; i < num_original_contigs; i++)
+ {
+ if (strcmp((char*)(Original_Contigs+i)->name, name.c_str()) == 0)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ std::string __str__() const
+ {
+ std::string
+ str = fmt::format("Sample name: {}\n", sample_name);
+ str += fmt::format("AGP Version: {}\n", agp_version);
+ str += fmt::format("Description: {}\n", description);
+ str += fmt::format("Date: {}\n", date.to_string());
+ str += fmt::format("BP per pixel: {}\n", bp_per_pixel);
+ str += fmt::format("Total BP: {}\n", total_bp);
+ return str;
+ }
+
+ void sort_frags_local_index(const original_contig* Original_Contigs)
+ {
+ for (auto& it:this->original_contigs) std::sort(it.second.starts.begin(), it.second.starts.end());
+ int tmp_index = 0 ;
+ for (int i = 0 ; i < frags.size(); i++)
+ {
+ std::string original_contig_name = std::string((char*)Original_Contigs[frags[i].orig_contig_id].name);
+ while (tmp_index < this->original_contigs[original_contig_name].starts.size() &&
+ this->frags[i].start != this->original_contigs[original_contig_name].starts[tmp_index]) tmp_index++;
+ if (tmp_index >= this->original_contigs[original_contig_name].starts.size())
+ {
+ throw std::runtime_error(fmt::format("Error: original contig name {} not found in Original_Contigs. file: {}, line: {}\n", original_contig_name, __FILE__, __LINE__));
+ }
+ this->frags[i].local_index = tmp_index;
+ tmp_index = 0;
+ }
+ }
+};
+
+#endif // parse_agp_h
+
+
diff --git a/src/self_matrix.h b/src/self_matrix.h
new file mode 100644
index 0000000..0b0db1c
--- /dev/null
+++ b/src/self_matrix.h
@@ -0,0 +1,168 @@
+#ifndef SELF_MATRIX_H
+#define SELF_MATRIX_H
+
+
+template
+class Matrix2D
+{
+private:
+ T* data = nullptr;
+public:
+ u32 row_num, col_num, length;
+ u32 shape[2];
+ Matrix2D(u32 row_num_, u32 col_num_)
+ : row_num(row_num_), col_num(col_num_)
+ {
+ shape[0] = row_num_;
+ shape[1] = col_num_;
+ if (row_num_ <= 0 || col_num_ <= 0)
+ {
+ fprintf(stderr, "The row_num(%d), col_num(%d) should be larger than 0\n", row_num_, col_num_);
+ assert(0);
+ }
+ length = row_num * col_num;
+ data = new T[length];
+ memset(data, 0, length * sizeof(T));
+ }
+
+ ~Matrix2D()
+ {
+ if (data)
+ {
+ delete[] data;
+ data = nullptr;
+ }
+ }
+
+ void check_indexing(const u32& row, const u32& col) const
+ {
+ if (row >= row_num || col>= col_num)
+ {
+ fprintf(stderr, "Index [%d, %d] is out of the maximum [%d, %d]\n", row, col, row_num-1, col_num-1);
+ assert(0);
+ }
+ return ;
+ }
+
+ // Access operator
+ T& operator()(const u32& row, const u32& col)
+ {
+ check_indexing(row, col);
+ return data[row * col_num + col];
+ }
+
+ const T& operator()(const u32& row, const u32& col) const
+ {
+ check_indexing(row, col);
+ return data[row * col_num + col];
+ }
+
+ T* get_data_ptr() const
+ {
+ return data;
+ }
+
+};
+
+
+
+template
+class Matrix3D
+{
+private:
+ T* data = nullptr;
+public:
+ u32 row_num, col_num, layer_num, length;
+ u32 shape[3];
+ Matrix3D(
+ u32 row_num_,
+ u32 col_num_,
+ u32 layer_)
+ {
+ MY_CHECK(0);
+ re_allocate_mem(row_num_, col_num_, layer_);
+ }
+
+ ~Matrix3D()
+ {
+ cleanup();
+ }
+
+ void cleanup()
+ {
+
+ if (data)
+ {
+ delete[] data;
+ data = nullptr;
+ }
+ }
+
+ void re_allocate_mem(u32 row_num_, u32 col_num_, u32 layer_)
+ {
+ cleanup();
+ row_num = row_num_;
+ col_num = col_num_;
+ layer_num = layer_;
+ shape[0] = row_num_;
+ shape[1] = col_num_;
+ shape[2] = layer_;
+ length = row_num * col_num * layer_num;
+
+ data = new T[length];
+
+ memset(data, 0, length * sizeof(T));
+ }
+
+ void check_indexing(const u32& row, const u32& col, const u32& layer) const
+ {
+ if (row >= row_num || col>= col_num || layer >= layer_num)
+ {
+ fprintf(stderr, "Index [%d, %d, %d] is out of the maximum [%d, %d, %d]\n", row, col, layer, row_num-1, col_num-1, layer_num-1);
+ assert(0);
+ }
+ return ;
+ }
+
+ // Access operator
+ T& operator()(const u32& row, const u32& col, const u32& layer) {
+ check_indexing(row, col, layer);
+ return data[row * col_num * layer_num + col * layer_num + layer];
+ }
+
+ const T& operator()(const u32& row, const u32& col, const u32& layer) const {
+ check_indexing(row, col, layer);
+ return data[row * col_num * layer_num + col * layer_num + layer];
+ }
+
+ void set_one(const u32& row, const u32& col, const u32& layer, const T& value)
+ {
+ check_indexing(row, col, layer);
+ data[row * col_num * layer_num + col* layer_num + layer] = value;
+ }
+
+ void output_to_file(FILE* fp) const
+ {
+ fmt::print(fp, "# Matrix shape: {} {} {}\n", row_num, col_num, layer_num);
+ for (u32 l = 0; l < layer_num; l++)
+ {
+ fmt::print(fp, "# layer: {}\n", l);
+ for (u32 i = 0; i < row_num; i++)
+ {
+ for (u32 j = 0; j < col_num; j++)
+ {
+ fmt::print(fp, "{:.4f} ", data[i * col_num * layer_num + j * layer_num + l]);
+ }
+ fmt::print(fp, "\n");
+ }
+ }
+ }
+
+ const T* get_data_ptr() const
+ {
+ return data;
+ }
+};
+
+
+#endif // SELF_MATRIX_H
\ No newline at end of file
diff --git a/src/showWindowData.h b/src/showWindowData.h
index 4132b4e..c8c72d4 100644
--- a/src/showWindowData.h
+++ b/src/showWindowData.h
@@ -225,7 +225,7 @@ enum global_mode
mode_scaff_edit = 3,
mode_meta_edit = 4,
mode_extension = 5,
- mode_selectExclude_sort_area = 6
+ mode_select_sort_area = 6
};
diff --git a/src/spectral_cluster.h b/src/spectral_cluster.h
new file mode 100644
index 0000000..366924d
--- /dev/null
+++ b/src/spectral_cluster.h
@@ -0,0 +1,141 @@
+
+#ifndef SPECTRAL_CLUSTER_H
+#define SPECTRAL_CLUSTER_H
+
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "self_matrix.h"
+
+
+// Gaussian kernel
+double gaussian_kernel(const Eigen::VectorXd& xi, const Eigen::VectorXd& xj, double sigma) {
+ return exp(-(xi - xj).squaredNorm() / (2 * sigma * sigma));
+}
+
+// Similarity matrix
+Eigen::MatrixXd buildSimilarityMatrix(const Eigen::MatrixXd& X, double sigma) {
+ int n = X.rows();
+ Eigen::MatrixXd W(n, n);
+ for (int i = 0; i < n; ++i)
+ for (int j = 0; j < n; ++j)
+ W(i, j) = gaussian_kernel(X.row(i), X.row(j), sigma);
+ return W;
+}
+
+// Degree matrix
+Eigen::MatrixXd buildDegreeMatrix(const Eigen::MatrixXd& W) {
+ int n = W.rows();
+ Eigen::MatrixXd D = Eigen::MatrixXd::Zero(n, n);
+ for (int i = 0; i < n; ++i)
+ D(i, i) = W.row(i).sum();
+ return D;
+}
+
+// Basic KMeans clustering
+Eigen::VectorXi kmeans(const Eigen::MatrixXd& data, int k, int max_iters = 100) {
+ int n = data.rows();
+ int d = data.cols();
+ Eigen::VectorXi labels(n);
+ Eigen::MatrixXd centroids = Eigen::MatrixXd::Zero(k, d);
+
+ // Randomly initialize centroids
+ std::srand(static_cast(time(nullptr)));
+ for (int i = 0; i < k; ++i)
+ centroids.row(i) = data.row(std::rand() % n);
+
+ for (int iter = 0; iter < max_iters; ++iter) {
+ // Step 1: Assign labels
+ for (int i = 0; i < n; ++i) {
+ double min_dist = std::numeric_limits::max();
+ int best_cluster = 0;
+ for (int j = 0; j < k; ++j) {
+ double dist = (data.row(i) - centroids.row(j)).squaredNorm();
+ if (dist < min_dist) {
+ min_dist = dist;
+ best_cluster = j;
+ }
+ }
+ labels[i] = best_cluster;
+ }
+
+ // Step 2: Update centroids
+ Eigen::MatrixXd new_centroids = Eigen::MatrixXd::Zero(k, d);
+ Eigen::VectorXi count = Eigen::VectorXi::Zero(k);
+ for (int i = 0; i < n; ++i) {
+ new_centroids.row(labels[i]) += data.row(i);
+ count[labels[i]]++;
+ }
+ for (int j = 0; j < k; ++j)
+ if (count[j] > 0)
+ new_centroids.row(j) /= count[j];
+
+ // Check convergence
+ if ((centroids - new_centroids).norm() < 1e-4)
+ break;
+ centroids = new_centroids;
+ }
+
+ return labels;
+}
+
+
+Eigen::MatrixXd selfmatrix_to_eigenMatrix(const Matrix3D& adj_mat) {
+ Eigen::MatrixXd norm_mat(adj_mat.row_num, adj_mat.col_num);
+ float max_tmp = 0;
+ for (int i = 0; i < norm_mat.rows(); ++i) {
+ for (int j = 0; j < norm_mat.cols(); ++j) {
+ max_tmp = -1.;
+ for (int k = 0; k < 4; ++k) {
+ max_tmp = std::max(max_tmp, adj_mat(i, j, k));
+ }
+ norm_mat(i, j) = max_tmp;
+ }
+ }
+ return norm_mat;
+}
+
+
+std::vector> labels_to_clusters(const Eigen::VectorXi& labels, int k) {
+ std::vector> clusters(k);
+ for (int i = 0; i < labels.size(); ++i) {
+ clusters[labels[i]].push_back(i);
+ }
+ return clusters;
+}
+
+
+// Main spectral clustering function
+std::vector> spectral_clustering(const Matrix3D& adj_mat, int k) {
+
+ // Step 1: Similarity matrix
+ Eigen::MatrixXd W = selfmatrix_to_eigenMatrix(adj_mat);
+
+ // Step 2: Degree matrix
+ Eigen::MatrixXd D = buildDegreeMatrix(W);
+ // Step 3: Laplacian
+ Eigen::MatrixXd L = D - W;
+ // Step 4: Eigen decomposition
+ Eigen::SelfAdjointEigenSolver eigensolver(L);
+ if (eigensolver.info() != Eigen::Success)
+ throw std::runtime_error("Eigen decomposition failed");
+
+ // Step 5: Use first k smallest eigenvectors
+ Eigen::MatrixXd eigvecs = eigensolver.eigenvectors().leftCols(k);
+
+ // Optional: Row normalization
+ for (int i = 0; i < eigvecs.rows(); ++i)
+ eigvecs.row(i).normalize();
+
+ // Step 6: KMeans on rows of eigvecs
+ Eigen::VectorXi labels = kmeans(eigvecs, k);
+
+ return labels_to_clusters(labels, k);
+}
+
+#endif // SPECTRAL_CLUSTER_H
\ No newline at end of file
diff --git a/src/utilsPretextView.h b/src/utilsPretextView.h
index 13247e9..c01c04d 100644
--- a/src/utilsPretextView.h
+++ b/src/utilsPretextView.h
@@ -35,7 +35,7 @@ SOFTWARE.
#include
#include
#include
-
+#include
#include
#include
@@ -55,11 +55,6 @@ SOFTWARE.
-#include
-#include
-#include
-
-
/*
original version not commented here
*/
@@ -238,6 +233,7 @@ template
T percentile_cal(T* data, u32 size, f32 percentile=0.95)
{
u32 heap_size = (u32)((f32)size * (1-percentile));
+ if (heap_size <=0) return 1.;
std::priority_queue, std::greater> min_heap;
for (auto i = 0; i < size; i++)
{
@@ -251,6 +247,18 @@ T percentile_cal(T* data, u32 size, f32 percentile=0.95)
min_heap.push(data[i]);
}
}
+
+ if (min_heap.top() < 0 )
+ {
+ s32 cnt_neg_1 = 0;
+ for (int i = 0; i< size; i++) if (data[i] < 0) cnt_neg_1++;
+ fmt::print(
+ stderr,
+ "[percentile_cal::error] Number of negative value: {} / {}, file:{}, line:{}\n",
+ cnt_neg_1, size, __FILE__, __LINE__);
+ assert(0);
+ }
+
if (min_heap.size() > 0)
return min_heap.top();
else return 0;
diff --git a/subprojects/eigen b/subprojects/eigen
new file mode 160000
index 0000000..d6b23a2
--- /dev/null
+++ b/subprojects/eigen
@@ -0,0 +1 @@
+Subproject commit d6b23a2256b0c5d77bdc9988b8a82a9e79b5c5af
diff --git a/subprojects/pybind11 b/subprojects/pybind11
new file mode 160000
index 0000000..a28ea8c
--- /dev/null
+++ b/subprojects/pybind11
@@ -0,0 +1 @@
+Subproject commit a28ea8ccc5b98af73a2306ca0e43bcf0c82d39d8