Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add UniGradICON Extension #2100

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

Add UniGradICON Extension #2100

wants to merge 2 commits into from

Conversation

basardemir
Copy link

@basardemir basardemir commented Oct 29, 2024

New extension

  • Extension has a reasonable name (not too general, not too narrow, suggests what the extension is for)
  • Repository name is Slicer+ExtensionName
  • Repository is associated with 3d-slicer-extension GitHub topic so that it is listed here. To edit topics, click the settings icon in the right side of "About" section header and enter 3d-slicer-extension in "Topics" and click "Save changes". To learn more about topics, read https://help.github.com/en/articles/about-topics
  • Extension description summarizes in 1-2 sentences what the extension is usable (should be understandable for non-experts)
  • Any known related patents must be mentioned in the extension description.
  • LICENSE.txt is present in the repository root. MIT (https://choosealicense.com/licenses/mit/) or Apache (https://choosealicense.com/licenses/apache-2.0/) license is recommended. If source code license is more restrictive for users than MIT, BSD, Apache, or 3D Slicer license then the name of the used license must be mentioned in the extension description.
  • Extension URL and revision (scmurl, scmrevision) is correct, consider using a branch name (main, release, ...) instead of a specific git hash to avoid re-submitting pull request whenever the extension is updated
  • Extension icon URL is correct (do not use the icon's webpage but the raw data download URL that you get from the download button - it should look something like this: https://raw.githubusercontent.com/user/repo/main/SomeIcon.png)
  • Screenshot URLs (screenshoturls) are correct, contains at least one
  • Homepage URL points to valid webpage containing the following:
    • Extension name
    • Short description: 1-2 sentences, which summarizes what the extension is usable for
    • At least one nice, informative image, that illustrates what the extension can do. It may be a screenshot.
    • Description of contained modules: at one sentence for each module
    • Tutorial: step-by-step description of at least the most typical use case, include a few screenshots, provide download links to sample input data set
    • Publication: link to publication and/or to PubMed reference (if available)
    • License: We suggest you use a permissive license that includes patent and contribution clauses. This will help protect developers and ensure the code remains freely available. We suggest you use the Slicer License or the Apache 2.0. Always mention in your README file the license you have chosen. If you choose a different license, explain why to the extension maintainers. Depending on the license we may not be able to host your work. Read here to learn more about licenses.
    • Content of submitted json file is consistent with the top-level CMakeLists.txt file in the repository (dependencies, etc. are the same)
  • Hide unused features in the repository to reduce noise/irrelevant information:
    • Click Settings and in repository settings uncheck Wiki, Projects, and Discussions (if they are currently not used)
    • Click the settings icon next to About in the top-right corner of the repository main page and uncheck Releases and Packages (if they are currently not used)

@lassoan
Copy link
Contributor

lassoan commented Nov 16, 2024

Thank you very much for your contribution. It will be great to try this new registration tool in Slicer!

  • Many extensions use pytorch, so installation of pytorch has to be coordinated among extensions, by using the SlicerPytorch extension. See an example how to install it here
  • Remove installation of SimpleITK. It is already bundled with Slicer.
  • Do not delete the input node! You can load a transform by creating a storage node (CreateDefaultStorageNode()) and read the node using this storage node (sn.SetFileName(...); sn.ReadData(transformNode)).
  • Registration can take several minutes. Provide some progress feedback. For example, make the logic class call a callback function to report progress (at least some status string, maybe percentage complete). See for example here: https://github.com/lassoan/SlicerTotalSegmentator/blob/c4144875e600705f4c4b30a44b49d05d27ffb757/TotalSegmentator/TotalSegmentator.py#L594-L597
  • All .py files in the module folder must be Slicer modules. Therefore, icon_helper.py file must be either moved into a subfolder (with a init.py file so that it can be imported) or the helper file content has to be moved into the module .py file.
  • Test would take a very long time and would install a large package, so please disable it by default (similarly to this). We'll figure out something later for automated testing computationally expensive deep learning modules.
  • When installing pytorch with CUDA acceleration then the module fails:
Python 3.9.10 (main, Nov  1 2024, 23:20:57) [MSC v.1939 64 bit (AMD64)] on win32
>>> 
RuntimeError: qSlicerScriptedLoadableModule::setPythonSource - Failed to load scripted loadable module: class icon_helper was not found in file C:/D/SlicerUniGradICON/UniGradICON/icon_helper.py
[Qt] Fail to instantiate module  "icon_helper"
[Qt] The following modules failed to be instantiated:
[Qt]    icon_helper
cpu
You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature.
You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature.
Traceback (most recent call last):
  File "C:/D/SlicerUniGradICON/UniGradICON/UniGradICON.py", line 333, in onRunRegistrationButton
    self.logic.process(**parameters)
  File "C:/D/SlicerUniGradICON/UniGradICON/UniGradICON.py", line 457, in process
    phi_AB, _ = icon_helper.register_pair(
  File "C:/D/SlicerUniGradICON/UniGradICON/icon_helper.py", line 235, in register_pair
    loss = model(A_resized, B_resized)
  File "C:\Users\andra\AppData\Local\slicer.org\Slicer 5.7.0-2024-11-01\lib\Python\Lib\site-packages\torch\nn\modules\module.py", line 1736, in _wrapped_call_impl
    return self._call_impl(*args, **kwargs)
  File "C:\Users\andra\AppData\Local\slicer.org\Slicer 5.7.0-2024-11-01\lib\Python\Lib\site-packages\torch\nn\modules\module.py", line 1747, in _call_impl
    return forward_call(*args, **kwargs)
  File "C:/D/SlicerUniGradICON/UniGradICON/icon_helper.py", line 30, in forward
    self.phi_AB = self.regis_net(image_A, image_B)
  File "C:\Users\andra\AppData\Local\slicer.org\Slicer 5.7.0-2024-11-01\lib\Python\Lib\site-packages\torch\nn\modules\module.py", line 1736, in _wrapped_call_impl
    return self._call_impl(*args, **kwargs)
  File "C:\Users\andra\AppData\Local\slicer.org\Slicer 5.7.0-2024-11-01\lib\Python\Lib\site-packages\torch\nn\modules\module.py", line 1747, in _call_impl
    return forward_call(*args, **kwargs)
  File "C:\Users\andra\AppData\Local\slicer.org\Slicer 5.7.0-2024-11-01\lib\Python\Lib\site-packages\icon_registration\network_wrappers.py", line 212, in forward
    phi = self.netPhi(image_A, image_B)
  File "C:\Users\andra\AppData\Local\slicer.org\Slicer 5.7.0-2024-11-01\lib\Python\Lib\site-packages\torch\nn\modules\module.py", line 1736, in _wrapped_call_impl
    return self._call_impl(*args, **kwargs)
  File "C:\Users\andra\AppData\Local\slicer.org\Slicer 5.7.0-2024-11-01\lib\Python\Lib\site-packages\torch\nn\modules\module.py", line 1747, in _call_impl
    return forward_call(*args, **kwargs)
  File "C:\Users\andra\AppData\Local\slicer.org\Slicer 5.7.0-2024-11-01\lib\Python\Lib\site-packages\icon_registration\network_wrappers.py", line 212, in forward
    phi = self.netPhi(image_A, image_B)
  File "C:\Users\andra\AppData\Local\slicer.org\Slicer 5.7.0-2024-11-01\lib\Python\Lib\site-packages\torch\nn\modules\module.py", line 1736, in _wrapped_call_impl
    return self._call_impl(*args, **kwargs)
  File "C:\Users\andra\AppData\Local\slicer.org\Slicer 5.7.0-2024-11-01\lib\Python\Lib\site-packages\torch\nn\modules\module.py", line 1747, in _call_impl
    return forward_call(*args, **kwargs)
  File "C:\Users\andra\AppData\Local\slicer.org\Slicer 5.7.0-2024-11-01\lib\Python\Lib\site-packages\icon_registration\network_wrappers.py", line 247, in forward
    return self.net(image_A, image_B)
  File "C:\Users\andra\AppData\Local\slicer.org\Slicer 5.7.0-2024-11-01\lib\Python\Lib\site-packages\torch\nn\modules\module.py", line 1736, in _wrapped_call_impl
    return self._call_impl(*args, **kwargs)
  File "C:\Users\andra\AppData\Local\slicer.org\Slicer 5.7.0-2024-11-01\lib\Python\Lib\site-packages\torch\nn\modules\module.py", line 1747, in _call_impl
    return forward_call(*args, **kwargs)
  File "C:\Users\andra\AppData\Local\slicer.org\Slicer 5.7.0-2024-11-01\lib\Python\Lib\site-packages\icon_registration\network_wrappers.py", line 212, in forward
    phi = self.netPhi(image_A, image_B)
  File "C:\Users\andra\AppData\Local\slicer.org\Slicer 5.7.0-2024-11-01\lib\Python\Lib\site-packages\torch\nn\modules\module.py", line 1736, in _wrapped_call_impl
    return self._call_impl(*args, **kwargs)
  File "C:\Users\andra\AppData\Local\slicer.org\Slicer 5.7.0-2024-11-01\lib\Python\Lib\site-packages\torch\nn\modules\module.py", line 1747, in _call_impl
    return forward_call(*args, **kwargs)
  File "C:\Users\andra\AppData\Local\slicer.org\Slicer 5.7.0-2024-11-01\lib\Python\Lib\site-packages\icon_registration\network_wrappers.py", line 247, in forward
    return self.net(image_A, image_B)
  File "C:\Users\andra\AppData\Local\slicer.org\Slicer 5.7.0-2024-11-01\lib\Python\Lib\site-packages\torch\nn\modules\module.py", line 1736, in _wrapped_call_impl
    return self._call_impl(*args, **kwargs)
  File "C:\Users\andra\AppData\Local\slicer.org\Slicer 5.7.0-2024-11-01\lib\Python\Lib\site-packages\torch\nn\modules\module.py", line 1747, in _call_impl
    return forward_call(*args, **kwargs)
  File "C:\Users\andra\AppData\Local\slicer.org\Slicer 5.7.0-2024-11-01\lib\Python\Lib\site-packages\icon_registration\network_wrappers.py", line 112, in forward
    tensor_of_displacements = self.net(image_A, image_B)
  File "C:\Users\andra\AppData\Local\slicer.org\Slicer 5.7.0-2024-11-01\lib\Python\Lib\site-packages\torch\nn\modules\module.py", line 1736, in _wrapped_call_impl
    return self._call_impl(*args, **kwargs)
  File "C:\Users\andra\AppData\Local\slicer.org\Slicer 5.7.0-2024-11-01\lib\Python\Lib\site-packages\torch\nn\modules\module.py", line 1747, in _call_impl
    return forward_call(*args, **kwargs)
  File "C:\Users\andra\AppData\Local\slicer.org\Slicer 5.7.0-2024-11-01\lib\Python\Lib\site-packages\icon_registration\networks.py", line 260, in forward
    y = self.downConvs[depth](F.leaky_relu(x))
  File "C:\Users\andra\AppData\Local\slicer.org\Slicer 5.7.0-2024-11-01\lib\Python\Lib\site-packages\torch\nn\modules\module.py", line 1736, in _wrapped_call_impl
    return self._call_impl(*args, **kwargs)
  File "C:\Users\andra\AppData\Local\slicer.org\Slicer 5.7.0-2024-11-01\lib\Python\Lib\site-packages\torch\nn\modules\module.py", line 1747, in _call_impl
    return forward_call(*args, **kwargs)
  File "C:\Users\andra\AppData\Local\slicer.org\Slicer 5.7.0-2024-11-01\lib\Python\Lib\site-packages\torch\nn\modules\conv.py", line 725, in forward
    return self._conv_forward(input, self.weight, self.bias)
  File "C:\Users\andra\AppData\Local\slicer.org\Slicer 5.7.0-2024-11-01\lib\Python\Lib\site-packages\torch\nn\modules\conv.py", line 720, in _conv_forward
    return F.conv3d(
NotImplementedError: Could not run 'aten::slow_conv3d_forward' with arguments from the 'CUDA' backend. This could be because the operator doesn't exist for this backend, or was omitted during the selective/custom build process (if using custom build). If you are a Facebook employee using PyTorch on mobile, please visit https://fburl.com/ptmfixes for possible resolutions. 'aten::slow_conv3d_forward' is only available for these backends: [CPU, Meta, BackendSelect, Python, FuncTorchDynamicLayerBackMode, Functionalize, Named, Conjugate, Negative, ZeroTensor, ADInplaceOrView, AutogradOther, AutogradCPU, AutogradCUDA, AutogradHIP, AutogradXLA, AutogradMPS, AutogradIPU, AutogradXPU, AutogradHPU, AutogradVE, AutogradLazy, AutogradMTIA, AutogradPrivateUse1, AutogradPrivateUse2, AutogradPrivateUse3, AutogradMeta, AutogradNestedTensor, Tracer, AutocastCPU, AutocastXPU, AutocastMPS, AutocastCUDA, FuncTorchBatched, BatchedNestedTensor, FuncTorchVmapMode, Batched, VmapMode, FuncTorchGradWrapper, PythonTLSSnapshot, FuncTorchDynamicLayerFrontMode, PreDispatch, PythonDispatcher].

CPU: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\build\aten\src\ATen\RegisterCPU.cpp:30476 [kernel]
Meta: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\aten\src\ATen\core\MetaFallbackKernel.cpp:23 [backend fallback]
BackendSelect: fallthrough registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\aten\src\ATen\core\BackendSelectFallbackKernel.cpp:3 [backend fallback]
Python: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\aten\src\ATen\core\PythonFallbackKernel.cpp:153 [backend fallback]
FuncTorchDynamicLayerBackMode: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\aten\src\ATen\functorch\DynamicLayer.cpp:497 [backend fallback]
Functionalize: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\aten\src\ATen\FunctionalizeFallbackKernel.cpp:349 [backend fallback]
Named: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\aten\src\ATen\core\NamedRegistrations.cpp:7 [backend fallback]
Conjugate: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\aten\src\ATen\ConjugateFallback.cpp:17 [backend fallback]
Negative: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\aten\src\ATen\native\NegateFallback.cpp:18 [backend fallback]
ZeroTensor: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\aten\src\ATen\ZeroTensorFallback.cpp:86 [backend fallback]
ADInplaceOrView: fallthrough registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\aten\src\ATen\core\VariableFallbackKernel.cpp:96 [backend fallback]
AutogradOther: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\torch\csrc\autograd\generated\VariableType_4.cpp:18915 [autograd kernel]
AutogradCPU: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\torch\csrc\autograd\generated\VariableType_4.cpp:18915 [autograd kernel]
AutogradCUDA: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\torch\csrc\autograd\generated\VariableType_4.cpp:18915 [autograd kernel]
AutogradHIP: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\torch\csrc\autograd\generated\VariableType_4.cpp:18915 [autograd kernel]
AutogradXLA: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\torch\csrc\autograd\generated\VariableType_4.cpp:18915 [autograd kernel]
AutogradMPS: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\torch\csrc\autograd\generated\VariableType_4.cpp:18915 [autograd kernel]
AutogradIPU: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\torch\csrc\autograd\generated\VariableType_4.cpp:18915 [autograd kernel]
AutogradXPU: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\torch\csrc\autograd\generated\VariableType_4.cpp:18915 [autograd kernel]
AutogradHPU: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\torch\csrc\autograd\generated\VariableType_4.cpp:18915 [autograd kernel]
AutogradVE: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\torch\csrc\autograd\generated\VariableType_4.cpp:18915 [autograd kernel]
AutogradLazy: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\torch\csrc\autograd\generated\VariableType_4.cpp:18915 [autograd kernel]
AutogradMTIA: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\torch\csrc\autograd\generated\VariableType_4.cpp:18915 [autograd kernel]
AutogradPrivateUse1: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\torch\csrc\autograd\generated\VariableType_4.cpp:18915 [autograd kernel]
AutogradPrivateUse2: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\torch\csrc\autograd\generated\VariableType_4.cpp:18915 [autograd kernel]
AutogradPrivateUse3: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\torch\csrc\autograd\generated\VariableType_4.cpp:18915 [autograd kernel]
AutogradMeta: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\torch\csrc\autograd\generated\VariableType_4.cpp:18915 [autograd kernel]
AutogradNestedTensor: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\torch\csrc\autograd\generated\VariableType_4.cpp:18915 [autograd kernel]
Tracer: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\torch\csrc\autograd\generated\TraceType_4.cpp:13465 [kernel]
AutocastCPU: fallthrough registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\aten\src\ATen\autocast_mode.cpp:321 [backend fallback]
AutocastXPU: fallthrough registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\aten\src\ATen\autocast_mode.cpp:463 [backend fallback]
AutocastMPS: fallthrough registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\aten\src\ATen\autocast_mode.cpp:209 [backend fallback]
AutocastCUDA: fallthrough registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\aten\src\ATen\autocast_mode.cpp:165 [backend fallback]
FuncTorchBatched: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\aten\src\ATen\functorch\LegacyBatchingRegistrations.cpp:731 [backend fallback]
BatchedNestedTensor: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\aten\src\ATen\functorch\LegacyBatchingRegistrations.cpp:758 [backend fallback]
FuncTorchVmapMode: fallthrough registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\aten\src\ATen\functorch\VmapModeRegistrations.cpp:27 [backend fallback]
Batched: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\aten\src\ATen\LegacyBatchingRegistrations.cpp:1075 [backend fallback]
VmapMode: fallthrough registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\aten\src\ATen\VmapModeRegistrations.cpp:33 [backend fallback]
FuncTorchGradWrapper: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\aten\src\ATen\functorch\TensorWrapper.cpp:207 [backend fallback]
PythonTLSSnapshot: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\aten\src\ATen\core\PythonFallbackKernel.cpp:161 [backend fallback]
FuncTorchDynamicLayerFrontMode: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\aten\src\ATen\functorch\DynamicLayer.cpp:493 [backend fallback]
PreDispatch: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\aten\src\ATen\core\PythonFallbackKernel.cpp:165 [backend fallback]
PythonDispatcher: registered at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\aten\src\ATen\core\PythonFallbackKernel.cpp:157 [backend fallback]

[Python] MRMLIDImageIO is not available, SimpleITK image transfer speed will be slower. Probably an extension replaced SimpleITK version that was bundled with Slicer. Current SimpleITK version: 2.4.0
does not have observer
[VTK] Input port 0 of algorithm vtkImageMapToWindowLevelColors (000001C723C57590) has 0 connections but is not optional.
[VTK] Input port 0 of algorithm vtkImageThreshold (000001C6B74E9210) has 0 connections but is not optional.
[VTK] Input port 0 of algorithm vtkImageMapToWindowLevelColors (000001C723C57590) has 0 connections but is not optional.
[VTK] Input port 0 of algorithm vtkImageMapToWindowLevelColors (000001C723C57590) has 0 connections but is not optional.
[VTK] Input port 0 of algorithm vtkImageThreshold (000001C6B74E9210) has 0 connections but is not optional.

FYI, installation (until the extension is added to the extensions manager) is much simpler that it is currently described in the extension documentation:

  1. download the extension from github
  2. drag-and-drop the UniGradICON folder to the Slicer application window
  3. click OK
    That's all, the module is loaded and available in the module list.

@lassoan lassoan added the Status: Awaiting Response ⏳ Waiting for a response/more information label Nov 16, 2024
@basardemir
Copy link
Author

Dear @lassoan,

Thank you very much for your thorough review and valuable feedback. We have addressed the issues you pointed out and made the following updates:

  • Made our extension compatible with the PyTorch Slicer extension (code reference).
  • Removed the installation of SimpleITK.
  • Switched to DefaultStorageNode for handling transformation visualization (code reference).
  • Added a progress bar and remaining time information to enhance user experience during instance optimization (IO) (code reference).
  • Moved icon_helper to a subfolder.
  • Disabled testing.
  • Resolved the CUDA acceleration issue.
  • Updated the installation instructions in the README to incorporate your suggested drag-and-drop approach.

Thank you again for your support and insights. We look forward to hearing your thoughts on these updates!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Awaiting Response ⏳ Waiting for a response/more information
Development

Successfully merging this pull request may close these issues.

2 participants