-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Patatrack integration - HCAL local reconstruction (8/N) #31720
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
Merged
cmsbuild
merged 34 commits into
cms-sw:master
from
cms-patatrack:patatrack_integration_8_N_hcal_local_reco
Dec 8, 2020
Merged
Changes from all commits
Commits
Show all changes
34 commits
Select commit
Hold shift + click to select a range
3b94f5c
Synchronise with CMSSW_10_4_0_pre2
fwyzard 72d50ab
Synchronise with CMSSW_10_6_0
fwyzard 58530e9
Synchronise with CMSSW_11_0_0_pre7
fwyzard df660a5
Synchronise with CMSSW_11_0_0_pre12
fwyzard 00b22a2
Synchronise with CMSSW_11_1_0_pre5
fwyzard b906b1b
Synchronise with CMSSW_11_1_0_pre7
fwyzard 815e8fe
Implement HCAL local reconstruction on GPUs (cms-patatrack#468)
fwyzard ed51435
Update HCAL local reconstruction on GPUs (cms-patatrack#470)
fwyzard b836fc9
Restructure code to work around CUDA build limitations (cms-patatrack…
fwyzard e1381c7
Apply code formatting (cms-patatrack#486)
fwyzard 7ab00f9
Fix warnings about unused variables in HCAL GPU code (cms-patatrack#491)
fwyzard aa8fb93
Remove duplicate dictionary definitions (cms-patatrack#489)
fwyzard 32e7831
Backport: add ECAL-only and HCAL-only workflows for MC and data (#30350)
fwyzard 8a4f781
Implement HCAL-only workflows on GPU (cms-patatrack#505)
fwyzard e4145eb
Update ECAL and HCAL reconstruction to run on multple GPUs [1/3] (cms…
fwyzard 288b5df
Update ECAL and HCAL reconstruction to run on multple GPUs [2/3] (cms…
fwyzard e4406a3
Apply code formatting
fwyzard f95560a
Synchronise with CMSSW_11_2_0_pre2
fwyzard 4858247
Refactor common ECAL and HCAL code (cms-patatrack#523)
fwyzard 79af505
Apply code formatting (cms-patatrack#526)
fwyzard 41c6b90
Use up to 10 time samples for the HBHE digis in Run 3 MC (cms-patatr…
fwyzard d4c4136
Apply code checks and code format (cms-patatrack#532)
fwyzard 92a8ce4
HcalDigisProducerGPU: preallocate pinned host memory only if CUDA is …
fwyzard b7c9319
Move multifit/MAHI common code to DataFormats/CaloRecHit (cms-patatra…
fwyzard e9a3c6d
Address HCAL review comments regarding CondFormats/HcalObjects (cms-p…
fwyzard 8c9b251
Reduce code duplication in CPU and GPU modules (cms-patatrack#566)
fwyzard 0d0c22a
Address more HCAL review comments (cms-patatrack#568)
fwyzard bc425a2
Move common ESProducer templates to ConvertingESProducer(WithDependen…
fwyzard 831b90f
Apply clang-format style formatting
fwyzard bbd4cca
Refactor ECAL and HCAL chi2 code (cms-patatrack#567)
fwyzard 7d16cb3
Move the HCALGPUAnalyzer to RecoLocalCalo/HcalRecProducers/ (cms-pata…
fwyzard 3740b04
Synchronise GPU code with CPU updates (cms-patatrack#576)
fwyzard 8069664
Update GPU HCAL conditions framework (cms-patatrack#574)
fwyzard 8e6a6a3
Apply code formatting
fwyzard File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| <use name="DataFormats/Common"/> | ||
| <use name="CUDADataFormats/CaloCommon"/> | ||
| <use name="HeterogeneousCore/CUDAUtilities"/> | ||
| <use name="cuda"/> | ||
|
|
||
| <export> | ||
| <lib name="1"/> | ||
| </export> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,160 @@ | ||
| #ifndef CUDADataFormats_HcalDigi_interface_DigiCollection_h | ||
| #define CUDADataFormats_HcalDigi_interface_DigiCollection_h | ||
|
|
||
| #include "CUDADataFormats/CaloCommon/interface/Common.h" | ||
|
|
||
| namespace hcal { | ||
|
|
||
| // FLAVOR_HE_QIE11 = 1; Phase1 upgrade | ||
| struct Flavor1 { | ||
| static constexpr int WORDS_PER_SAMPLE = 1; | ||
| static constexpr int SAMPLES_PER_WORD = 1; | ||
| static constexpr int HEADER_WORDS = 1; | ||
|
|
||
| static constexpr uint8_t adc(uint16_t const* const sample_start) { return (*sample_start & 0xff); } | ||
| static constexpr uint8_t tdc(uint16_t const* const sample_start) { return (*sample_start >> 8) & 0x3f; } | ||
| static constexpr uint8_t soibit(uint16_t const* const sample_start) { return (*sample_start >> 14) & 0x1; } | ||
| }; | ||
|
|
||
| // FLAVOR_HB_QIE11 = 3; Phase1 upgrade | ||
| struct Flavor3 { | ||
| static constexpr int WORDS_PER_SAMPLE = 1; | ||
| static constexpr int SAMPLES_PER_WORD = 1; | ||
| static constexpr int HEADER_WORDS = 1; | ||
|
|
||
| static constexpr uint8_t adc(uint16_t const* const sample_start) { return (*sample_start & 0xff); } | ||
| static constexpr uint8_t tdc(uint16_t const* const sample_start) { return ((*sample_start >> 8) & 0x3); } | ||
| static constexpr uint8_t soibit(uint16_t const* const sample_start) { return ((*sample_start >> 14) & 0x1); } | ||
| static constexpr uint8_t capid(uint16_t const* const sample_start) { return ((*sample_start >> 10) & 0x3); } | ||
| }; | ||
|
|
||
| // FLAVOR_HB_QIE10 = 5; Phase0 | ||
| struct Flavor5 { | ||
| static constexpr float WORDS_PER_SAMPLE = 0.5; | ||
| static constexpr int SAMPLES_PER_WORD = 2; | ||
| static constexpr int HEADER_WORDS = 1; | ||
|
|
||
| static constexpr uint8_t adc(uint16_t const* const sample_start, uint8_t const shifter) { | ||
| return ((*sample_start >> shifter * 8) & 0x7f); | ||
| } | ||
| }; | ||
|
|
||
| template <typename Flavor> | ||
| constexpr uint8_t capid_for_sample(uint16_t const* const dfstart, uint32_t const sample) { | ||
| auto const capid_first = (*dfstart >> 8) & 0x3; | ||
| return (capid_first + sample) & 0x3; // same as % 4 | ||
| } | ||
|
|
||
| template <> | ||
| constexpr uint8_t capid_for_sample<Flavor3>(uint16_t const* const dfstart, uint32_t const sample) { | ||
| return Flavor3::capid(dfstart + Flavor3::HEADER_WORDS + sample * Flavor3::WORDS_PER_SAMPLE); | ||
| } | ||
|
|
||
| template <typename Flavor> | ||
| constexpr uint8_t soibit_for_sample(uint16_t const* const dfstart, uint32_t const sample) { | ||
| return Flavor::soibit(dfstart + Flavor::HEADER_WORDS + sample * Flavor::WORDS_PER_SAMPLE); | ||
| } | ||
|
|
||
| template <typename Flavor> | ||
| constexpr uint8_t adc_for_sample(uint16_t const* const dfstart, uint32_t const sample) { | ||
| return Flavor::adc(dfstart + Flavor::HEADER_WORDS + sample * Flavor::WORDS_PER_SAMPLE); | ||
| } | ||
|
|
||
| template <typename Flavor> | ||
| constexpr uint8_t tdc_for_sample(uint16_t const* const dfstart, uint32_t const sample) { | ||
| return Flavor::tdc(dfstart + Flavor::HEADER_WORDS + sample * Flavor::WORDS_PER_SAMPLE); | ||
| } | ||
|
|
||
| template <> | ||
| constexpr uint8_t adc_for_sample<Flavor5>(uint16_t const* const dfstart, uint32_t const sample) { | ||
| // avoid using WORDS_PER_SAMPLE and simply shift | ||
| return Flavor5::adc(dfstart + Flavor5::HEADER_WORDS + (sample >> 1), sample % 2); | ||
| } | ||
|
|
||
| template <typename Flavor> | ||
| constexpr uint32_t compute_stride(uint32_t const nsamples) { | ||
| return static_cast<uint32_t>(nsamples * Flavor::WORDS_PER_SAMPLE) + Flavor::HEADER_WORDS; | ||
| } | ||
|
|
||
| template <typename Flavor> | ||
| constexpr uint32_t compute_nsamples(uint32_t const nwords) { | ||
| if constexpr (Flavor::SAMPLES_PER_WORD >= 1) | ||
| return (nwords - Flavor::HEADER_WORDS) * Flavor::SAMPLES_PER_WORD; | ||
| else | ||
| return (nwords - Flavor::HEADER_WORDS) / Flavor::WORDS_PER_SAMPLE; | ||
| } | ||
|
|
||
| // | ||
| template <typename StoragePolicy> | ||
| struct DigiCollectionBase : public ::calo::common::AddSize<typename StoragePolicy::TagType> { | ||
| DigiCollectionBase() = default; | ||
| DigiCollectionBase(DigiCollectionBase const&) = default; | ||
| DigiCollectionBase& operator=(DigiCollectionBase const&) = default; | ||
|
|
||
| DigiCollectionBase(DigiCollectionBase&&) = default; | ||
| DigiCollectionBase& operator=(DigiCollectionBase&&) = default; | ||
|
|
||
| template <typename T = typename StoragePolicy::TagType> | ||
| typename std::enable_if<std::is_same<T, ::calo::common::tags::Vec>::value, void>::type resize(std::size_t size) { | ||
| ids.resize(size); | ||
| data.resize(size * stride); | ||
| } | ||
|
|
||
| template <typename T = typename StoragePolicy::TagType> | ||
| typename std::enable_if<std::is_same<T, ::calo::common::tags::Vec>::value, void>::type reserve(std::size_t size) { | ||
| ids.reserve(size); | ||
| data.reserve(size * stride); | ||
| } | ||
|
|
||
| template <typename T = typename StoragePolicy::TagType> | ||
| typename std::enable_if<std::is_same<T, ::calo::common::tags::Vec>::value, void>::type clear() { | ||
| ids.clear(); | ||
| data.clear(); | ||
| } | ||
|
|
||
| typename StoragePolicy::template StorageSelector<uint32_t>::type ids; | ||
| typename StoragePolicy::template StorageSelector<uint16_t>::type data; | ||
| uint32_t stride{0}; | ||
| }; | ||
|
|
||
| template <typename Flavor, typename StoragePolicy> | ||
| struct DigiCollection : public DigiCollectionBase<StoragePolicy> { | ||
| using DigiCollectionBase<StoragePolicy>::DigiCollectionBase; | ||
| }; | ||
|
|
||
| // NOTE: base ctors will not be available | ||
| template <typename StoragePolicy> | ||
| struct DigiCollection<Flavor5, StoragePolicy> : public DigiCollectionBase<StoragePolicy> { | ||
| DigiCollection() = default; | ||
|
|
||
| DigiCollection(DigiCollection const&) = default; | ||
| DigiCollection& operator=(DigiCollection const&) = default; | ||
|
|
||
| DigiCollection(DigiCollection&&) = default; | ||
| DigiCollection& operator=(DigiCollection&&) = default; | ||
|
|
||
| template <typename T = typename StoragePolicy::TagType> | ||
| typename std::enable_if<std::is_same<T, ::calo::common::tags::Vec>::value, void>::type resize(std::size_t size) { | ||
| DigiCollectionBase<StoragePolicy>::resize(size); | ||
| npresamples.resize(size); | ||
| } | ||
|
|
||
| template <typename T = typename StoragePolicy::TagType> | ||
| typename std::enable_if<std::is_same<T, ::calo::common::tags::Vec>::value, void>::type reserve(std::size_t size) { | ||
| DigiCollectionBase<StoragePolicy>::reserve(size); | ||
| npresamples.reserve(size); | ||
| } | ||
|
|
||
| template <typename T = typename StoragePolicy::TagType> | ||
| typename std::enable_if<std::is_same<T, ::calo::common::tags::Vec>::value, void>::type clear() { | ||
| DigiCollectionBase<StoragePolicy>::clear(); | ||
| npresamples.clear(); | ||
| } | ||
|
|
||
| // add npresamples member | ||
| typename StoragePolicy::template StorageSelector<uint8_t>::type npresamples; | ||
| }; | ||
|
|
||
| } // namespace hcal | ||
|
|
||
| #endif // CUDADataFormats_HcalDigi_interface_DigiCollection_h | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| #include "CUDADataFormats/Common/interface/Product.h" | ||
| #include "CUDADataFormats/HcalDigi/interface/DigiCollection.h" | ||
| #include "DataFormats/Common/interface/Wrapper.h" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| <lcgdict> | ||
| <class name="hcal::DigiCollectionBase<calo::common::VecStoragePolicy<std::allocator>>" /> | ||
| <class name="hcal::DigiCollectionBase<calo::common::VecStoragePolicy<calo::common::CUDAHostAllocatorAlias>>" /> | ||
|
|
||
| <class name="hcal::DigiCollection<hcal::Flavor1, calo::common::VecStoragePolicy<std::allocator>>" /> | ||
| <class name="hcal::DigiCollection<hcal::Flavor3, calo::common::VecStoragePolicy<std::allocator>>" /> | ||
| <class name="hcal::DigiCollection<hcal::Flavor5, calo::common::VecStoragePolicy<std::allocator>>" /> | ||
|
|
||
| <class name="hcal::DigiCollection<hcal::Flavor1, calo::common::VecStoragePolicy<calo::common::CUDAHostAllocatorAlias>>" /> | ||
| <class name="hcal::DigiCollection<hcal::Flavor3, calo::common::VecStoragePolicy<calo::common::CUDAHostAllocatorAlias>>" /> | ||
| <class name="hcal::DigiCollection<hcal::Flavor5, calo::common::VecStoragePolicy<calo::common::CUDAHostAllocatorAlias>>" /> | ||
|
|
||
| <class name="cms::cuda::Product<hcal::DigiCollection<hcal::Flavor1, calo::common::ViewStoragePolicy>>" persistent="false" /> | ||
| <class name="cms::cuda::Product<hcal::DigiCollection<hcal::Flavor3, calo::common::ViewStoragePolicy>>" persistent="false" /> | ||
| <class name="cms::cuda::Product<hcal::DigiCollection<hcal::Flavor5, calo::common::ViewStoragePolicy>>" persistent="false" /> | ||
|
|
||
| <class name="cms::cuda::Product<hcal::DigiCollection<hcal::Flavor1, calo::common::DevStoragePolicy>>" persistent="false" /> | ||
| <class name="cms::cuda::Product<hcal::DigiCollection<hcal::Flavor3, calo::common::DevStoragePolicy>>" persistent="false" /> | ||
| <class name="cms::cuda::Product<hcal::DigiCollection<hcal::Flavor5, calo::common::DevStoragePolicy>>" persistent="false" /> | ||
|
|
||
| <class name="edm::Wrapper<cms::cuda::Product<hcal::DigiCollection<hcal::Flavor1, calo::common::ViewStoragePolicy>>>" persistent="false" /> | ||
| <class name="edm::Wrapper<cms::cuda::Product<hcal::DigiCollection<hcal::Flavor3, calo::common::ViewStoragePolicy>>>" persistent="false" /> | ||
| <class name="edm::Wrapper<cms::cuda::Product<hcal::DigiCollection<hcal::Flavor5, calo::common::ViewStoragePolicy>>>" persistent="false" /> | ||
|
|
||
| <class name="edm::Wrapper<cms::cuda::Product<hcal::DigiCollection<hcal::Flavor1, calo::common::DevStoragePolicy>>>" persistent="false" /> | ||
| <class name="edm::Wrapper<cms::cuda::Product<hcal::DigiCollection<hcal::Flavor3, calo::common::DevStoragePolicy>>>" persistent="false" /> | ||
| <class name="edm::Wrapper<cms::cuda::Product<hcal::DigiCollection<hcal::Flavor5, calo::common::DevStoragePolicy>>>" persistent="false" /> | ||
|
|
||
| <class name="edm::Wrapper<hcal::DigiCollection<hcal::Flavor1, calo::common::VecStoragePolicy<std::allocator>>>" /> | ||
| <class name="edm::Wrapper<hcal::DigiCollection<hcal::Flavor3, calo::common::VecStoragePolicy<std::allocator>>>" /> | ||
| <class name="edm::Wrapper<hcal::DigiCollection<hcal::Flavor5, calo::common::VecStoragePolicy<std::allocator>>>" /> | ||
|
|
||
| <class name="edm::Wrapper<hcal::DigiCollection<hcal::Flavor1, calo::common::VecStoragePolicy<calo::common::CUDAHostAllocatorAlias>>>" /> | ||
| <class name="edm::Wrapper<hcal::DigiCollection<hcal::Flavor3, calo::common::VecStoragePolicy<calo::common::CUDAHostAllocatorAlias>>>" /> | ||
| <class name="edm::Wrapper<hcal::DigiCollection<hcal::Flavor5, calo::common::VecStoragePolicy<calo::common::CUDAHostAllocatorAlias>>>" /> | ||
| </lcgdict> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| <use name="DataFormats/Common"/> | ||
| <use name="CUDADataFormats/Common" /> | ||
| <use name="HeterogeneousCore/CUDAUtilities"/> | ||
|
|
||
| <export> | ||
| <lib name="1"/> | ||
| </export> |
38 changes: 38 additions & 0 deletions
38
CUDADataFormats/HcalRecHitSoA/interface/RecHitCollection.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| #ifndef CUDADataFormats_HcalRecHitCollectionSoA_interface_RecHitCollection_h | ||
| #define CUDADataFormats_HcalRecHitCollectionSoA_interface_RecHitCollection_h | ||
|
|
||
| #include <vector> | ||
|
|
||
| #include "CUDADataFormats/CaloCommon/interface/Common.h" | ||
| #include "HeterogeneousCore/CUDAUtilities/interface/HostAllocator.h" | ||
|
|
||
| namespace hcal { | ||
|
|
||
| template <typename StoragePolicy> | ||
| struct RecHitCollection : public ::calo::common::AddSize<typename StoragePolicy::TagType> { | ||
| RecHitCollection() = default; | ||
| RecHitCollection(const RecHitCollection&) = default; | ||
| RecHitCollection& operator=(const RecHitCollection&) = default; | ||
|
|
||
| RecHitCollection(RecHitCollection&&) = default; | ||
| RecHitCollection& operator=(RecHitCollection&&) = default; | ||
|
|
||
| typename StoragePolicy::template StorageSelector<float>::type energy; | ||
| typename StoragePolicy::template StorageSelector<float>::type chi2; | ||
| typename StoragePolicy::template StorageSelector<float>::type energyM0; | ||
| typename StoragePolicy::template StorageSelector<float>::type timeM0; | ||
| typename StoragePolicy::template StorageSelector<uint32_t>::type did; | ||
|
|
||
| template <typename U = typename StoragePolicy::TagType> | ||
| typename std::enable_if<std::is_same<U, ::calo::common::tags::Vec>::value, void>::type resize(size_t size) { | ||
| energy.resize(size); | ||
| chi2.resize(size); | ||
| energyM0.resize(size); | ||
| timeM0.resize(size); | ||
| did.resize(size); | ||
| } | ||
| }; | ||
|
|
||
| } // namespace hcal | ||
|
|
||
| #endif // RecoLocalCalo_HcalRecAlgos_interface_RecHitCollection_h |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| #include "CUDADataFormats/Common/interface/Product.h" | ||
| #include "CUDADataFormats/HcalRecHitSoA/interface/RecHitCollection.h" | ||
| #include "DataFormats/Common/interface/Wrapper.h" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| <lcgdict> | ||
| <class name="hcal::RecHitCollection<calo::common::VecStoragePolicy<std::allocator>>"/> | ||
| <class name="edm::Wrapper<hcal::RecHitCollection<calo::common::VecStoragePolicy<std::allocator>>>"/> | ||
|
|
||
| <class name="hcal::RecHitCollection<calo::common::VecStoragePolicy<calo::common::CUDAHostAllocatorAlias>>"/> | ||
| <class name="edm::Wrapper<hcal::RecHitCollection<calo::common::VecStoragePolicy<calo::common::CUDAHostAllocatorAlias>>>"/> | ||
|
|
||
| <class name="cms::cuda::Product<hcal::RecHitCollection<calo::common::ViewStoragePolicy>>" persistent="false" /> | ||
| <class name="edm::Wrapper<cms::cuda::Product<hcal::RecHitCollection<calo::common::ViewStoragePolicy>>>" persistent="false" /> | ||
|
|
||
| <class name="cms::cuda::Product<hcal::RecHitCollection<calo::common::DevStoragePolicy>>" persistent="false" /> | ||
| <class name="edm::Wrapper<cms::cuda::Product<hcal::RecHitCollection<calo::common::DevStoragePolicy>>>" persistent="false" /> | ||
| </lcgdict> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| <bin name="makeHcalRaw2DigiGpuValidationPlots" file="makeHcalRaw2DigiGpuValidationPlots.cpp"> | ||
| <use name="root"/> | ||
| <use name="rootgraphics"/> | ||
| <use name="DataFormats/Common"/> | ||
| <use name="DataFormats/HcalDigi"/> | ||
| <use name="DataFormats/HcalDetId"/> | ||
| <use name="cuda"/> | ||
| </bin> |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.