diff --git a/Application/src/commons/common/gui/CrossPlatform.h b/Application/src/commons/common/gui/CrossPlatform.h
index 1618e22287de2c4f0797a1df43e4fd94936540af..4d424d4eebe6fa8f63f433c24ff3cd0c6fad0471 100644
--- a/Application/src/commons/common/gui/CrossPlatform.h
+++ b/Application/src/commons/common/gui/CrossPlatform.h
@@ -11,10 +11,10 @@ namespace gui {
     struct PlatformTexture {
         void* ptr = nullptr ;
         std::function<void(void**)> deleter;
-        int width;
-        int height;
-        int image_width;
-        int image_height;
+        uint width = 0;
+        uint height = 0;
+        uint image_width = 0;
+        uint image_height = 0;
         
         PlatformTexture() = default;
         ~PlatformTexture() {
diff --git a/Application/src/commons/common/gui/GLImpl.cpp b/Application/src/commons/common/gui/GLImpl.cpp
index ea86c3ae8f221638f27d5310fa3509778ae873ff..903df07ca5178a39190c18a51f4241fcb3869acb 100644
--- a/Application/src/commons/common/gui/GLImpl.cpp
+++ b/Application/src/commons/common/gui/GLImpl.cpp
@@ -426,8 +426,8 @@ TexturePtr GLImpl::texture(const Image * ptr) {
             
             *ptr = nullptr;
         },
-        static_cast<int>(width), static_cast<int>(height),
-        static_cast<int>(ptr->cols), static_cast<int>(ptr->rows)
+        static_cast<uint>(width), static_cast<uint>(height),
+        ptr->cols, ptr->rows
     });
 }
 
diff --git a/Application/src/commons/common/gui/IMGUIBase.cpp b/Application/src/commons/common/gui/IMGUIBase.cpp
index d0eb29dcf3d7acb90d10b1a0f27ea03c16494761..03562bd8622e334c91dfe8e4ff6680ca76182c64 100644
--- a/Application/src/commons/common/gui/IMGUIBase.cpp
+++ b/Application/src/commons/common/gui/IMGUIBase.cpp
@@ -452,7 +452,7 @@ void clear_cache() {
             if (!ptr) {
                 Warning("Cannot load font '%S' with index %d.", &path.str(), config.FontNo);
                 ptr = io.Fonts->AddFontDefault();
-                im_font_scale = max(1, dpi_scale) * 0.5;
+                im_font_scale = max(1, dpi_scale) * 0.5f;
             }
             ptr->FontSize = base_scale * im_font_scale;
             
diff --git a/Application/src/commons/common/gui/MetalImpl.mm b/Application/src/commons/common/gui/MetalImpl.mm
index 63a5593c7dc67262247d6597215960b21833b758..e24bd469ed8d4a7591f6986aa26cbccd1f44c941 100644
--- a/Application/src/commons/common/gui/MetalImpl.mm
+++ b/Application/src/commons/common/gui/MetalImpl.mm
@@ -354,8 +354,8 @@ bool MetalImpl::open_files(const std::vector<file::Path> &paths) {
     TexturePtr MetalImpl::texture(const Image * ptr) {
         GLIMPL_CHECK_THREAD_ID();
         
-        int width = next_pow2(ptr->cols);
-        int height = next_pow2(ptr->rows);
+        uint width = next_pow2(ptr->cols);
+        uint height = next_pow2(ptr->rows);
         
         auto input_format = MTLPixelFormatRGBA8Unorm;
         if(ptr->dims == 1) {
@@ -399,7 +399,7 @@ bool MetalImpl::open_files(const std::vector<file::Path> &paths) {
             *ptr = nullptr;
             //id<MTLTexture> texture = (__bridge id<MTLTexture>)ptr;
             //[texture release];
-        }, width, height, static_cast<int>(ptr->cols), static_cast<int>(ptr->rows)});
+        }, width, height, ptr->cols, ptr->rows});
     }
 
     void MetalImpl::clear_texture(TexturePtr&& tex) {
diff --git a/Application/src/commons/common/misc/metastring.h b/Application/src/commons/common/misc/metastring.h
index 35a3384cf253740d6cf24810c14e084b28d042cb..70e79347ec40a30b09f13f3dbb7163dd683ba77e 100644
--- a/Application/src/commons/common/misc/metastring.h
+++ b/Application/src/commons/common/misc/metastring.h
@@ -257,6 +257,9 @@ namespace cmn {
         template <typename T>
         struct has_tostr_method;
     
+        template <typename T>
+        struct has_classname_method;
+    
         template <typename T>
         struct has_internal_tostr_method;
     
@@ -303,7 +306,7 @@ namespace cmn {
         template<class Q> std::string name(const typename std::enable_if< std::is_same<DurationUS, typename std::remove_cv<Q>::type>::value, Q >::type* =nullptr) { return "time"; }
         
         template<class Q>
-        std::string name(const typename std::enable_if< std::is_convertible<Q, MetaObject>::value, Q >::type* =nullptr) {
+        std::string name(const typename std::enable_if< std::is_convertible<Q, MetaObject>::value || Meta::has_classname_method<Q>::value, Q >::type* =nullptr) {
             //MetaObject obj = Q();
             //return obj.class_name();
             return Q::class_name();
@@ -1002,6 +1005,21 @@ namespace cmn {
             static const bool value = std::is_same<std::true_type, decltype(test<T, dummy>(nullptr))>::value;
         };
     
+        template <typename T>
+        struct has_classname_method
+        {
+            struct dummy {  };
+            
+            template <typename C, typename P>
+            static auto test(C * p) -> decltype(static_cast<void>(sizeof(decltype(C::class_name()))), std::true_type());
+            
+            template <typename, typename>
+            static std::false_type test(...);
+            
+            typedef decltype(test<T, dummy>(nullptr)) type;
+            static const bool value = std::is_same<std::true_type, decltype(test<T, dummy>(nullptr))>::value;
+        };
+    
         template <typename T>
         struct has_internal_tostr_method
         {
diff --git a/Application/src/commons/common/types.h b/Application/src/commons/common/types.h
index 2be9394fd45f4456d9a0dcfafa1484c1ce7fedb1..c31e929ab95c90b42178a72e038d5ea5520527e3 100644
--- a/Application/src/commons/common/types.h
+++ b/Application/src/commons/common/types.h
@@ -35,7 +35,6 @@ namespace gui {
 
 namespace track {
     using namespace cmn;
-    typedef long_t idx_t;
 }
 
 #include <misc/vec2.h>
diff --git a/Application/src/grabber/default_config.cpp b/Application/src/grabber/default_config.cpp
index 3afaf6226a8d9250a149e4821aa5b4b2d2ee5c11..9c2fac044c33f4fc18435308a7738f6cf255a2c9 100644
--- a/Application/src/grabber/default_config.cpp
+++ b/Application/src/grabber/default_config.cpp
@@ -72,7 +72,7 @@ namespace default_config {
 #endif
         
         CONFIG("app_name", std::string("TGrabs"), "Name of the application.", SYSTEM);
-        CONFIG("version", std::string("1.0.4"), "Version of the application.", SYSTEM);
+        CONFIG("version", std::string("1.0.5"), "Version of the application.", SYSTEM);
         CONFIG("color_channel", size_t(1), "Index (0-2) of the color channel to be used during video conversion, if more than one channel is present in the video file.");
         CONFIG("system_memory_limit", uint64_t(0), "Custom override of how many bytes of system RAM the program is allowed to fill. If `approximate_length_minutes` or `stop_after_minutes` are set, this might help to increase the resulting RAW video footage frame_rate.");
         
diff --git a/Application/src/grabber/main.cpp b/Application/src/grabber/main.cpp
index 26860c0402bc567d1da949f0c97d408df46e8a70..b421109cb627185d7e9a480433efc03f09d0585e 100644
--- a/Application/src/grabber/main.cpp
+++ b/Application/src/grabber/main.cpp
@@ -636,11 +636,11 @@ int main(int argc, char** argv)
             Debug("Logging to '%S'.", &path.str());
         }
         
-        if(SETTING(manual_identities).value<std::set<uint32_t>>().empty() && SETTING(track_max_individuals).value<uint32_t>() != 0)
+        if(SETTING(manual_identities).value<std::set<track::Idx_t>>().empty() && SETTING(track_max_individuals).value<uint32_t>() != 0)
         {
-            std::set<uint32_t> vector;
+            std::set<track::Idx_t> vector;
             for(uint32_t i=0; i<SETTING(track_max_individuals).value<uint32_t>(); ++i) {
-                vector.insert(i);
+                vector.insert(track::Idx_t(i));
             }
             SETTING(manual_identities) = vector;
         }
diff --git a/Application/src/tracker/gui/DrawDataset.cpp b/Application/src/tracker/gui/DrawDataset.cpp
index d689407588a73e6c7fe55718d28baedeac8aaadd..f3859894d5dee61f056c1b893ad2ef1f8ba55b5c 100644
--- a/Application/src/tracker/gui/DrawDataset.cpp
+++ b/Application/src/tracker/gui/DrawDataset.cpp
@@ -65,7 +65,7 @@ namespace gui {
                 return;
             }
             
-            using dataset_t = std::tuple<std::map<track::idx_t, DatasetQuality::Single>, DatasetQuality::Quality>;
+            using dataset_t = std::tuple<std::map<track::Idx_t, DatasetQuality::Single>, DatasetQuality::Quality>;
             //_current_quality = dataset ? dataset->quality(frame) : -1;
                 
             for(auto id : FAST_SETTINGS(manual_identities)) {
@@ -119,7 +119,7 @@ namespace gui {
             
             auto && [per_fish, quality] = dataset
                 ? dataset_t{ dataset->per_fish(consec), dataset->quality(consec) }
-                : dataset_t{ std::map<track::idx_t, DatasetQuality::Single>{}, DatasetQuality::Quality() };
+                : dataset_t{ std::map<track::Idx_t, DatasetQuality::Single>{}, DatasetQuality::Quality() };
             
             _meta = per_fish;
             _last_consecutive_frames = consec;
@@ -145,16 +145,16 @@ namespace gui {
          * is available for given individual.
          */
         
-        std::set<long_t> identities_found;
-        std::set<long_t> double_identities;
-        std::map<long_t, std::tuple<size_t, long_t, float>> max_identity;
+        std::set<Idx_t> identities_found;
+        std::set<Idx_t> double_identities;
+        std::map<Idx_t, std::tuple<size_t, Idx_t, float>> max_identity;
         
         for(auto && [id, tup] : _cache) {
             auto & [samples, map] = tup;
             float max_p = 0;
-            long_t max_id = -1;
+            Idx_t max_id;
             for(auto & [id, p] : map) {
-                if(p > max_p) {
+                if(!max_id.valid() || p > max_p) {
                     max_p = p;
                     max_id = id;
                 }
@@ -162,7 +162,7 @@ namespace gui {
             
             max_identity[id] = { samples, max_id, max_p };
             
-            if(max_id != -1) {
+            if(max_id.valid()) {
                 if(identities_found.find(max_id) != identities_found.end()
                    && double_identities.find(max_id) == double_identities.end())
                 {
@@ -173,7 +173,7 @@ namespace gui {
             identities_found.insert(max_id);
         }
         
-        std::map<long_t, std::tuple<float, float>> fish_offset;
+        std::map<Idx_t, std::tuple<float, float>> fish_offset;
         float y = 10, max_w = 0;
         Font font(0.75);
         
@@ -191,7 +191,7 @@ namespace gui {
                 color = Yellow.alpha(200);
             
             Drawable *secondary;
-            if(max_id != -1)
+            if(max_id.valid())
                 secondary = advance(new Text(Meta::toStr(max_id)+" ("+Meta::toStr(max_p)+", "+Meta::toStr(samples)+" samples)", text->pos() + Vec2(text->width(), 0), color, font));
             else
                 secondary = advance(new Text("N/A ("+Meta::toStr(samples)+" samples)", text->pos() + Vec2(text->width(), 0), DarkCyan.brightenHSL(1.5).alpha(200), font));
@@ -278,7 +278,7 @@ namespace gui {
         advance(new Line(Vec2(x - 10, 5), Vec2(x - 10, y + 5), White.alpha(150)));
         
         if(index < _texts.size())
-            _texts.erase(_texts.begin() + index, _texts.end());
+            _texts.erase(_texts.begin() + (int64_t)index, _texts.end());
         
         end();
         
diff --git a/Application/src/tracker/gui/DrawDataset.h b/Application/src/tracker/gui/DrawDataset.h
index b8f5e0d1439642c89952138569799306cfbcbf85..bbbf969c3fbe4ac1591dd6c7885464af806f3a77 100644
--- a/Application/src/tracker/gui/DrawDataset.h
+++ b/Application/src/tracker/gui/DrawDataset.h
@@ -3,6 +3,7 @@
 #include <gui/DrawStructure.h>
 #include <gui/types/Entangled.h>
 #include <tracking/DatasetQuality.h>
+#include <misc/idx_t.h>
 
 namespace gui {
     class DrawDataset : public Entangled {
@@ -10,12 +11,12 @@ namespace gui {
         Rangel _last_consecutive_frames, _last_current_frames;
         track::DatasetQuality::Quality _quality, _current_quality;
         
-        std::map<long_t, std::tuple<size_t, std::map<long_t, float>>> _cache;
-        std::map<long_t, std::string> _names;
+        std::map<track::Idx_t, std::tuple<size_t, std::map<track::Idx_t, float>>> _cache;
+        std::map<track::Idx_t, std::string> _names;
         std::vector<std::shared_ptr<StaticText>> _texts;
         
-        std::map<track::idx_t, track::DatasetQuality::Single> _meta;
-        std::map<track::idx_t, track::DatasetQuality::Single> _meta_current;
+        std::map<track::Idx_t, track::DatasetQuality::Single> _meta;
+        std::map<track::Idx_t, track::DatasetQuality::Single> _meta_current;
         bool _initial_pos_set;
         
     public:
diff --git a/Application/src/tracker/gui/DrawFish.cpp b/Application/src/tracker/gui/DrawFish.cpp
index e35ce051254e45501dfddc692befd6b4bf97c91b..4f221d67a8e9cc2e3a9970d708c5ecb9cabc6a86 100644
--- a/Application/src/tracker/gui/DrawFish.cpp
+++ b/Application/src/tracker/gui/DrawFish.cpp
@@ -39,7 +39,7 @@ CREATE_STRUCT(CachedGUIOptions,
     {
         CachedGUIOptions::init();
         
-        assert(_obj.identity().ID() < std::numeric_limits<idx_t>::max());
+        assert(_obj.identity().ID().valid());
         auto ID = _obj.identity().ID();
         set_clickable(true);
         _circle.set_clickable(true);
@@ -49,7 +49,7 @@ CREATE_STRUCT(CachedGUIOptions,
             GUI::cache().set_tracking_dirty();
         });
         on_click([ID, this](auto) {
-            std::vector<uint32_t> selections = SETTING(gui_focus_group);
+            std::vector<Idx_t> selections = SETTING(gui_focus_group);
 
             if(stage() && !(stage()->is_key_pressed(gui::LShift) || stage()->is_key_pressed(gui::RShift))) {
                 if(!selections.empty() && selections.front() == ID)
diff --git a/Application/src/tracker/gui/DrawFish.h b/Application/src/tracker/gui/DrawFish.h
index 97a3bef9b052210ed9c685072efdc83986122276..1fd0edf158149adef8d42e4d1f213ee1108f8179 100644
--- a/Application/src/tracker/gui/DrawFish.h
+++ b/Application/src/tracker/gui/DrawFish.h
@@ -17,7 +17,7 @@ namespace gui {
         const track::PPFrame* _frame;
         GETTER(long_t, idx)
         long_t _safe_idx;
-        float _time;
+        double _time;
         std::unique_ptr<ExternalImage> _image;
         Midline::Ptr _cached_midline;
         MinimalOutline::Ptr _cached_outline;
diff --git a/Application/src/tracker/gui/DrawMenu.cpp b/Application/src/tracker/gui/DrawMenu.cpp
index 5f85a8c4c5306bca74e5603adf14fa789944ebfb..a1dd54b4e197e73329e9400fa53bf678f4969e59 100644
--- a/Application/src/tracker/gui/DrawMenu.cpp
+++ b/Application/src/tracker/gui/DrawMenu.cpp
@@ -40,17 +40,17 @@ public:
 class ItemIndividual : public gui::List::Item {
 protected:
     GETTER_SETTER(std::string, name)
-    GETTER_SETTER(long_t, ptr)
+    GETTER_SETTER(Idx_t, ptr)
     GETTER_SETTER(long_t, selected_blob_id)
     
 public:
-    ItemIndividual(long_t fish = -1, long_t blob = -1)
+    ItemIndividual(Idx_t fish = Idx_t(), long_t blob = -1)
     : gui::List::Item(fish),
     _ptr(fish),
     _selected_blob_id(blob)
     {
-        if(fish != -1) {
-            Identity id((idx_t)_ptr);
+        if(fish.valid()) {
+            Identity id(_ptr);
             _name = id.name();
         }
     }
@@ -140,7 +140,7 @@ public:
           [this](List*, const List::Item& item) {
               Debug("%d %d", item.ID(), item.selected());
               if(!item.selected() && item.ID() >= 0) {
-                  GUI::instance()->add_manual_match(GUI::instance()->frameinfo().frameIndex, _list->selected_item() >= 0 ? (idx_t)_list->selected_item() : std::numeric_limits<idx_t>::max(), item.ID());
+                  GUI::instance()->add_manual_match(GUI::instance()->frameinfo().frameIndex, _list->selected_item() >= 0 ? Idx_t(_list->selected_item()) : Idx_t(), item.ID());
               }
           }
         );
@@ -286,10 +286,10 @@ public:
              * Try and match the last displayed fish items to the currently existing ones
              */
             struct FishAndBlob {
-                idx_t fish;
+                Idx_t fish;
                 long_t blob;
                 
-                FishAndBlob(idx_t fish = 0, long_t blob = -1) : fish(fish), blob(blob)
+                FishAndBlob(Idx_t fish = Idx_t(), long_t blob = -1) : fish(fish), blob(blob)
                 {}
                 
                 void convert(std::shared_ptr<List::Item> ptr) {
@@ -408,7 +408,7 @@ public:
             tooltip = new Tooltip(nullptr, 300);
         }
         
-        if((overall.id == -1 || memory_timer.elapsed() > 10) && GUI::cache().tracked_frames.end != last_end_frame) {
+        if((!overall.id.valid() || memory_timer.elapsed() > 10) && GUI::cache().tracked_frames.end != last_end_frame) {
             Tracker::LockGuard guard("memory_stats", 100);
             if(guard.locked()) {
                 overall.clear();
diff --git a/Application/src/tracker/gui/GUICache.cpp b/Application/src/tracker/gui/GUICache.cpp
index a51698611f5e5226c307af841fc4a716a1521d20..d0b7b59310f39b8d2cf4cf860f5c5a5a791fa68a 100644
--- a/Application/src/tracker/gui/GUICache.cpp
+++ b/Application/src/tracker/gui/GUICache.cpp
@@ -80,18 +80,18 @@ namespace gui {
         selected.clear();
     }
     
-    bool GUICache::is_selected(uint32_t id) const {
+    bool GUICache::is_selected(Idx_t id) const {
         return contains(selected, id);
     }
     
-    void GUICache::do_select(uint32_t id) {
+    void GUICache::do_select(Idx_t id) {
         if(!is_selected(id)) {
             selected.push_back(id);
             SETTING(gui_focus_group) = selected;
         }
     }
     
-    void GUICache::deselect(uint32_t id) {
+    void GUICache::deselect(Idx_t id) {
         auto it = std::find(selected.begin(), selected.end(), id);
         if(it != selected.end()) {
             selected.erase(it);
@@ -99,7 +99,7 @@ namespace gui {
         }
     }
     
-    void GUICache::deselect_all_select(uint32_t id) {
+    void GUICache::deselect_all_select(Idx_t id) {
         selected.clear();
         selected.push_back(id);
         
@@ -152,7 +152,7 @@ namespace gui {
             
             Tracker::instance()->thread_pool().enqueue([this](){
                 Debug("Percentiles...");
-                auto percentiles = GUI::instance()->video_source()->calculate_percentiles({0.05, 0.95});
+                auto percentiles = GUI::instance()->video_source()->calculate_percentiles({0.05f, 0.95f});
                 
                 if(GUI::instance()) {
                     std::lock_guard<std::recursive_mutex> guard(GUI::instance()->gui().lock());
@@ -178,7 +178,7 @@ namespace gui {
         if(properties) {
             active = _tracker.active_individuals(frameIndex);
             individuals = _tracker.individuals();
-            selected = SETTING(gui_focus_group).value<std::vector<uint32_t>>();
+            selected = SETTING(gui_focus_group).value<std::vector<Idx_t>>();
             active_blobs.clear();
             inactive_ids.clear();
             active_ids.clear();
@@ -189,7 +189,7 @@ namespace gui {
             auto delete_callback = [this](Individual* fish) {
                 std::lock_guard<std::recursive_mutex> guard(GUI::instance()->gui().lock());
                 
-                auto id = narrow_cast<int32_t>(fish->identity().ID());
+                auto id = fish->identity().ID();
                 auto it = individuals.find(id);
                 if(it != individuals.end())
                     individuals.erase(it);
@@ -221,7 +221,7 @@ namespace gui {
             } else {
                 
                 for(auto id : FAST_SETTINGS(manual_identities)) {
-                    auto it = individuals.find((idx_t)id);
+                    auto it = individuals.find(id);
                     if(it != individuals.end()) {
                         it->second->register_delete_callback((void*)12341337, delete_callback);
                     }
@@ -286,7 +286,7 @@ namespace gui {
             } else {
                 // display blobs that are selected
                 for(auto id : selected) {
-                    auto it = individuals.find((idx_t)id);
+                    auto it = individuals.find(id);
                     if(it != individuals.end()) {
                         auto blob = it->second->compressed_blob(frameIndex);
                         if(blob)
@@ -448,7 +448,7 @@ namespace gui {
         }
     }
 
-    bool GUICache::has_probs(uint32_t fdx) {
+    bool GUICache::has_probs(Idx_t fdx) {
         if(checked_probs.find(fdx) != checked_probs.end()) {
             return probabilities.find(fdx) != probabilities.end();
         }
@@ -456,7 +456,7 @@ namespace gui {
         return probs(fdx) != nullptr;
     }
 
-    const std::map<uint32_t, Individual::Probability>* GUICache::probs(uint32_t fdx) {
+    const std::map<uint32_t, Individual::Probability>* GUICache::probs(Idx_t fdx) {
         if(checked_probs.find(fdx) != checked_probs.end()) {
             auto it = probabilities.find(fdx);
             if(it  != probabilities.end())
@@ -472,7 +472,7 @@ namespace gui {
             if(it != processed_frame.cached_individuals.end()) {
                 auto && [fdx, cache] = *it;
                 for(auto blob : processed_frame.blobs) {
-                    auto p = individuals.count((idx_t)fdx) ? individuals.at((idx_t)fdx)->probability(cache, frame_idx, blob) : Individual::Probability{0,0,0,0};
+                    auto p = individuals.count(fdx) ? individuals.at(fdx)->probability(cache, frame_idx, blob) : Individual::Probability{0,0,0,0};
                     if(p.p >= FAST_SETTINGS(matching_probability_threshold))
                         probabilities[fdx][blob->blob_id()] = p;
                 }
diff --git a/Application/src/tracker/gui/GUICache.h b/Application/src/tracker/gui/GUICache.h
index 83e56bbfe34091fd63d31d49b69ccac24ce9527e..87fcf1b0cff6abe7a42d7cd29b697f1483af23bf 100644
--- a/Application/src/tracker/gui/GUICache.h
+++ b/Application/src/tracker/gui/GUICache.h
@@ -28,7 +28,7 @@ namespace gui {
         int last_threshold;
         long_t last_frame;
         Bounds boundary;
-        std::vector<uint32_t> previous_active_fish;
+        std::vector<Idx_t> previous_active_fish;
         std::set<uint32_t> previous_active_blobs, active_blobs;
         Vec2 previous_mouse_position;
         bool _dirty;
@@ -60,16 +60,16 @@ namespace gui {
         
         std::map<uint32_t, long_t> automatic_assignments;
         
-        std::unordered_map<idx_t, Individual*> individuals;
-        std::set<uint32_t> active_ids;
-        std::set<uint32_t> inactive_ids;
-        std::set<uint32_t> recognized_ids;
-        std::map<uint32_t, std::shared_ptr<gui::Circle>> recognition_circles;
-        std::map<uint32_t, Timer> recognition_timer;
+        std::unordered_map<Idx_t, Individual*> individuals;
+        std::set<Idx_t> active_ids;
+        std::set<Idx_t> inactive_ids;
+        std::set<Idx_t> recognized_ids;
+        std::map<Idx_t, std::shared_ptr<gui::Circle>> recognition_circles;
+        std::map<Idx_t, Timer> recognition_timer;
         
         Tracker::set_of_individuals_t _registered_callback;
         
-        std::map<uint32_t, long_t> fish_selected_blobs;
+        std::map<Idx_t, long_t> fish_selected_blobs;
         Tracker::set_of_individuals_t active;
         //std::vector<std::shared_ptr<gui::ExternalImage>> blob_images;
         std::vector<std::shared_ptr<SimpleBlob>> raw_blobs;
@@ -79,7 +79,7 @@ namespace gui {
         std::vector<Vec2> inactive_estimates;
         
     protected:
-        std::map<uint32_t, std::map<uint32_t, Individual::Probability>> probabilities;
+        std::map<Idx_t, std::map<uint32_t, Individual::Probability>> probabilities;
         std::set<uint32_t> checked_probs;
         
     public:
@@ -90,20 +90,20 @@ namespace gui {
         std::vector<float> connectivity_matrix;
         
         PPFrame processed_frame;
-        std::vector<uint32_t> selected;
+        std::vector<Idx_t> selected;
         
     public:
         bool has_selection() const;
         Individual * primary_selection() const;
         void deselect_all();
-        bool is_selected(uint32_t id) const;
-        void do_select(uint32_t id);
+        bool is_selected(Idx_t id) const;
+        void do_select(Idx_t id);
         
-        void deselect(uint32_t id);
-        void deselect_all_select(uint32_t id);
+        void deselect(Idx_t id);
+        void deselect_all_select(Idx_t id);
         
-        const std::map<uint32_t, Individual::Probability>* probs(uint32_t fdx);
-        bool has_probs(uint32_t fdx);
+        const std::map<uint32_t, Individual::Probability>* probs(Idx_t fdx);
+        bool has_probs(Idx_t fdx);
         
         void set_tracking_dirty();
         void set_blobs_dirty();
diff --git a/Application/src/tracker/gui/IdentityHeatmap.cpp b/Application/src/tracker/gui/IdentityHeatmap.cpp
index 38943f6131d73ce38add4f7b147bf53ed0d9b0ce..5a16dbcede967519a764e46c2ecee219f29045ea 100644
--- a/Application/src/tracker/gui/IdentityHeatmap.cpp
+++ b/Application/src/tracker/gui/IdentityHeatmap.cpp
@@ -429,7 +429,7 @@ HeatmapController::UpdatedStats HeatmapController::update_data(long_t current_fr
             
             auto &range = updated.add_range;
             for(auto [id, fish] : Tracker::individuals()) {
-                auto frame = max(Tracker::start_frame(), range.start);
+                auto frame = max((long_t)Tracker::start_frame(), range.start);
                 if(fish->end_frame() < frame)
                     continue;
                 if(fish->start_frame() > range.end)
@@ -472,7 +472,7 @@ HeatmapController::UpdatedStats HeatmapController::update_data(long_t current_fr
 //                            Debug("Cannot find segment for frame %d in fish %d", frame, fish->identity().ID());
                 Output::Library::LibInfo info(fish, _mods);
                 
-                for(; frame < min(Tracker::end_frame(), range.end); ++frame) {
+                for(; frame < min((long_t)Tracker::end_frame(), range.end); ++frame) {
                     if(_grid.root()->frame_range().contains(frame))
                         continue;
                     //break;
@@ -500,7 +500,7 @@ HeatmapController::UpdatedStats HeatmapController::update_data(long_t current_fr
                     
                     auto bid = (*kit)->basic_stuff(frame);
                     if(bid != -1) {
-                        auto &basic = fish->basic_stuff()[bid];
+                        auto &basic = fish->basic_stuff()[(uint32_t)bid];
                         auto pos = basic->centroid->pos(Units::PX_AND_SECONDS);
                         //auto speed = basic->centroid->speed(Units::PX_AND_SECONDS);
                         
diff --git a/Application/src/tracker/gui/InfoCard.cpp b/Application/src/tracker/gui/InfoCard.cpp
index 1ef73008bb2be1fa9d369c5d47e55bd6cf1b3114..ea9b4820e9fc285f47b8d44ab6ceb94f6bf2f391 100644
--- a/Application/src/tracker/gui/InfoCard.cpp
+++ b/Application/src/tracker/gui/InfoCard.cpp
@@ -296,7 +296,7 @@ void InfoCard::update() {
         
         auto blob_id = _fish->compressed_blob(_frameNr)->blob_id();
         auto && [valid, segment] = _fish->has_processed_segment(_frameNr);
-        std::map<long_t, float> raw;
+        std::map<Idx_t, float> raw;
         std::string title = "recognition";
         
         if(valid) {
diff --git a/Application/src/tracker/gui/RecognitionSummary.cpp b/Application/src/tracker/gui/RecognitionSummary.cpp
index 24cbcbc75e72ab5b6524e14fe83878cdc69a5635..f4f005f04119a84fc546f6a5aad0b3128c46ff93 100644
--- a/Application/src/tracker/gui/RecognitionSummary.cpp
+++ b/Application/src/tracker/gui/RecognitionSummary.cpp
@@ -17,7 +17,7 @@ namespace gui {
         Font bottom_font(0.8f / interface_scale, Align::Center);
         
         auto manual_identities = FAST_SETTINGS(manual_identities);
-        std::set<uint32_t> sorted(manual_identities.begin(), manual_identities.end());
+        std::set<Idx_t> sorted(manual_identities.begin(), manual_identities.end());
         for(auto id : manual_identities) {
             if(cache.individuals.find(id) == cache.individuals.end())
                 sorted.erase(id);
@@ -49,7 +49,7 @@ namespace gui {
                 base.advance(new Text("recognition summary", Vec2(obj.width() * 0.5f, margin + (title_height - margin) * 0.5f), White, title_font));
                 
                 size_t counter = 0, j = 0;
-                std::map<long_t, size_t> fdx_to_idx;
+                std::map<Idx_t, size_t> fdx_to_idx;
                 std::map<size_t, long_t> idx_to_fdx;
                 
                 outputs.resize(output_size * sorted.size());
diff --git a/Application/src/tracker/gui/Timeline.cpp b/Application/src/tracker/gui/Timeline.cpp
index 39c3b2dba921ad483bcc77c86ca10d463f0e19e9..74330b6cd20920f25119c63551c07cb1a49b8b39 100644
--- a/Application/src/tracker/gui/Timeline.cpp
+++ b/Application/src/tracker/gui/Timeline.cpp
@@ -30,11 +30,11 @@ namespace gui {
         _visible(true),
         _mOverFrame(-1),
         _title_layout({}, Vec2(20, 20), Bounds(0, 0, 17, 0)),
-        _status_text("", Vec2(), White, 0.8),
-        _status_text2("", Vec2(), White, 0.8),
-        _status_text3("", Vec2(), White, 0.8),
-        _raw_text("[RAW]", Vec2(), Black, Font(0.8, Style::Bold)),
-        _auto_text("", Vec2(), Black, Font(0.8, Style::Bold)),
+        _status_text("", Vec2(), White, 0.8f),
+        _status_text2("", Vec2(), White, 0.8f),
+        _status_text3("", Vec2(), White, 0.8f),
+        _raw_text("[RAW]", Vec2(), Black, Font(0.8f, Style::Bold)),
+        _auto_text("", Vec2(), Black, Font(0.8f, Style::Bold)),
         _pause("pause", Size2(100,27))
     {
         _instance = this;
@@ -83,7 +83,7 @@ void Timeline::update_consecs(float max_w, const Range<long_t>& consec, const st
     static Range<long_t> previous_consec(-1, -1);
     static std::vector<Rangel> previous_other_consec = {};
     static float previous_scale = 0;
-    const double scale = max(1, min(_scale, CV_MAX_THICKNESS));
+    const float scale = max(1, min(_scale, CV_MAX_THICKNESS));
     float new_height = roundf(bar_height) + 5 * scale;
     
     if(consec == previous_consec
@@ -221,7 +221,7 @@ void Timeline::update_consecs(float max_w, const Range<long_t>& consec, const st
             consec_color = Green;
         
         if(_status_text2.hovered())
-            consec_color = consec_color.brightenHSL(0.9);
+            consec_color = consec_color.brightenHSL(0.9f);
         _status_text2.set_color(consec_color);
         
         _status_text2.set_txt(number.str());
@@ -289,14 +289,14 @@ void Timeline::update_consecs(float max_w, const Range<long_t>& consec, const st
             base.wrap_object(*_bar);
             
             if(FAST_SETTINGS(recognition_enable)) {
-                update_consecs(max_w, consec, other_consec, use_scale.y * 0.75);
+                update_consecs(max_w, consec, other_consec, use_scale.y * 0.75f);
                 if(_consecutives) {
-                    _consecutives->set_pos(pos - Vec2(0,5) * max(1, use_scale.y * 0.75));
+                    _consecutives->set_pos(pos - Vec2(0,5) * max(1, use_scale.y * 0.75f));
                     base.wrap_object(*_consecutives);
                 }
             }
             
-            base.add_object(new Text(Meta::toStr(tracker_endframe.load()), pos + Vec2(max_w * tracker_endframe / float(_frame_info.video_length) + 5, bar_height * 0.5), Black, Font(0.5), Vec2(1), Vec2(0,0.5)));
+            base.add_object(new Text(Meta::toStr(tracker_endframe.load()), pos + Vec2(max_w * tracker_endframe / float(_frame_info.video_length) + 5, bar_height * 0.5f), Black, Font(0.5), Vec2(1), Vec2(0,0.5)));
             
             // display hover sign with frame number
             if(_mOverFrame != -1) {
@@ -304,19 +304,19 @@ void Timeline::update_consecs(float max_w, const Range<long_t>& consec, const st
                 //if(it != _proximity_bar.changed_frames.end() || _mOverFrame >= _proximity_bar.end)
                 {
                     std::string t = "Frame "+std::to_string(_mOverFrame);
-                    auto dims = Base::text_dimensions(t, &_title_layout, Font(0.7));
+                    auto dims = Base::text_dimensions(t, &_title_layout, Font(0.7f));
                     
-                    Vec2 pp(max_w / float(_frame_info.video_length) * _mOverFrame, _bar->pos().y + _bar->global_bounds().height / use_scale.y + dims.height * 0.5 + 2);
+                    Vec2 pp(max_w / float(_frame_info.video_length) * _mOverFrame, _bar->pos().y + _bar->global_bounds().height / use_scale.y + dims.height * 0.5f + 2);
                     
-                    if(pp.x < dims.width * 0.5)
-                        pp.x = dims.width * 0.5;
-                    if(pp.x + dims.width * 0.5 > max_w)
-                        pp.x = max_w - dims.width * 0.5;
+                    if(pp.x < dims.width * 0.5f)
+                        pp.x = dims.width * 0.5f;
+                    if(pp.x + dims.width * 0.5f > max_w)
+                        pp.x = max_w - dims.width * 0.5f;
                     
                     pp -= offset;
                     
-                    base.rect(pp - dims * 0.5 - Vec2(5, 2), dims + Vec2(10, 4), Black.alpha(125));
-                    base.text(t, pp, gui::White, Font(0.7, Align::Center));
+                    base.rect(pp - dims * 0.5f - Vec2(5, 2), dims + Vec2(10, 4), Black.alpha(125));
+                    base.text(t, pp, gui::White, Font(0.7f, Align::Center));
                 }
             }
         }
@@ -385,7 +385,7 @@ void Timeline::update_consecs(float max_w, const Range<long_t>& consec, const st
                         //Vec2 pp(max_w / float(_frame_info.video_length) * idx.first, 50);
                         //float dis = abs(e.hover.x - pp.x);
                         static Timing timing("Scrubbing", 0.01);
-                        long_t idx = roundf(e.hover.x / max_w_ * float(_frame_info.video_length));
+                        int64_t idx = roundf(e.hover.x / max_w_ * float(_frame_info.video_length));
                         auto it = _proximity_bar.changed_frames.find(idx);
                         if(it != _proximity_bar.changed_frames.end()) {
                             framemOver = idx;
@@ -707,7 +707,7 @@ void Timeline::update_consecs(float max_w, const Range<long_t>& consec, const st
         }
     }
     
-    void Timeline::next_poi(long_t _s_fdx) {
+    void Timeline::next_poi(Idx_t _s_fdx) {
         auto frame = GUI::frame();
         long_t next_frame = frame;
         std::set<FOI::fdx_t> fdx;
@@ -715,7 +715,7 @@ void Timeline::update_consecs(float max_w, const Range<long_t>& consec, const st
         {
             std::lock_guard<std::mutex> guard(_proximity_bar.mutex);
             for(auto && [idx, number] : _proximity_bar.changed_frames) {
-                if(_s_fdx != -1) {
+                if(_s_fdx.valid()) {
                     if(number.find(FOI::fdx_t(_s_fdx)) == number.end())
                         continue;
                 }
@@ -731,20 +731,20 @@ void Timeline::update_consecs(float max_w, const Range<long_t>& consec, const st
         if(frame != next_frame) {
             SETTING(gui_frame) = next_frame;
             
-            if(_s_fdx == -1) {
+            if(_s_fdx.valid()) {
                 auto &cache = GUI::instance()->cache();
                 if(!fdx.empty()) {
                     cache.deselect_all();
                     for(auto id : fdx) {
-                        if(!cache.is_selected(id.id))
-                            cache.do_select(id.id);
+                        if(!cache.is_selected(Idx_t(id.id)))
+                            cache.do_select(Idx_t(id.id));
                     }
                 }
             }
         }
     }
     
-    void Timeline::prev_poi(long_t _s_fdx) {
+    void Timeline::prev_poi(Idx_t _s_fdx) {
         auto frame = GUI::frame();
         long_t next_frame = frame;
         std::set<FOI::fdx_t> fdx;
@@ -752,7 +752,7 @@ void Timeline::update_consecs(float max_w, const Range<long_t>& consec, const st
         {
             std::lock_guard<std::mutex> guard(_proximity_bar.mutex);
             for(auto && [idx, number] : MakeReverse(_proximity_bar.changed_frames)) {
-                if(_s_fdx != -1) {
+                if(_s_fdx.valid()) {
                     if(number.find(FOI::fdx_t(_s_fdx)) == number.end())
                         continue;
                 }
@@ -768,13 +768,13 @@ void Timeline::update_consecs(float max_w, const Range<long_t>& consec, const st
         if(frame != next_frame && next_frame != -1) {
             SETTING(gui_frame) = next_frame;
             
-            if(_s_fdx == -1) {
+            if(_s_fdx.valid()) {
                 auto &cache = GUI::instance()->cache();
                 if(!fdx.empty()) {
                     cache.deselect_all();
                     for(auto id : fdx) {
-                        if(!cache.is_selected(id.id))
-                            cache.do_select(id.id);
+                        if(!cache.is_selected(Idx_t(id.id)))
+                            cache.do_select(Idx_t(id.id));
                     }
                 }
             }
diff --git a/Application/src/tracker/gui/Timeline.h b/Application/src/tracker/gui/Timeline.h
index 6d11eece5c81c8355d917013d5062377f10d06ce..0035552d463f0c409cf0b7e0e6b36473760a2f7d 100644
--- a/Application/src/tracker/gui/Timeline.h
+++ b/Application/src/tracker/gui/Timeline.h
@@ -106,8 +106,8 @@ namespace gui {
         void update_thread();
         void reset_events(long_t after_frame = -1);
         //void update_border();
-        void next_poi(long_t fdx = -1);
-        void prev_poi(long_t fdx = -1);
+        void next_poi(Idx_t fdx = Idx_t());
+        void prev_poi(Idx_t fdx = Idx_t());
         static std::tuple<Vec2, float> timeline_offsets();
         
     private:
diff --git a/Application/src/tracker/gui/gui.cpp b/Application/src/tracker/gui/gui.cpp
index 2d4f86eecf48b5cdc96f7144c7455c3fe9d50b4a..f01c2673c3bcb7664607f02d824a95f900470ddb 100644
--- a/Application/src/tracker/gui/gui.cpp
+++ b/Application/src/tracker/gui/gui.cpp
@@ -611,7 +611,7 @@ void GUI::run_loop(gui::DrawStructure&) {
         
         if(inc >= 1) {
             auto before = image_index;
-            image_index = min(_tracker.end_frame(), image_index + inc);
+            image_index = min((float)_tracker.end_frame(), image_index + inc);
             
             t = 0;
             if(before != image_index) {
@@ -1687,30 +1687,30 @@ std::tuple<Vec2, Vec2> GUI::gui_scale_with_boundary(Bounds& boundary, Section* s
 #ifndef NDEBUG
         Debug("target_pos.x = %f target_scale.x = %f", target_pos.x, target_scale.x);
 #endif
-        target_pos.x = -mw * target_scale.x * 0.95;
+        target_pos.x = -mw * target_scale.x * 0.95f;
     }
-    if(target_pos.y / target_scale.y < -mh * 0.95)
-        target_pos.y = -mh * target_scale.y * 0.95;
+    if(target_pos.y / target_scale.y < -mh * 0.95f)
+        target_pos.y = -mh * target_scale.y * 0.95f;
     
-    if(target_pos.x / target_scale.x > mw * 0.95) {
+    if(target_pos.x / target_scale.x > mw * 0.95f) {
 #ifndef NDEBUG
         Debug("target_pos.x = %f target_scale.x = %f screen_center.x = %f screen_dimensions.x = %f window_dimensions.x = %f", target_pos.x, target_scale.x, screen_center.width, screen_dimensions.width, base()->window_dimensions().width);
 #endif
-        target_pos.x = mw * target_scale.x * 0.95;
+        target_pos.x = mw * target_scale.x * 0.95f;
     }
-    if(target_pos.y / target_scale.y > mh * 0.95)
-        target_pos.y = mh * target_scale.y * 0.95;
+    if(target_pos.y / target_scale.y > mh * 0.95f)
+        target_pos.y = mh * target_scale.y * 0.95f;
     
     _cache.set_zoom_level(target_scale.x);
     
     static Timer timer;
-    float e = _recording ? cache().dt() : timer.elapsed(); //_recording ? (1 / float(FAST_SETTINGS(frame_rate))) : timer.elapsed();
+    auto e = _recording ? cache().dt() : timer.elapsed(); //_recording ? (1 / float(FAST_SETTINGS(frame_rate))) : timer.elapsed();
     //e = cache().dt();
     
     e = min(0.1, e);
     e *= 3;
     
-    auto check_target = [](const Vec2& start, const Vec2& target, float e) {
+    auto check_target = [](const Vec2& start, const Vec2& target, double e) {
         Vec2 direction = target - start;
         double speed = direction.length();
         if(speed > 0)
@@ -1803,7 +1803,7 @@ void GUI::label_fish(gui::DrawStructure &base, track::Individual *fish, long_t f
         //L = SQR(L) * 0.5;
         
         auto text_offset = Vec2(0, Base::default_line_spacing(font));
-        auto offset_from_blob = blob->calculate_bounds().height * 0.25;
+        auto offset_from_blob = blob->calculate_bounds().height * 0.25f;
         auto line_start = offset_from_blob;
         auto line_end = L + line_start;
         text_pos = blob_center - factor * (line_end + Base::default_line_spacing(Font(0.5f)));
@@ -2077,7 +2077,7 @@ void GUI::draw_tracking(DrawStructure& base, long_t frameNr, bool draw_graph) {
                         std::vector<std::vector<float>> all;
                         std::vector<float> lengths;
                         
-                        std::map<track::idx_t, Individual*> search;
+                        std::map<track::Idx_t, Individual*> search;
                         
                         if(FAST_SETTINGS(manual_identities).empty()) {
                             for(auto fish : _cache.active) {
@@ -2152,14 +2152,14 @@ void GUI::draw_tracking(DrawStructure& base, long_t frameNr, bool draw_graph) {
                     _cache.connectivity_reload = false;
                     _cache.connectivity_last_frame = frameIndex;
                     
-                    const idx_t number_fish = FAST_SETTINGS(track_max_individuals);
-                    for (idx_t i=0; i<number_fish; ++i) {
-                        if(!_cache.individuals.count(i)) {
+                    const auto number_fish = FAST_SETTINGS(track_max_individuals);
+                    for (uint32_t i=0; i<number_fish; ++i) {
+                        if(!_cache.individuals.count(Idx_t(i))) {
                             Except("Individuals seem to be named differently than 0-%d. Cannot find %d.", FAST_SETTINGS(track_max_individuals), i);
                             continue;
                         }
                         
-                        auto fish0 = _cache.individuals.at(i);
+                        auto fish0 = _cache.individuals.at(Idx_t(i));
                         Vec2 p0(infinity<Float2_t>());
                         
                         if(!fish0->has(frameIndex)) {
@@ -2174,13 +2174,13 @@ void GUI::draw_tracking(DrawStructure& base, long_t frameNr, bool draw_graph) {
                         if(cmn::isinf(p0.x))
                             continue;
                         
-                        for(idx_t j=i+1; j<number_fish; ++j) {
-                            if(!_cache.individuals.count(j)) {
+                        for(uint32_t j=i+1; j<number_fish; ++j) {
+                            if(!_cache.individuals.count(Idx_t(j))) {
                                 Except("Individuals seem to be named differently than 0-%d. Cannot find %d.", FAST_SETTINGS(track_max_individuals), j);
                                 continue;
                             }
                             
-                            auto fish1 = _cache.individuals.at(j);
+                            auto fish1 = _cache.individuals.at(Idx_t(j));
                             Vec2 p1(infinity<Float2_t>());
                             
                             if(!fish1->has(frameIndex)) {
@@ -2255,7 +2255,7 @@ void GUI::draw_tracking(DrawStructure& base, long_t frameNr, bool draw_graph) {
         if(SETTING(gui_show_uniqueness)) {
             static Graph graph(Bounds(50, 100, 800, 400), "uniqueness");
             static std::mutex mutex;
-            static std::map<uint32_t, float> estimated_uniqueness;
+            static std::map<Frame_t, float> estimated_uniqueness;
             static std::vector<Vec2> uniquenesses;
             static bool running = false;
             
@@ -2311,7 +2311,7 @@ void GUI::draw_tracking(DrawStructure& base, long_t frameNr, bool draw_graph) {
                     if(graph.empty()) {
                         graph.add_function(Graph::Function("raw", Graph::Type::DISCRETE, [uq = &estimated_uniqueness](float x) -> float {
                             std::lock_guard<std::mutex> guard(mutex);
-                            auto it = uq->upper_bound(x);
+                            auto it = uq->upper_bound(Frame_t(narrow_cast<long_t>(x)));
                             if(!uq->empty() && it != uq->begin())
                                 --it;
                             if(it != uq->end() && it->second <= x) {
@@ -3722,7 +3722,7 @@ void GUI::debug_binary(DrawStructure &base, long_t frameIndex) {
                             SETTING(manual_splits) = copy;
                         });
                     } else {
-                        auto it = _cache.individuals.find(item.ID() - 1);
+                        auto it = _cache.individuals.find(Idx_t(item.ID() - 1));
                         if(it != _cache.individuals.end()) {
                             auto fish = it->second;
                             auto id = it->first;
@@ -3928,7 +3928,7 @@ void GUI::key_event(const gui::Event &event) {
     if(key.code >= Codes::Num0 && key.code <= Codes::Num9) {
         std::lock_guard<std::recursive_mutex> lock(_gui.lock());
         Identity id(int(key.code - Codes::Num0));
-        SETTING(gui_focus_group) = std::vector<uint32_t>{id.ID()};
+        SETTING(gui_focus_group) = std::vector<Idx_t>{id.ID()};
         set_redraw();
         return;
     }
@@ -3943,8 +3943,8 @@ void GUI::key_event(const gui::Event &event) {
             if(!cache._current_foi.foi.fdx().empty()) {
                 cache.deselect_all();
                 for(auto id : cache._current_foi.foi.fdx()) {
-                    if(!cache.is_selected(id.id))
-                        cache.do_select(id.id);
+                    if(!cache.is_selected(Idx_t(id.id)))
+                        cache.do_select(Idx_t(id.id));
                 }
             }
         }
@@ -4109,7 +4109,7 @@ void GUI::key_event(const gui::Event &event) {
             } else
                 break;
             
-            SETTING(gui_focus_group) = std::vector<uint32_t>{id.ID()};
+            SETTING(gui_focus_group) = std::vector<Idx_t>{id.ID()};
             
             break;
         }
@@ -4134,7 +4134,7 @@ void GUI::key_event(const gui::Event &event) {
             } else
                 break;
             
-            SETTING(gui_focus_group) = std::vector<uint32_t>{id.ID()};
+            SETTING(gui_focus_group) = std::vector<Idx_t>{id.ID()};
             
             break;
         }
@@ -4194,8 +4194,8 @@ void GUI::key_event(const gui::Event &event) {
                     if(!cache._current_foi.foi.fdx().empty()) {
                         cache.deselect_all();
                         for(auto id : cache._current_foi.foi.fdx()) {
-                            if(!cache.is_selected(id.id))
-                                cache.do_select(id.id);
+                            if(!cache.is_selected(Idx_t(id.id)))
+                                cache.do_select(Idx_t(id.id));
                         }
                     }
                 }
@@ -5053,7 +5053,7 @@ void GUI::generate_training_data_faces(const file::Path& path) {
     }
 }
 
-void GUI::add_manual_match(long_t frameIndex, idx_t fish_id, long_t blob_id) {
+void GUI::add_manual_match(long_t frameIndex, Idx_t fish_id, long_t blob_id) {
     Debug("Requesting change of fish %d to blob %d in frame %d", fish_id, blob_id, frameIndex);
     
     auto matches = FAST_SETTINGS(manual_matches);
diff --git a/Application/src/tracker/gui/gui.h b/Application/src/tracker/gui/gui.h
index c966c27a3875975e021783d0d4f4136539e0f4b4..cf96bed41af829e7806a11dcbe76602dd76bce96 100644
--- a/Application/src/tracker/gui/gui.h
+++ b/Application/src/tracker/gui/gui.h
@@ -266,7 +266,7 @@ private:
     std::map<long_t, long_t> check_additional_range(const Rangel& range, TrainingData& data);
     
 public:
-    void add_manual_match(long_t frameIndex, idx_t fish_id, long_t blob_id);
+    void add_manual_match(long_t frameIndex, Idx_t fish_id, long_t blob_id);
     
 private:
     void selected_setting(long_t index, const std::string& name, gui::Textfield& textfield, gui::Dropdown& settings_dropdown, gui::Layout& layout, gui::DrawStructure& base);
diff --git a/Application/src/tracker/main.cpp b/Application/src/tracker/main.cpp
index 1ce40a270f33c133d41c93f9d2c33d0dd6c75de8..6752dbd4363804727cdc86a869772edfcfa6d54d 100644
--- a/Application/src/tracker/main.cpp
+++ b/Application/src/tracker/main.cpp
@@ -936,11 +936,11 @@ int main(int argc, char** argv)
     
     Tracker::auto_calculate_parameters(video);
     
-    if(SETTING(manual_identities).value<std::set<uint32_t>>().empty() && SETTING(track_max_individuals).value<uint32_t>() != 0)
+    if(SETTING(manual_identities).value<std::set<track::Idx_t>>().empty() && SETTING(track_max_individuals).value<uint32_t>() != 0)
     {
-        std::set<uint32_t> vector;
+        std::set<track::Idx_t> vector;
         for(uint32_t i=0; i<SETTING(track_max_individuals).value<uint32_t>(); ++i) {
-            vector.insert(i);
+            vector.insert(track::Idx_t(i));
         }
         SETTING(manual_identities) = vector;
     }
@@ -1131,7 +1131,7 @@ int main(int argc, char** argv)
     analysis = std::make_shared<ConnectedTasks>(tasks);
     analysis->start(// main thread
         [&]() {
-            auto endframe = tracker.end_frame();
+            auto endframe = (long_t)tracker.end_frame();
             if(currentID > endframe + cache_size
                || currentID == -1
                || (analysis->stage_empty(0) && analysis->stage_empty(1))
diff --git a/Application/src/tracker/misc/MemoryStats.cpp b/Application/src/tracker/misc/MemoryStats.cpp
index 882a08230651422e9d2a178c0deb46321f020677..3b92a821930284f4d984229b93d3590f33413701 100644
--- a/Application/src/tracker/misc/MemoryStats.cpp
+++ b/Application/src/tracker/misc/MemoryStats.cpp
@@ -5,6 +5,10 @@
 
 namespace mem {
 
+uint64_t memory_selector(MemoryStats& stats, const Idx_t& obj, const std::string& name) {
+    return sizeof(Idx_t);
+}
+
 template <typename K, typename V>
 uint64_t memory_selector(MemoryStats& stats, const std::map<K, V>& map, const std::string& name) {
     //using map_t = typename remove_cvref<decltype(map)>::type;
@@ -227,7 +231,7 @@ TrackerMemoryStats::TrackerMemoryStats() {
     sizes["fois"] = foi_bytes;
     bytes += foi_bytes;
     
-    id = -2;
+    id = Idx_t(std::numeric_limits<uint32_t>::max()-1);
 }
 
 IndividualMemoryStats::IndividualMemoryStats(Individual *fish) {
@@ -306,7 +310,7 @@ OutputLibraryMemoryStats::OutputLibraryMemoryStats(Output::LibraryCache::Ptr ptr
     }
     bytes += sizeof(decltype(cache)::element_type);
     
-    id = -2;
+    id = Idx_t(std::numeric_limits<uint32_t>::max()-1);
 }
 
 void IndividualMemoryStats::print() const {
@@ -336,7 +340,7 @@ void MemoryStats::print() const {
     
     auto str = prettify_array(Meta::toStr(vec));
     auto overall = Meta::toStr(FileSize{bytes});
-    auto id_str = id == -2 ? std::string("overall") : (id == -1 ? "<empty>" : Meta::toStr(id));
+    auto id_str = id == Idx_t(std::numeric_limits<uint32_t>::max()-1) ? std::string("overall") : (!id.valid() ? "<empty>" : Meta::toStr(id));
     
     Debug("%S: %S\n%S", &id_str, &overall, &str);
 }
diff --git a/Application/src/tracker/misc/MemoryStats.h b/Application/src/tracker/misc/MemoryStats.h
index 9ab7b5db10af98a56045edcc640e50e6f5890a99..f9ec704e213284a266b1f1ff982aa72040892cd0 100644
--- a/Application/src/tracker/misc/MemoryStats.h
+++ b/Application/src/tracker/misc/MemoryStats.h
@@ -3,6 +3,7 @@
 #include <types.h>
 #include <tracking/Individual.h>
 #include <misc/OutputLibrary.h>
+#include <misc/idx_t.h>
 
 namespace mem {
 using namespace track;
@@ -10,7 +11,7 @@ using namespace track;
 struct MemoryStats {
     MemoryStats();
     
-    idx_t id;
+    Idx_t id;
     uint64_t bytes;
     std::map<std::string, uint64_t> sizes;
     std::map<std::string, std::map<std::string, uint64_t>> details;
@@ -21,7 +22,7 @@ struct MemoryStats {
     }
     
     void operator +=(const MemoryStats& other) {
-        if(id == -1) {
+        if(!id.valid()) {
             *this = other;
             return;
         }
@@ -37,12 +38,12 @@ struct MemoryStats {
             }
         }
         
-        id = -2;
+        id = Idx_t(std::numeric_limits<uint32_t>::max()-1);
     }
     
     void clear() {
         bytes = 0;
-        id = -1;
+        id = Idx_t();
         sizes.clear();
     }
     virtual void print() const;
diff --git a/Application/src/tracker/misc/Output.cpp b/Application/src/tracker/misc/Output.cpp
index fc09645b8676e1761c8fade9c13709c8a2342e19..4e5477358684c29ad657b0b8d6fdb385f38e6ce0 100644
--- a/Application/src/tracker/misc/Output.cpp
+++ b/Application/src/tracker/misc/Output.cpp
@@ -1036,7 +1036,7 @@ namespace Output {
         return pack_size;
     }
     
-    void ResultsFormat::write_file(const std::vector<track::FrameProperties> &frames, const std::unordered_map<long_t, Tracker::set_of_individuals_t > &active_individuals_frame, const std::unordered_map<idx_t, Individual *> &individuals, const std::vector<std::string>& exclude_settings)
+    void ResultsFormat::write_file(const std::vector<track::FrameProperties> &frames, const std::unordered_map<long_t, Tracker::set_of_individuals_t > &active_individuals_frame, const std::unordered_map<Idx_t, Individual *> &individuals, const std::vector<std::string>& exclude_settings)
     {
         estimated_size = sizeof(uint64_t)*3 + frames.size() * (sizeof(data_long_t)+sizeof(CompatibilityFrameProperties)) + active_individuals_frame.size() * (sizeof(data_long_t)+sizeof(uint64_t)+(active_individuals_frame.empty() ? individuals.size() : active_individuals_frame.begin()->second.size())*sizeof(data_long_t));
         
@@ -1166,7 +1166,7 @@ void TrackingResults::update_fois(const std::function<void(const std::string&, f
     const track::FrameProperties* prev_props = nullptr;
     data_long_t prev_frame = -1;
     
-    std::unordered_map<long_t, Individual::segment_map::const_iterator> iterator_map;
+    std::unordered_map<Idx_t, Individual::segment_map::const_iterator> iterator_map;
     
     for(const auto &props : _tracker._added_frames) {
         prev_time = props.time;
@@ -1338,7 +1338,7 @@ void TrackingResults::update_fois(const std::function<void(const std::string&, f
                 if(biggest_id < fish->identity().ID())
                     biggest_id = fish->identity().ID();
                 map_id_ptr[fish->identity().ID()] = fish;
-                _tracker._individuals[(long_t)fish->identity().ID()] = fish;
+                _tracker._individuals[fish->identity().ID()] = fish;
             }
         }
         
@@ -1429,9 +1429,9 @@ void TrackingResults::update_fois(const std::function<void(const std::string&, f
             }
             
             if(config.has("gui_focus_group")) {
-                SETTING(gui_focus_group) = config["gui_focus_group"].value<std::vector<uint32_t>>();
+                SETTING(gui_focus_group) = config["gui_focus_group"].value<std::vector<Idx_t>>();
             } else
-                SETTING(gui_focus_group) = std::vector<uint32_t>{};
+                SETTING(gui_focus_group) = std::vector<Idx_t>{};
             
             SETTING(gui_frame).value<long_t>() = (long_t)file.header().gui_frame;
         }
diff --git a/Application/src/tracker/misc/Output.h b/Application/src/tracker/misc/Output.h
index 4a33e9277bb7380c2de58b472387bed2b7386d3b..6591193d3e0c91e2b73cab1fe1fdba9fecf513e0 100644
--- a/Application/src/tracker/misc/Output.h
+++ b/Application/src/tracker/misc/Output.h
@@ -152,7 +152,7 @@ namespace Output {
         uint64_t write_data(uint64_t num_bytes, const char* buffer) override;
         
         static uint64_t estimate_individual_size(const Individual& val);
-        void write_file(const std::vector<track::FrameProperties>& frames, const std::unordered_map<long_t, Tracker::set_of_individuals_t>& active_individuals_frame, const std::unordered_map<idx_t, Individual*>& individuals, const std::vector<std::string>& exclude_settings);
+        void write_file(const std::vector<track::FrameProperties>& frames, const std::unordered_map<long_t, Tracker::set_of_individuals_t>& active_individuals_frame, const std::unordered_map<Idx_t, Individual*>& individuals, const std::vector<std::string>& exclude_settings);
         
         Individual* read_individual(Data& ref, const CacheHints* cache);
         Midline::Ptr read_midline(Data& ref);
diff --git a/Application/src/tracker/misc/default_config.cpp b/Application/src/tracker/misc/default_config.cpp
index fbcd2854b49804fb4f9450b38da66e3781444c46..14adffcf2e4e11421d3b266760d9e821c3d21717 100644
--- a/Application/src/tracker/misc/default_config.cpp
+++ b/Application/src/tracker/misc/default_config.cpp
@@ -2,6 +2,7 @@
 #include <misc/SpriteMap.h>
 #include <file/Path.h>
 #include <misc/BlobSizeRange.h>
+#include <misc/idx_t.h>
 #include "GitSHA1.h"
 
 #ifndef WIN32
@@ -238,7 +239,7 @@ file::Path conda_environment_path() {
         Adding adding(config, docs, fn);
         
         CONFIG<std::string>("app_name", "TRex", "Name of the application.", SYSTEM);
-        CONFIG("version", std::string("1.0.4"), "Current application version.", SYSTEM);
+        CONFIG("version", std::string("1.0.5"), "Current application version.", SYSTEM);
         CONFIG("build_type", std::string(g_TREX_BUILD_TYPE), "The mode the application was built in.", SYSTEM);
         CONFIG("build_is_debug", std::string(is_ndebug_enabled()), "If built in debug mode, this will show 'debug'.", SYSTEM);
         CONFIG("build_cxx_options", std::string(g_TREX_BUILD_CXX_OPTIONS), "The mode the application was built in.", SYSTEM);
@@ -370,7 +371,7 @@ file::Path conda_environment_path() {
         CONFIG("midline_start_with_head", false, "If enabled, the midline is going to be estimated starting at the head instead of the tail.");
         CONFIG("midline_invert", false, "If enabled, all midlines will be inverted (tail/head swapped).");
         CONFIG("peak_mode", peak_mode_t::pointy, "This determines whether the tail of an individual should be expected to be pointy or broad.");
-        CONFIG("manual_matches", std::map<long_t, std::map<idx_t, int64_t>>{ }, "A map of manually defined matches (also updated by GUI menu for assigning manual identities). {{frame: {fish0: blob2, fish1: blob0}}, ...}");
+        CONFIG("manual_matches", std::map<long_t, std::map<track::Idx_t, int64_t>>{ }, "A map of manually defined matches (also updated by GUI menu for assigning manual identities). {{frame: {fish0: blob2, fish1: blob0}}, ...}");
         CONFIG("manual_splits", std::map<long_t, std::set<int64_t>>{}, "This map contains {frame: [blobid1,blobid2,...]} where frame and blobid are integers. When this is read during tracking for a frame, the tracker will attempt to force-split the given blob ids.");
         CONFIG("match_mode", matching_mode_t::accurate, "Changes the default algorithm to be used for matching blobs in one frame to blobs in the next frame. The accurate algorithm performs best, but also scales less well for more individuals than the approximate one. However, if it is too slow (temporarily) in a few frames, the program falls back to using the approximate one that doesnt slow down.");
         CONFIG("matching_probability_threshold", float(0.1), "The probability below which a possible connection between blob and identity is considered too low. The probability depends largely upon settings like `track_max_speed`.");
@@ -399,7 +400,7 @@ file::Path conda_environment_path() {
         CONFIG("enable_absolute_difference", true, "If set to true, the threshold values will be applied to abs(image - background). Otherwise max(0, image - background).");
         CONFIG("track_time_probability_enabled", bool(true), "");
         CONFIG("track_max_reassign_time", float(0.5), "Distance in time (seconds) where the matcher will stop trying to reassign an individual based on previous position. After this time runs out, depending on the settings, the tracker will try to find it based on other criteria, or generate a new individual.");
-        CONFIG("manual_identities", std::set<uint32_t>{}, "", SYSTEM);
+        CONFIG("manual_identities", std::set<track::Idx_t>{}, "", SYSTEM);
         CONFIG("pixel_grid_cells", size_t(25), "");
         
         CONFIG("web_quality", int(75), "JPEG quality of images transferred over the web interface.");
@@ -538,7 +539,7 @@ file::Path conda_environment_path() {
         CONFIG("terminate_training", bool(false), "Setting this to true aborts the training in progress.");
         
         CONFIG("manually_approved", std::map<long_t,long_t>(), "A list of ranges of manually approved frames that may be used for generating training datasets {232:232,5555:5560}.");
-        CONFIG("gui_focus_group", std::vector<uint32_t>(), "Focus on this group of individuals.");
+        CONFIG("gui_focus_group", std::vector<Idx_t>(), "Focus on this group of individuals.");
         
         CONFIG("track_ignore", std::vector<std::vector<Vec2>>(), "If this is not empty, objects within the given rectangles or polygons (>= 3 points) [[x0,y0],[x1,y1](, ...)], ...] will be ignored during tracking.");
         CONFIG("track_include", std::vector<std::vector<Vec2>>(), "If this is not empty, objects within the given rectangles or polygons (>= 3 points) [[x0,y0],[x1,y1](, ...)], ...] will be the only objects being tracked. (overwrites `track_ignore`)");
diff --git a/Application/src/tracker/misc/idx_t.cpp b/Application/src/tracker/misc/idx_t.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..82dcdf47ea86f3673c43942044072789f658b0ee
--- /dev/null
+++ b/Application/src/tracker/misc/idx_t.cpp
@@ -0,0 +1,14 @@
+#include "idx_t.h"
+#include <misc/metastring.h>
+
+namespace track {
+
+/*Idx_t::operator std::string() const {
+    return Meta::toStr(_identity);
+}*/
+
+Idx_t Idx_t::fromStr(const std::string& str) {
+    return Idx_t(Meta::fromStr<uint32_t>(str));
+}
+
+}
diff --git a/Application/src/tracker/misc/idx_t.h b/Application/src/tracker/misc/idx_t.h
new file mode 100644
index 0000000000000000000000000000000000000000..e2a2d87ab0085067d6e79d46d44b4881c2bbf5fc
--- /dev/null
+++ b/Application/src/tracker/misc/idx_t.h
@@ -0,0 +1,50 @@
+#pragma once
+#include <commons.pc.h>
+#include <misc/checked_casts.h>
+
+namespace track {
+
+struct Idx_t {
+    uint32_t _identity = infinity<uint32_t>();
+    constexpr Idx_t() = default;
+    template<typename T>
+    explicit constexpr Idx_t(T ID) : _identity(cmn::narrow_cast<uint32_t>(ID)) {}
+    constexpr operator uint32_t() const { return _identity; }
+    constexpr bool valid() const { return _identity != infinity<uint32_t>(); }
+    
+    static std::string class_name() { return "Idx_t"; }
+    //operator std::string() const;
+    static Idx_t fromStr(const std::string&);
+};
+
+struct Frame_t {
+    long_t _frame = infinity<long_t>();
+    constexpr Frame_t() = default;
+    explicit constexpr Frame_t(long_t frame) : _frame(frame) {}
+    constexpr operator long_t() const { return _frame; }
+    constexpr bool valid() const { return _frame != infinity<long_t>(); }
+    constexpr Frame_t& operator+=(Frame_t&& other) {
+        assert(valid() && other.valid());
+        _frame += other._frame;
+        return *this;
+    }
+    constexpr Frame_t& operator+=(long_t&& other) {
+        assert(valid() && other != infinity<long_t>());
+        _frame += other;
+        return *this;
+    }
+};
+
+}
+
+namespace std
+{
+    template<>
+    struct hash<track::Idx_t>
+    {
+        size_t operator()(const track::Idx_t& k) const
+        {
+            return std::hash<uint32_t>{}((uint32_t)k);
+        }
+    };
+}
diff --git a/Application/src/tracker/python/GPURecognition.h b/Application/src/tracker/python/GPURecognition.h
index d21ec6d4273c56243cc7cb2eabee68d84970cc02..795e2bb90e98c4ec086f5c7a30d8b03c4496902a 100644
--- a/Application/src/tracker/python/GPURecognition.h
+++ b/Application/src/tracker/python/GPURecognition.h
@@ -15,16 +15,17 @@
 #include <misc/Image.h>
 #include <misc/SoftException.h>
 #include <misc/GlobalSettings.h>
+#include <misc/idx_t.h>
 
 namespace track {
     using namespace cmn;
 
     class TREX_EXPORT PythonIntegration {
         std::atomic_bool _terminate;
-        std::map<idx_t, std::deque<std::tuple<long_t, Image::Ptr>>> _classes;
-        std::map<idx_t, std::set<long_t>> _received;
-        std::map<idx_t, std::set<long_t>> _sent_to_training;
-        std::map<idx_t, std::vector<Image::Ptr>> _test_data;
+        std::map<Idx_t, std::deque<std::tuple<long_t, Image::Ptr>>> _classes;
+        std::map<Idx_t, std::set<long_t>> _received;
+        std::map<Idx_t, std::set<long_t>> _sent_to_training;
+        std::map<Idx_t, std::vector<Image::Ptr>> _test_data;
         
         std::queue<std::packaged_task<bool()>> tasks;
         
diff --git a/Application/src/tracker/tracking/Accumulation.cpp b/Application/src/tracker/tracking/Accumulation.cpp
index 5bd82954a0a43cf554de6bb368d24bfee85edac1..5365840e681a461069cdb0408f64d907c7347280 100644
--- a/Application/src/tracker/tracking/Accumulation.cpp
+++ b/Application/src/tracker/tracking/Accumulation.cpp
@@ -111,9 +111,9 @@ Accumulation* Accumulation::current() {
     return _current_accumulation;
 }
 
-std::map<long_t, std::set<long_t>> Accumulation::generate_individuals_per_frame(const Rangel& range, TrainingData* data, std::map<long_t, std::set<std::shared_ptr<Individual::SegmentInformation>>>* coverage) {
+std::map<Frame_t, std::set<Idx_t>> Accumulation::generate_individuals_per_frame(const Rangel& range, TrainingData* data, std::map<Idx_t, std::set<std::shared_ptr<Individual::SegmentInformation>>>* coverage) {
     Tracker::LockGuard guard("Accumulation::generate_individuals_per_frame");
-    std::map<long_t, std::set<long_t>> individuals_per_frame;
+    std::map<Frame_t, std::set<Idx_t>> individuals_per_frame;
     const bool calculate_posture = FAST_SETTINGS(calculate_posture);
     
     for(auto id : FAST_SETTINGS(manual_identities)) {
@@ -143,7 +143,7 @@ std::map<long_t, std::set<long_t>> Accumulation::generate_individuals_per_frame(
         it->second->iterate_frames(overall_range, [&individuals_per_frame, id, &used_segments, &current_segment, calculate_posture](long_t frame, const std::shared_ptr<Individual::SegmentInformation>& segment, const std::shared_ptr<Individual::BasicStuff> & basic, const std::shared_ptr<Individual::PostureStuff> & posture) -> bool
         {
             if(basic && (posture || !calculate_posture)) {
-                individuals_per_frame[frame].insert(id);
+                individuals_per_frame[Frame_t(frame)].insert(Idx_t(id));
                 if(segment != current_segment) {
                     used_segments.insert(segment);
                     current_segment = segment;
@@ -159,12 +159,12 @@ std::map<long_t, std::set<long_t>> Accumulation::generate_individuals_per_frame(
         
         if(data) {
             for(auto &segment : used_segments) {
-                data->filters().set(id, *segment, Tracker::recognition()->local_midline_length(it->second, segment->range, false));
+                data->filters().set(Idx_t(id), *segment, Tracker::recognition()->local_midline_length(it->second, segment->range, false));
             }
         }
         
         if(coverage)
-            (*coverage)[id].insert(used_segments.begin(), used_segments.end());
+            (*coverage)[Idx_t(id)].insert(used_segments.begin(), used_segments.end());
     }
     
     /*std::map<long_t, long_t> lengths;
@@ -178,7 +178,7 @@ std::map<long_t, std::set<long_t>> Accumulation::generate_individuals_per_frame(
     return individuals_per_frame;
 }
 
-std::tuple<bool, std::map<long_t, long_t>> Accumulation::check_additional_range(const Rangel& range, TrainingData& data, bool check_length, DatasetQuality::Quality quality) {
+std::tuple<bool, std::map<Idx_t, Idx_t>> Accumulation::check_additional_range(const Rangel& range, TrainingData& data, bool check_length, DatasetQuality::Quality quality) {
     const float pure_chance = 1.f / FAST_SETTINGS(manual_identities).size();
    // data.set_normalized(SETTING(recognition_normalization).value<default_config::recognition_normalization_t::Class>());
     
@@ -186,18 +186,18 @@ std::tuple<bool, std::map<long_t, long_t>> Accumulation::check_additional_range(
         Tracker::LockGuard guard("Accumulation::generate_training_data");
         GUI::work().set_progress("generating images", 0);
         
-        std::map<long_t, std::set<std::shared_ptr<Individual::SegmentInformation>>> segments;
+        std::map<Idx_t, std::set<std::shared_ptr<Individual::SegmentInformation>>> segments;
         auto coverage = generate_individuals_per_frame(range, &data, &segments);
         
         if(check_length) {
-            std::map<long_t, size_t> counts;
+            std::map<Idx_t, size_t> counts;
             for(auto && [frame, ids] : coverage) {
                 for(auto id : ids)
                     ++counts[id];
             }
             
             size_t min_size = std::numeric_limits<size_t>::max(), max_size = 0;
-            long_t min_id = -1;
+            Idx_t min_id;
             
             for(auto && [id, count] : counts) {
                 if(count < min_size) {
@@ -228,13 +228,13 @@ std::tuple<bool, std::map<long_t, long_t>> Accumulation::check_additional_range(
     
     Tracker::LockGuard guard("Accumulation::generate_training_data");
 
-    std::map<long_t, std::tuple<float, std::vector<float>>> averages;
+    std::map<Idx_t, std::tuple<float, std::vector<float>>> averages;
     for(auto id : FAST_SETTINGS(manual_identities)) {
-        std::get<1>(averages[id]).resize(FAST_SETTINGS(manual_identities).size());
-        std::get<0>(averages[id]) = 0;
+        std::get<1>(averages[Idx_t(id)]).resize(FAST_SETTINGS(manual_identities).size());
+        std::get<0>(averages[Idx_t(id)]) = 0;
     }
     
-    std::set<long_t> added_ids, not_added_ids;
+    std::set<Idx_t> added_ids, not_added_ids;
     for(size_t i=0; i<images.size(); ++i) {
         auto & ps = probabilities[i];
         
@@ -253,9 +253,9 @@ std::tuple<bool, std::map<long_t, long_t>> Accumulation::check_additional_range(
     auto str1 = Meta::toStr(not_added_ids);
     Debug("\tCalculated assignments for range %d-%d based on previous training (ids %S / missing %S):", range.start, range.end, &str, &str1);
     
-    std::map<long_t, long_t> max_indexes;
-    std::map<long_t, float> max_probs;
-    std::map<long_t, std::tuple<long_t, float>> print_out;
+    std::map<Idx_t, Idx_t> max_indexes;
+    std::map<Idx_t, float> max_probs;
+    std::map<Idx_t, std::tuple<long_t, float>> print_out;
     
     for(auto && [id, tup] : averages) {
         auto & [samples, values] = tup;
@@ -274,9 +274,11 @@ std::tuple<bool, std::map<long_t, long_t>> Accumulation::check_additional_range(
             }
         }
         
+        assert(max_index >= 0);
+        
         auto str = Meta::toStr(values);
         Debug("\t\t%d: %S (%f, %d = %f)", id, &str, samples, max_index, max_p);
-        max_indexes[id] = max_index;
+        max_indexes[id] = Idx_t((uint32_t)max_index);
         max_probs[id] = max_p;
         print_out[id] = {max_index, max_p};
     }
@@ -284,7 +286,7 @@ std::tuple<bool, std::map<long_t, long_t>> Accumulation::check_additional_range(
     str = Meta::toStr(print_out);
     Debug("%S", &str);
     
-    std::set<long_t> unique_ids;
+    std::set<Idx_t> unique_ids;
     float min_prob = std::numeric_limits<float>::infinity();
     for(auto && [my_id, p] : max_probs)
         min_prob = min(min_prob, p);
@@ -294,7 +296,9 @@ std::tuple<bool, std::map<long_t, long_t>> Accumulation::check_additional_range(
     
     if(unique_ids.size() == FAST_SETTINGS(manual_identities).size() - 1 && min_prob > pure_chance * 1.5) {
         Debug("\tOnly one missing id in predicted ids. Guessing solution...");
-        long_t missing_predicted_id=0;
+        
+        //! Searching for consecutive numbers, finding the gap
+        Idx_t missing_predicted_id(0);
         for(auto id : unique_ids) {
             if(id != missing_predicted_id) {
                 // missing id i
@@ -302,12 +306,12 @@ std::tuple<bool, std::map<long_t, long_t>> Accumulation::check_additional_range(
                 break;
             }
             
-            ++missing_predicted_id;
+            missing_predicted_id = Idx_t((uint32_t)missing_predicted_id + 1u);
         }
         
         // find out which one is double
-        long_t original_id0 = -1, original_id1 = -1;
-        std::map<long_t, long_t> assign;
+        Idx_t original_id0, original_id1;
+        std::map<Idx_t, Idx_t> assign;
         for(auto && [my_id, pred_id] : max_indexes) {
             if(assign.count(pred_id)) {
                 original_id0 = my_id;
@@ -318,7 +322,7 @@ std::tuple<bool, std::map<long_t, long_t>> Accumulation::check_additional_range(
                 assign[pred_id] = my_id;
             }
         }
-        assert(original_id1 != -1);
+        assert(original_id1.valid());
         
         Debug("\tPossible choices are %d (%f) and %d (%f).", original_id0, max_probs.at(original_id0), original_id1, max_probs.at(original_id1));
         
@@ -407,7 +411,7 @@ void Accumulation::update_coverage(const TrainingData &data) {
         });
 }
 
-std::tuple<std::shared_ptr<TrainingData>, std::vector<Image::Ptr>, std::map<long_t, Range<size_t>>> Accumulation::generate_discrimination_data(const std::shared_ptr<TrainingData>& source)
+std::tuple<std::shared_ptr<TrainingData>, std::vector<Image::Ptr>, std::map<Frame_t, Range<size_t>>> Accumulation::generate_discrimination_data(const std::shared_ptr<TrainingData>& source)
 {
     auto data = std::make_shared<TrainingData>();
     
@@ -423,9 +427,9 @@ std::tuple<std::shared_ptr<TrainingData>, std::vector<Image::Ptr>, std::map<long
         auto analysis_range = Tracker::analysis_range();
         auto &individuals = Tracker::individuals();
         
-        std::map<long_t, std::set<long_t>> disc_individuals_per_frame;
+        std::map<Frame_t, std::set<Idx_t>> disc_individuals_per_frame;
         
-        for(long_t frame = analysis_range.start; frame <= analysis_range.end; frame += max(1, analysis_range.length() / 333))
+        for(Frame_t frame(analysis_range.start); frame <= analysis_range.end; frame += max(1, analysis_range.length() / 333))
         {
             if(frame < Tracker::start_frame())
                 continue;
@@ -444,10 +448,10 @@ std::tuple<std::shared_ptr<TrainingData>, std::vector<Image::Ptr>, std::map<long
                     {
                         auto frange = fish->get_segment(frame);
                         if(frange.contains(frame)) {
-                            if(!data->filters().has(id, frange)) {
-                                data->filters().set(id, frange,  Tracker::recognition()->local_midline_length(fish, frame, false));
+                            if(!data->filters().has(Idx_t(id), frange)) {
+                                data->filters().set(Idx_t(id), frange,  Tracker::recognition()->local_midline_length(fish, frame, false));
                             }
-                            disc_individuals_per_frame[frame].insert(id);
+                            disc_individuals_per_frame[frame].insert(Idx_t(id));
                         }
                     }
                 }
@@ -468,7 +472,7 @@ std::tuple<std::shared_ptr<TrainingData>, std::vector<Image::Ptr>, std::map<long
     return {data, disc_images, disc_frame_map};
 }
 
-std::tuple<float, std::map<uint32_t, float>, float> Accumulation::calculate_uniqueness(bool internal, const std::vector<Image::Ptr>& images, const std::map<long_t, Range<size_t>>& map_indexes)
+std::tuple<float, std::map<Frame_t, float>, float> Accumulation::calculate_uniqueness(bool internal, const std::vector<Image::Ptr>& images, const std::map<Frame_t, Range<size_t>>& map_indexes)
 {
     std::vector<std::vector<float>> predictions;
     if(internal) {
@@ -513,18 +517,18 @@ std::tuple<float, std::map<uint32_t, float>, float> Accumulation::calculate_uniq
     size_t good_frames = 0;
     size_t bad_frames = 0;
     double percentages = 0, rpercentages = 0;
-    std::map<uint32_t, float> unique_percent;
-    std::map<uint32_t, float> unique_percent_raw;
+    std::map<Frame_t, float> unique_percent;
+    std::map<Frame_t, float> unique_percent_raw;
     
-    std::map<uint32_t, float> unique_percent_per_identity;
-    std::map<uint32_t, float> per_identity_samples;
+    std::map<Idx_t, float> unique_percent_per_identity;
+    std::map<Idx_t, float> per_identity_samples;
     
     for(auto && [frame, range] : map_indexes) {
-        std::set<uint32_t> unique_ids;
-        std::map<uint32_t, float> probs;
+        std::set<Idx_t> unique_ids;
+        std::map<Idx_t, float> probs;
         
         for (auto i = range.start; i < range.end; ++i) {
-            int64_t max_id = -1;
+            Idx_t max_id;
             float max_p = 0;
             
             if(predictions.at(i).size() < FAST_SETTINGS(manual_identities).size()) {
@@ -536,13 +540,13 @@ std::tuple<float, std::map<uint32_t, float>, float> Accumulation::calculate_uniq
                 auto p = predictions.at(i).at(id);
                 if(p > max_p) {
                     max_p = p;
-                    max_id = id;
+                    max_id = Idx_t(id);
                 }
             }
             
-            if(max_id != -1) {
-                unique_ids.insert((uint32_t)max_id);
-                probs[(uint32_t)max_id] = max(probs[(uint32_t)max_id], max_p);
+            if(max_id.valid()) {
+                unique_ids.insert(max_id);
+                probs[max_id] = max(probs[max_id], max_p);
             }
         }
         
@@ -555,19 +559,19 @@ std::tuple<float, std::map<uint32_t, float>, float> Accumulation::calculate_uniq
         }
         
         auto logic_regression = [](float x) {
-            static const float NORMAL = (1+expf(-1*M_PI*1));
+            static const float NORMAL = (1+expf(-1*float(M_PI)*1));
             return 1/(1+exp(-x*M_PI*1))*NORMAL;
             //return 1.f/(1.f+expf(-x*10));
         };
         
-        unique_percent_raw[frame] = p;
+        unique_percent_raw[frame] = float(p);
         rpercentages += p;
         
         if(!probs.empty())
             p = logic_regression(accum_p / float(probs.size())) * p;
             //p = (accum_p / float(probs.size()) + p) * 0.5;
         
-        unique_percent[frame] = p;
+        unique_percent[frame] = float(p);
         percentages += p;
         
         if(unique_ids.size() == range.length() - 1) {
@@ -658,7 +662,8 @@ bool Accumulation::start() {
         Accumulation::setup();
         
         auto data = std::make_shared<TrainingData>();
-        data->set_classes(FAST_SETTINGS(manual_identities));
+        auto manual = FAST_SETTINGS(manual_identities);
+        data->set_classes(std::set<Idx_t>(manual.begin(), manual.end()));
         auto result = Recognition::train(data, FrameRange(), TrainingMode::Apply, -1, true);
         
         if(result) {
@@ -768,7 +773,7 @@ bool Accumulation::start() {
                 auto ranges_path = pv::DataLocation::parse("output", Path(SETTING(filename).value<file::Path>().filename()+"_validation_data.npz"));
                 
                 const Size2 dims = SETTING(recognition_image_size);
-                FileSize size((data.validation_images.size() + data.training_images.size()) * dims.width * dims.height);
+                FileSize size((data.validation_images.size() + data.training_images.size()) * size_t(dims.width * dims.height));
                 std::vector<uchar> all_images;
                 all_images.resize(size.bytes);
                 
@@ -876,9 +881,9 @@ bool Accumulation::start() {
                             range_distance = min(r.start - range.end, range_distance);
                     }
                     
-                    const long frames_around_center = max(1, analysis_range.length() * 0.1);
+                    const long frames_around_center = max(1, analysis_range.length() / 10);
                     
-                    auto center = range.length() * 0.5 + range.start;
+                    auto center = range.length() / 2 + range.start;
                     FrameRange extended_range(Rangel(
                         max(analysis_range.start, center - frames_around_center),
                         min(analysis_range.end, center + frames_around_center))
@@ -901,7 +906,7 @@ bool Accumulation::start() {
                     if(distance < min_distance) min_distance = distance;
                     //distance = roundf((1 - SQR(average)) * 10) * 10;
                     
-                    range_distance = next_pow2(range_distance);
+                    range_distance = narrow_cast<int64_t>(next_pow2(range_distance));
                     
                     copied_sorted.insert({distance, range_distance, q, cached, range, extended_range, samples});
                 } else {
@@ -1085,7 +1090,7 @@ bool Accumulation::start() {
                         //}
                     }
                     
-                    if(acceptance) {
+                    if(acceptance > 0) {
                         _added_ranges.push_back(range);
                         
                         auto str = Meta::toStr(*second_data);
@@ -1153,7 +1158,7 @@ bool Accumulation::start() {
             return {false, success ? second_data : nullptr};
         };
         
-        auto update_meta_start_acc = [&](std::string prefix, Rangel next_range, DatasetQuality::Quality quality, float average_unique) {
+        auto update_meta_start_acc = [&](std::string prefix, Rangel next_range, DatasetQuality::Quality quality, double average_unique) {
             Debug("");
             auto qual_str = Meta::toStr(quality);
             Debug("[Accumulation %d%S] %d ranges remaining for accumulation (%d cached that did not predict unique ids yet), range %d-%d (%S, %f unique weight).", steps, &prefix, sorted.size(), tried_ranges.size(), next_range.start, next_range.end, &qual_str, average_unique);
@@ -1172,12 +1177,12 @@ bool Accumulation::start() {
                 return false;
             }
             
-            std::map<long_t, size_t> sizes;
+            std::map<Idx_t, int64_t> sizes;
             for(auto id : FAST_SETTINGS(manual_identities)) {
-                sizes[id] = 0;
+                sizes[Idx_t(id)] = 0;
             }
             
-            std::map<long_t, std::set<FrameRange>> assigned_ranges;
+            std::map<Idx_t, std::set<FrameRange>> assigned_ranges;
             
             for(auto & d : _collected_data->data()) {
                 /*for(auto && [id, per] : d->mappings) {
@@ -1193,8 +1198,8 @@ bool Accumulation::start() {
                 }
             }
             
-            std::map<long_t, std::set<FrameRange>> gaps;
-            std::map<long_t, long_t> frame_gaps;
+            std::map<Idx_t, std::set<FrameRange>> gaps;
+            std::map<Idx_t, long_t> frame_gaps;
             for(auto && [id, ranges] : assigned_ranges)
             {
                 long_t previous_frame = analysis_range.start;
@@ -1367,7 +1372,7 @@ bool Accumulation::start() {
     }
     
     if(!GUI::work().item_aborted() && SETTING(gpu_accumulation_enable_final_step)) {
-        std::map<long_t, size_t> images_per_class;
+        std::map<Idx_t, size_t> images_per_class;
         size_t overall_images = 0;
         for(auto &d : _collected_data->data()) {
             for(auto &image : d->images) {
@@ -1463,8 +1468,8 @@ bool Accumulation::start() {
                 Collect all frames for all individuals.
                 Then generate all frames for all normalization methods.
              */
-            std::map<long_t, std::set<long_t>> frames_collected;
-            std::map<long_t, std::map<long_t, long_t>> frames_assignment;
+            std::map<long_t, std::set<Idx_t>> frames_collected;
+            std::map<long_t, std::map<Idx_t, Idx_t>> frames_assignment;
             for(auto &data : _collected_data->data()) {
                 for(auto && [id, per] : data->mappings) {
                     auto org = data->unmap(id);
@@ -1477,7 +1482,7 @@ bool Accumulation::start() {
             
             for(auto method : default_config::recognition_normalization_t::values)
             {
-                std::map<long_t, std::vector<Image::Ptr>> images;
+                std::map<Idx_t, std::vector<Image::Ptr>> images;
                 PPFrame video_frame;
                 auto &video_file = *GUI::instance()->video_source();
                 
@@ -1538,7 +1543,7 @@ bool Accumulation::start() {
                         
                         using namespace default_config;
                         auto midline = posture ? fish->calculate_midline_for(basic, posture) : nullptr;
-                        Recognition::ImageData image_data(Recognition::ImageData::Blob{blob->num_pixels(), blob->blob_id(), -1, blob->parent_id(), blob->bounds()}, frame, (FrameRange)(*it->get()), fish, fish->identity().ID(), midline ? midline->transform(method) : gui::Transform());
+                        Recognition::ImageData image_data(Recognition::ImageData::Blob{blob->num_pixels(), blob->blob_id(), -1, blob->parent_id(), blob->bounds()}, frame, (FrameRange)(*it->get()), fish, Idx_t(fish->identity().ID()), midline ? midline->transform(method) : gui::Transform());
                         image_data.filters = std::make_shared<TrainingFilterConstraints>(filters);
                         
                         image = Recognition::calculate_diff_image_with_settings(method, blob, image_data, output_size);
@@ -1560,7 +1565,7 @@ bool Accumulation::start() {
                     
                     
                     const Size2 dims = SETTING(recognition_image_size);
-                    std::vector<long_t> ids;
+                    std::vector<Idx_t> ids;
                     size_t total_images = 0;
                     for(auto && [id, img]: images) {
                         ids.insert(ids.end(), img.size(), id);
diff --git a/Application/src/tracker/tracking/Accumulation.h b/Application/src/tracker/tracking/Accumulation.h
index 215cdfee90ae9b561909e799889a66752ca82809..8a61f702d67478bc0b6e16e2630f7053fc1562b8 100644
--- a/Application/src/tracker/tracking/Accumulation.h
+++ b/Application/src/tracker/tracking/Accumulation.h
@@ -45,9 +45,9 @@ class Accumulation {
     std::shared_ptr<TrainingData> _collected_data, _generated_data;
     std::shared_ptr<TrainingData> _discrimination_data;
     std::vector<Image::Ptr> _disc_images;
-    std::map<long_t, Range<size_t>> _disc_frame_map;
+    std::map<Frame_t, Range<size_t>> _disc_frame_map;
     std::vector<long_t> _checked_ranges_output;
-    std::map<uint32_t, float> unique_map, temp_unique;
+    std::map<Frame_t, float> unique_map, temp_unique;
     std::map<Rangel, std::tuple<double, FrameRange>> assigned_unique_averages;
     size_t _accumulation_step;
     size_t _counted_steps, _last_step;
@@ -84,13 +84,13 @@ public:
     bool start();
     
     static float good_uniqueness();
-    std::map<long_t, std::set<long_t>> generate_individuals_per_frame(const Rangel& range, TrainingData* data, std::map<long_t, std::set<std::shared_ptr<Individual::SegmentInformation>>>*);
-    std::tuple<bool, std::map<long_t, long_t>> check_additional_range(const Rangel& range, TrainingData& data, bool check_length, DatasetQuality::Quality);
+    std::map<Frame_t, std::set<Idx_t>> generate_individuals_per_frame(const Rangel& range, TrainingData* data, std::map<Idx_t, std::set<std::shared_ptr<Individual::SegmentInformation>>>*);
+    std::tuple<bool, std::map<Idx_t, Idx_t>> check_additional_range(const Rangel& range, TrainingData& data, bool check_length, DatasetQuality::Quality);
     void confirm_weights();
     void update_coverage(const TrainingData& data);
     
-    static std::tuple<float, std::map<uint32_t, float>, float> calculate_uniqueness(bool internal, const std::vector<Image::Ptr>&, const std::map<long_t, Range<size_t>>&);
-    static std::tuple<std::shared_ptr<TrainingData>, std::vector<Image::Ptr>, std::map<long_t, Range<size_t>>> generate_discrimination_data(const std::shared_ptr<TrainingData>& source = nullptr);
+    static std::tuple<float, std::map<Frame_t, float>, float> calculate_uniqueness(bool internal, const std::vector<Image::Ptr>&, const std::map<Frame_t, Range<size_t>>&);
+    static std::tuple<std::shared_ptr<TrainingData>, std::vector<Image::Ptr>, std::map<Frame_t, Range<size_t>>> generate_discrimination_data(const std::shared_ptr<TrainingData>& source = nullptr);
     static void setup();
     static void unsetup();
     static Accumulation* current();
@@ -98,7 +98,7 @@ public:
 private:
     
     Rangel _initial_range;
-    std::map<long_t, std::set<long_t>> individuals_per_frame;
+    std::map<Frame_t, std::set<Idx_t>> individuals_per_frame;
     //std::map<long_t, std::set<std::shared_ptr<Individual::SegmentInformation>>> overall_coverage;
     std::vector<Rangel> _added_ranges;
     std::vector<Rangel> _next_ranges;
diff --git a/Application/src/tracker/tracking/DatasetQuality.cpp b/Application/src/tracker/tracking/DatasetQuality.cpp
index 310d48fad4f8409a68b65f10a33ef08867b0b1d9..1f4a53425b51f6d24ea0e0144cdb502efddff09c 100644
--- a/Application/src/tracker/tracking/DatasetQuality.cpp
+++ b/Application/src/tracker/tracking/DatasetQuality.cpp
@@ -125,7 +125,7 @@ bool DatasetQuality::calculate_segment(const Rangel &consec, const long_t video_
     
     Tracker::instance()->thread_pool().wait();
     
-    if(num_average)
+    if(num_average != 0)
         average_samples /= num_average;
     
     /*std::set<float> values;
@@ -233,7 +233,7 @@ Rangel DatasetQuality::best_range() const {
     return Rangel(-1,-1);
 }
 
-std::map<idx_t, DatasetQuality::Single> DatasetQuality::per_fish(const Rangel &range) const {
+std::map<Idx_t, DatasetQuality::Single> DatasetQuality::per_fish(const Rangel &range) const {
     auto it = _cache.find(range);
     if(it == _cache.end())
         return {};
@@ -245,7 +245,7 @@ bool DatasetQuality::has(const Rangel& range) const {
     return it != _cache.end() && !it->second.empty();
 }
 
-DatasetQuality::Single DatasetQuality::evaluate_single(idx_t id, Individual* fish, const Rangel &_consec, const Tracker::LockGuard&)
+DatasetQuality::Single DatasetQuality::evaluate_single(Idx_t id, Individual* fish, const Rangel &_consec, const Tracker::LockGuard&)
 {
     //assert(Tracker::individuals().find(id) != Tracker::individuals().end());
     
diff --git a/Application/src/tracker/tracking/DatasetQuality.h b/Application/src/tracker/tracking/DatasetQuality.h
index 6a25928cddf1cf5628496a77fb38bf18178552d7..5beb26e89936bcd09b9a369a8f2f5914d0c31e39 100644
--- a/Application/src/tracker/tracking/DatasetQuality.h
+++ b/Application/src/tracker/tracking/DatasetQuality.h
@@ -8,7 +8,7 @@ namespace track {
     class DatasetQuality {
     public:
         struct Single {
-            idx_t id;
+            Idx_t id;
             
             float midline_len;
             float midline_std;
@@ -26,7 +26,7 @@ namespace track {
             
             long_t number_frames;
             
-            Single(idx_t id = infinity<idx_t>())
+            Single(Idx_t id = Idx_t())
                 : id(id), midline_len(0), midline_std(0), distance_travelled(0), grid_cells_visited(0), median_angle_var(0), number_frames(0)
             { }
             
@@ -65,7 +65,7 @@ namespace track {
         
     private:
         Rangel _manually_selected;
-        std::map<Rangel, std::map<idx_t, Single>> _cache;
+        std::map<Rangel, std::map<Idx_t, Single>> _cache;
         std::map<Rangel, Quality> _quality;
         Rangel _last_seen;
         std::set<Rangel> _previous_selected;
@@ -81,13 +81,13 @@ namespace track {
         //Quality quality(float frame) const;
         bool has(const Rangel& range) const;
         Rangel best_range() const;
-        std::map<idx_t, Single> per_fish(const Rangel&) const;
+        std::map<Idx_t, Single> per_fish(const Rangel&) const;
         
         void print_info() const;
         
     private:
         void remove_segment(const Rangel& range);
         bool calculate_segment(const Rangel&, const long_t video_length, const Tracker::LockGuard&);
-        Single evaluate_single(idx_t id, Individual* fish, const Rangel& consec, const Tracker::LockGuard& guard);
+        Single evaluate_single(Idx_t id, Individual* fish, const Rangel& consec, const Tracker::LockGuard& guard);
     };
 }
diff --git a/Application/src/tracker/tracking/Export.cpp b/Application/src/tracker/tracking/Export.cpp
index fd37d7558ce6db0e9700bf5cbe15aef813e0341d..2f09abc4b02f8bbf55be60030d0c258e57ebb7e4 100644
--- a/Application/src/tracker/tracking/Export.cpp
+++ b/Application/src/tracker/tracking/Export.cpp
@@ -678,7 +678,7 @@ void export_data(Tracker& tracker, long_t fdx, const Rangel& range) {
                     temporary_save(final_path, [&](file::Path path){
                         Debug("Generating memory stats...");
                         mem::IndividualMemoryStats overall;
-                        std::map<track::idx_t, mem::IndividualMemoryStats> indstats;
+                        std::map<track::Idx_t, mem::IndividualMemoryStats> indstats;
                         for(auto && [fdx, fish] : tracker.individuals()) {
                             mem::IndividualMemoryStats stats(fish);
                             indstats[fdx] = stats;
diff --git a/Application/src/tracker/tracking/Individual.cpp b/Application/src/tracker/tracking/Individual.cpp
index 671857008e764c569f9a29ad3274958c3927bdbf..1ef71fc586f4df50efe424c128b573688e7b28b5 100644
--- a/Application/src/tracker/tracking/Individual.cpp
+++ b/Application/src/tracker/tracking/Individual.cpp
@@ -2602,7 +2602,7 @@ void Individual::calculate_average_recognition() {
     _average_recognition_samples = 0;
     _average_recognition.clear();
     
-    std::map<long_t, size_t> samples;
+    std::map<Idx_t, size_t> samples;
     const float frame_limit = FAST_SETTINGS(frame_rate) * 2;
     
     for(auto & segment : _frame_segments) {
@@ -2707,7 +2707,7 @@ const decltype(Individual::average_recognition_segment)::mapped_type Individual:
             return {0, {}};
         }
         
-        std::map<long_t, std::tuple<long_t, float>> samples;
+        std::map<Idx_t, std::tuple<long_t, float>> samples;
         size_t overall = 0;
         
         for(long_t i = segment.start; i < segment.end; ++i) {
@@ -2720,14 +2720,14 @@ const decltype(Individual::average_recognition_segment)::mapped_type Individual:
                 ++overall;
                 
                 for (auto && [fdx, p] : raw) {
-                    ++std::get<0>(samples[fdx]);
-                    std::get<1>(samples[fdx]) += p;
+                    ++std::get<0>(samples[Idx_t(fdx)]);
+                    std::get<1>(samples[Idx_t(fdx)]) += p;
                 }
             }
         }
         
         if(overall > 0) {
-            std::map<long_t, float> average;
+            std::map<Idx_t, float> average;
             float s = 0;
             for (auto && [key, value] : samples) {
                 float n = std::get<0>(value);
@@ -2767,7 +2767,7 @@ const decltype(Individual::average_recognition_segment)::mapped_type Individual:
             return {0, {}};
         }
         
-        std::map<long_t, std::tuple<long_t, float>> samples;
+        std::map<Idx_t, std::tuple<long_t, float>> samples;
         size_t overall = 0;
         
         for(long_t i = segment.start; i < segment.end; ++i) {
@@ -2780,14 +2780,14 @@ const decltype(Individual::average_recognition_segment)::mapped_type Individual:
                 ++overall;
                 
                 for (auto && [fdx, p] : raw) {
-                    ++std::get<0>(samples[fdx]);
-                    std::get<1>(samples[fdx]) += p;
+                    ++std::get<0>(samples[Idx_t(fdx)]);
+                    std::get<1>(samples[Idx_t(fdx)]) += p;
                 }
             }
         }
         
         if(overall > 0) {
-            std::map<long_t, float> average;
+            std::map<Idx_t, float> average;
             float s = 0;
             for (auto && [key, value] : samples) {
                 float n = std::get<0>(value);
@@ -2808,17 +2808,17 @@ const decltype(Individual::average_recognition_segment)::mapped_type Individual:
     return average_recognition_segment.at(segment_start);
 }
 
-std::tuple<size_t, long_t, float> Individual::average_recognition_identity(long_t segment_start) const {
+std::tuple<size_t, Idx_t, float> Individual::average_recognition_identity(long_t segment_start) const {
     auto it = average_recognition_segment.find(segment_start);
     if(it == average_recognition_segment.end()) {
-        return {0, -1, 0};
+        return {0, Idx_t(), 0};
     }
     
-    long_t mdx = -1;
+    Idx_t mdx;
     float mdx_p = 0;
     
     for(auto && [fdx, p] : std::get<1>(it->second)) {
-        if(p > mdx_p) {
+        if(!mdx.valid() || p > mdx_p) {
             mdx_p = p;
             mdx = fdx;
         }
diff --git a/Application/src/tracker/tracking/Individual.h b/Application/src/tracker/tracking/Individual.h
index fdd1e0a7007880e49e46891ee9915b244e9a6a29..59171bdb973163fb3ded8dc5299b4825cb00f5f0 100644
--- a/Application/src/tracker/tracking/Individual.h
+++ b/Application/src/tracker/tracking/Individual.h
@@ -2,6 +2,7 @@
 #define _FISHP_H
 
 #include <types.h>
+#include <tracker/misc/idx_t.h>
 #include <gui/colors.h>
 #include <misc/Blob.h>
 #include "Posture.h"
@@ -92,7 +93,7 @@ namespace track {
         std::vector<std::shared_ptr<pv::Blob>> blobs, original_blobs;
         std::vector<std::shared_ptr<pv::Blob>> filtered_out;
         
-        std::map<uint32_t, IndividualCache> cached_individuals;
+        std::map<Idx_t, IndividualCache> cached_individuals;
         std::map<uint32_t, std::set<long_t>> blob_cliques, fish_cliques;
         std::set<uint32_t> split_blobs;
         std::map<uint32_t, pv::BlobPtr> bdx_to_ptr;
@@ -118,7 +119,7 @@ namespace track {
         
     protected:
         GETTER_SETTER(gui::Color, color)
-        uint32_t _myID;
+        Idx_t _myID;
         std::string _name;
         GETTER_SETTER(bool, manual)
         
@@ -129,7 +130,7 @@ namespace track {
         decltype(_myID) ID() const { return _myID; }
         void set_ID(uint32_t val) {
             _color = ColorWheel(val).next();
-            _myID = val;
+            _myID = Idx_t(val);
             _name = Meta::toStr(_myID);
         }
         const std::string& raw_name();
@@ -276,12 +277,12 @@ namespace track {
         
         //! Contains a map with individual -> probability for the blob that has been
         //  assigned to this individual.
-        std::map<long_t, std::tuple<size_t, std::map<long_t, float>>> average_recognition_segment;
-        std::map<long_t, std::tuple<size_t, std::map<long_t, float>>> average_processed_segment;
+        std::map<long_t, std::tuple<size_t, std::map<Idx_t, float>>> average_recognition_segment;
+        std::map<long_t, std::tuple<size_t, std::map<Idx_t, float>>> average_processed_segment;
         
         //! Contains a map from fish id to probability that averages over
         //  all available segments when "check identities" was last clicked
-        std::map<long_t, float> _average_recognition;
+        std::map<Idx_t, float> _average_recognition;
         GETTER(size_t, average_recognition_samples)
         
         long_t _startFrame = -1, _endFrame = -1;
@@ -390,7 +391,7 @@ namespace track {
         //const decltype(average_recognition_segment)::mapped_type& average_recognition(long_t segment_start) const;
         const decltype(average_recognition_segment)::mapped_type average_recognition(long_t segment_start);
         const decltype(average_recognition_segment)::mapped_type processed_recognition(long_t segment_start);
-        std::tuple<size_t, long_t, float> average_recognition_identity(long_t segment_start) const;
+        std::tuple<size_t, Idx_t, float> average_recognition_identity(long_t segment_start) const;
         
         //! Properties based on centroid:
         const PhysicalProperties* centroid(long_t frameIndex) const;
diff --git a/Application/src/tracker/tracking/Recognition.cpp b/Application/src/tracker/tracking/Recognition.cpp
index 244b50849cf037cd996e0929defdd4d5ec5c8761..5f91a543343066968be664e838638ca3676688b6 100644
--- a/Application/src/tracker/tracking/Recognition.cpp
+++ b/Application/src/tracker/tracking/Recognition.cpp
@@ -270,15 +270,15 @@ std::unique_ptr<Image> Recognition::calculate_diff_image_with_settings(const def
         return false;
     }*/
     
-    std::map<long_t, float> Recognition::ps_raw(long_t frame, uint32_t blob_id) {
+    std::map<Idx_t, float> Recognition::ps_raw(long_t frame, uint32_t blob_id) {
         std::lock_guard<std::mutex> probs_guard(_mutex);
         auto entry = probs.find(frame);
         if (entry != probs.end()) {
             auto it = entry->second.find(blob_id);
             if(it != entry->second.end()) {
-                std::map<long_t, float> map;
+                std::map<Idx_t, float> map;
                 for (size_t i=0; i<it->second.size(); i++) {
-                    map[fish_idx_to_id.empty() ? i : fish_idx_to_id.at(i)] = it->second[i];
+                    map[fish_idx_to_id.empty() ? Idx_t(i) : fish_idx_to_id.at(Idx_t(i))] = it->second[i];
                 }
                 return map;
             }
@@ -778,7 +778,7 @@ std::unique_ptr<Image> Recognition::calculate_diff_image_with_settings(const def
             
             _fish_last_frame.clear();
             for(auto id : identities)
-                _fish_last_frame[id] = FishInfo();
+                _fish_last_frame[Idx_t(id)] = FishInfo();
         }
         
         auto str = Meta::toStr(_fish_last_frame);
@@ -1076,19 +1076,19 @@ std::unique_ptr<Image> Recognition::calculate_diff_image_with_settings(const def
         return obj;
     }
     
-    void Recognition::Detail::inproc_frame(long_t frame, long_t fdx) {
+    void Recognition::Detail::inproc_frame(long_t frame, Idx_t fdx) {
         std::lock_guard<std::mutex> guard(lock);
         auto & [add, inp, proc] = added_individuals_per_frame[frame];
         inp.insert(fdx);
     }
     
-    void Recognition::Detail::add_frame(long_t frame, long_t fdx) {
+    void Recognition::Detail::add_frame(long_t frame, Idx_t fdx) {
         std::lock_guard<std::mutex> guard(lock);
         auto & [add, inp, proc] = added_individuals_per_frame[frame];
         add.insert(fdx);
     }
 
-    void Recognition::Detail::failed_frame(long_t frame, long_t fdx) {
+    void Recognition::Detail::failed_frame(long_t frame, Idx_t fdx) {
         std::lock_guard<std::mutex> guard(lock);
         auto & [add, inp, proc] = added_individuals_per_frame[frame];
         add.insert(fdx);
@@ -1096,7 +1096,7 @@ std::unique_ptr<Image> Recognition::calculate_diff_image_with_settings(const def
         proc.insert(fdx);
     }
     
-    void Recognition::Detail::finished_frames(const std::map<long_t, std::set<idx_t> > &individuals_per_frame) {
+    void Recognition::Detail::finished_frames(const std::map<long_t, std::set<Idx_t> > &individuals_per_frame) {
         size_t added_frames;
         Rangel analysis_range;
         long_t end_frame, video_length;
@@ -1206,7 +1206,7 @@ std::unique_ptr<Image> Recognition::calculate_diff_image_with_settings(const def
         _last_checked_frame = min(_last_checked_frame, after);
     }
     
-    void Recognition::Detail::remove_individual(idx_t fdx) {
+    void Recognition::Detail::remove_individual(Idx_t fdx) {
         std::lock_guard<std::mutex> guard(lock);
         std::set<long_t> frames;
         for (auto & [frame, tup] : added_individuals_per_frame) {
@@ -1289,7 +1289,7 @@ std::unique_ptr<Image> Recognition::calculate_diff_image_with_settings(const def
 
                 std::vector<ImageData> data;
                 std::vector<Image::Ptr> images;
-                std::map<long_t, std::set<idx_t>> uploaded_frames;
+                std::map<long_t, std::set<Idx_t>> uploaded_frames;
 
                 {
                     //! TODO: only exit if this is not the end of the video
@@ -1451,7 +1451,7 @@ void Recognition::check_learning_module(bool force) {
         auto result = PythonIntegration::check_module("learn_static");
         if(result || force || py::is_none("classes", "learn_static")) {
             size_t N = FAST_SETTINGS(track_max_individuals) ? (size_t)FAST_SETTINGS(track_max_individuals) : 1u;
-            std::vector<idx_t> ids;
+            std::vector<int32_t> ids;
             ids.resize(N);
             
             for(size_t i=0; i<N; ++i)
@@ -1881,7 +1881,7 @@ void Recognition::load_weights(std::string postfix) {
                     auto joined_data = data->join_split_data();
                     
                     if(FAST_SETTINGS(manual_identities).size() > classes.size()) {
-                        std::set<idx_t> missing;
+                        std::set<Idx_t> missing;
                         for(auto id : FAST_SETTINGS(manual_identities)) {
                             if(std::find(classes.begin(), classes.end(), id) == classes.end())
                                 missing.insert(id);
diff --git a/Application/src/tracker/tracking/Recognition.h b/Application/src/tracker/tracking/Recognition.h
index cd587780716420328049625ea5e7f64144ccaaa2..091a129d1ed0791acd5dc8ce32414ce62552ae3f 100644
--- a/Application/src/tracker/tracking/Recognition.h
+++ b/Application/src/tracker/tracking/Recognition.h
@@ -51,10 +51,10 @@ namespace track {
         std::map<long_t, std::map<uint32_t, std::vector<float>>> probs;
         //std::set<long_t> identities;
         //std::map<long_t, long_t> fish_id_to_idx;
-        std::map<long_t, long_t> fish_idx_to_id;
+        std::map<Idx_t, Idx_t> fish_idx_to_id;
         std::set<Rangel> gui_last_trained_ranges;
         
-        typedef long_t fdx_t;
+        typedef Idx_t fdx_t;
         typedef long_t frame_t;
         
         struct FishInfo {
@@ -71,7 +71,7 @@ namespace track {
         std::map<frame_t, std::set<fdx_t>> _last_frames;
         std::map<fdx_t, FishInfo> _fish_last_frame;
         
-        std::map<long_t, std::map<Rangel, TrainingFilterConstraints>> custom_midline_lengths;
+        std::map<Idx_t, std::map<Rangel, TrainingFilterConstraints>> custom_midline_lengths;
         
     public:
         struct ImageData {
@@ -88,10 +88,10 @@ namespace track {
             long_t frame;
             FrameRange segment;
             Individual *fish;
-            idx_t fdx;
+            Idx_t fdx;
             gui::Transform midline_transform;
             
-            ImageData(Blob blob = Blob{0,0,-1,-1}, long_t frame = -1, const FrameRange& segment = FrameRange(), Individual * fish = NULL, idx_t fdx = -1, const gui::Transform& transform = gui::Transform())
+            ImageData(Blob blob = Blob{0,0,-1,-1}, long_t frame = -1, const FrameRange& segment = FrameRange(), Individual * fish = NULL, Idx_t fdx = Idx_t(), const gui::Transform& transform = gui::Transform())
                 : image(nullptr), filters(nullptr), blob(blob), frame(frame), segment(segment), fish(fish), fdx(fdx), midline_transform(transform)
             {}
         };
@@ -123,13 +123,13 @@ namespace track {
             size_t processed;
             float _percent;
             
-            std::map<long_t, std::tuple<std::set<idx_t>, std::set<idx_t>, std::set<idx_t>>> added_individuals_per_frame;
+            std::map<long_t, std::tuple<std::set<Idx_t>, std::set<Idx_t>, std::set<Idx_t>>> added_individuals_per_frame;
             std::vector<std::function<void()>> registered_callbacks;
             
             GETTER_SETTER(long_t, last_checked_frame)
             GETTER_SETTER(float, processing_percent)
-            std::map<idx_t, long_t> _max_pre_frame;
-            std::map<idx_t, long_t> _max_pst_frame;
+            std::map<Idx_t, long_t> _max_pre_frame;
+            std::map<Idx_t, long_t> _max_pst_frame;
             float _last_percent;
             
             GETTER(size_t, unavailable_blobs)
@@ -147,8 +147,8 @@ namespace track {
                 size_t added, processed, N, max_frame, inproc;
                 float percent;
                 long_t last_frame;
-                std::map<idx_t, long_t> max_pre_frame;
-                std::map<idx_t, long_t> max_pst_frame;
+                std::map<Idx_t, long_t> max_pre_frame;
+                std::map<Idx_t, long_t> max_pst_frame;
                 size_t failed_blobs;
                 
                 Info() : added(0), processed(0), N(0), max_frame(0), inproc(0), percent(0), last_frame(-1), failed_blobs(0) {
@@ -175,13 +175,13 @@ namespace track {
             }
             
             void remove_frames(long_t after);
-            void remove_individual(idx_t fdx);
+            void remove_individual(Idx_t fdx);
             
-            void add_frame(long_t, long_t);
-            void inproc_frame(long_t, long_t);
-            void failed_frame(long_t, long_t);
+            void add_frame(long_t, Idx_t);
+            void inproc_frame(long_t, Idx_t);
+            void failed_frame(long_t, Idx_t);
             
-            void finished_frames(const std::map<long_t, std::set<idx_t>>& individuals_per_frame);
+            void finished_frames(const std::map<long_t, std::set<Idx_t>>& individuals_per_frame);
             void register_finished_callback(std::function<void()>&& fn);
             void clear();
         };
@@ -196,7 +196,7 @@ namespace track {
 
         static void fix_python();
         //float p(long_t frame, uint32_t blob_id, const Individual *fish);
-        std::map<long_t, float> ps_raw(long_t frame, uint32_t blob_id);
+        std::map<Idx_t, float> ps_raw(long_t frame, uint32_t blob_id);
         //bool has(long_t frame, uint32_t blob_id);
         //bool has(long_t frame, const Individual* fish);
         //std::map<long_t, std::map<long_t, long_t>> check_identities(long_t frame, const std::vector<pv::BlobPtr>& blobs);
diff --git a/Application/src/tracker/tracking/Tracker.cpp b/Application/src/tracker/tracking/Tracker.cpp
index da35ba56445b867e5787b418431f631eb664144c..a47605357918047afe5d993b1822d8c60a0fba8a 100644
--- a/Application/src/tracker/tracking/Tracker.cpp
+++ b/Application/src/tracker/tracking/Tracker.cpp
@@ -70,11 +70,11 @@ namespace track {
     }
     
     //std::map<long_t, std::map<uint32_t, long_t>> automatically_assigned_blobs;
-    std::map<long_t, std::map<Rangel, std::vector<long_t>>> automatically_assigned_ranges;
+    std::map<Idx_t, std::map<Rangel, std::vector<int64_t>>> automatically_assigned_ranges;
     
-    inline std::map<long_t, long_t> automatically_assigned(long_t frame) {
+    inline std::map<Idx_t, long_t> automatically_assigned(long_t frame) {
         //LockGuard guard;
-        std::map<long_t, long_t> blob_for_fish;
+        std::map<Idx_t, long_t> blob_for_fish;
         
         for(auto && [fdx, bff] : automatically_assigned_ranges) {
             blob_for_fish[fdx] = -1;
@@ -82,7 +82,7 @@ namespace track {
             for(auto && [range, blob_ids] : bff) {
                 if(range.contains(frame)) {
                     assert(frame >= range.start && range.end >= frame);
-                    blob_for_fish[fdx] = blob_ids.at(frame - range.start);
+                    blob_for_fish[fdx] = blob_ids.at(sign_cast<size_t>(frame - range.start));
                     break;
                 }
             }
@@ -208,7 +208,7 @@ const FrameProperties* Tracker::properties(long_t frameIndex, const CacheHints*
         stats.print();
     }
 
-    void Tracker::delete_automatic_assignments(long_t fish_id, const FrameRange& frame_range) {
+    void Tracker::delete_automatic_assignments(Idx_t fish_id, const FrameRange& frame_range) {
         auto it = automatically_assigned_ranges.find(fish_id);
         if(it == automatically_assigned_ranges.end()) {
             Except("Cannot find fish %d in automatic assignments");
@@ -249,7 +249,7 @@ void Tracker::analysis_state(AnalysisState pause) {
             _startFrame(-1), _endFrame(-1), _max_individuals(0),
             _background(NULL), _recognition(NULL),
             _approximative_enabled_in_frame(std::numeric_limits<long_t>::lowest()),
-            _inactive_individuals([this](long_t A, long_t B){
+            _inactive_individuals([this](Idx_t A, Idx_t B){
                 auto it = _individuals.find(A);
                 assert(it != _individuals.end());
                 const Individual* a = it->second;
@@ -1681,7 +1681,7 @@ bool operator<(long_t frame, const FrameProperties& props) {
         }
     }
     
-    Individual* Tracker::create_individual(idx_t ID, Tracker::set_of_individuals_t& active_individuals) {
+    Individual* Tracker::create_individual(Idx_t ID, Tracker::set_of_individuals_t& active_individuals) {
         if(_individuals.find(ID) != _individuals.end())
             U_EXCEPTION("Cannot assign identity (%d) twice.", ID);
         
@@ -1976,9 +1976,9 @@ void Tracker::clear_properties() {
         
         // prepare active_individuals array and assign fixed matches for which
         // the individuals already exist
-        std::map<uint32_t, std::set<idx_t>> cannot_find;
-        std::map<uint32_t, std::set<idx_t>> double_find;
-        std::map<uint32_t, idx_t> actually_assign;
+        std::map<uint32_t, std::set<Idx_t>> cannot_find;
+        std::map<uint32_t, std::set<Idx_t>> double_find;
+        std::map<uint32_t, Idx_t> actually_assign;
         
         for(auto && [fdx, bdx] : current_fixed_matches) {
             auto it = _individuals.find(fdx);
@@ -2077,7 +2077,7 @@ void Tracker::clear_properties() {
         }
         
         if(!cannot_find.empty()) {
-            std::map<uint32_t, std::vector<std::tuple<idx_t, Vec2, uint32_t>>> assign_blobs;
+            std::map<uint32_t, std::vector<std::tuple<Idx_t, Vec2, uint32_t>>> assign_blobs;
             
             for(auto && [bdx, fdxs] : cannot_find) {
                 assert(bdx >= 0);
@@ -2098,7 +2098,7 @@ void Tracker::clear_properties() {
             //auto str = prettify_array(Meta::toStr(assign_blobs));
             //Debug("replacing blobids / potentially splitting:\n%S", &str);
             
-            std::map<idx_t, uint32_t> actual_assignments;
+            std::map<Idx_t, uint32_t> actual_assignments;
             
             for(auto && [bdx, clique] : assign_blobs) {
                 //if(clique.size() > 1)
@@ -2240,21 +2240,21 @@ void Tracker::clear_properties() {
             // create correct identities
             //assert(_individuals.empty());
             
-            uint32_t max_id = Identity::running_id();
+            Idx_t max_id(Identity::running_id());
             
             for (auto m : manual_identities) {
                 if(_individuals.find(m) == _individuals.end()) {
-                    Individual *fish = new Individual(m);
+                    Individual *fish = new Individual((uint32_t)m);
                     //fish->identity().set_ID(m);
                     assert(fish->identity().ID() == m);
-                    max_id = max(max_id, m);
+                    max_id = Idx_t(max((uint32_t)max_id, (uint32_t)m));
                     
                     _individuals[m] = fish;
                     //active_individuals.push_back(fish);
                 }
             }
             
-            if(max_id > -1) {
+            if(max_id.valid()) {
                 Identity::set_running_id(max_id + 1);
             }
         }
@@ -2866,7 +2866,7 @@ void Tracker::clear_properties() {
         
 #ifndef NDEBUG
         if(!number_fish) {
-            static std::set<idx_t> lost_ids;
+            static std::set<Idx_t> lost_ids;
             for(auto && [fdx, fish] : _individuals) {
                 if(active_individuals.find(fish) == active_individuals.end() && _inactive_individuals.find(fdx) == _inactive_individuals.end()) {
                     if(lost_ids.find(fdx) != lost_ids.end())
@@ -3004,7 +3004,7 @@ void Tracker::clear_properties() {
         _statistics[frameIndex].posture_seconds = posture_seconds;
     }
 
-void Tracker::update_iterator_maps(long_t frame, const Tracker::set_of_individuals_t& active_individuals, std::unordered_map<long_t, Individual::segment_map::const_iterator>& individual_iterators)
+void Tracker::update_iterator_maps(long_t frame, const Tracker::set_of_individuals_t& active_individuals, std::unordered_map<Idx_t, Individual::segment_map::const_iterator>& individual_iterators)
 {
     for(auto fish : active_individuals) {
         auto fit = individual_iterators.find(fish->identity().ID());
@@ -3039,7 +3039,7 @@ void Tracker::update_iterator_maps(long_t frame, const Tracker::set_of_individua
     }
 }
             
-    void Tracker::update_warnings(long_t frameIndex, double time, long_t /*number_fish*/, long_t n_found, long_t n_prev, const FrameProperties *props, const FrameProperties *prev_props, const Tracker::set_of_individuals_t& active_individuals, std::unordered_map<long_t, Individual::segment_map::const_iterator>& individual_iterators) {
+    void Tracker::update_warnings(long_t frameIndex, double time, long_t /*number_fish*/, long_t n_found, long_t n_prev, const FrameProperties *props, const FrameProperties *prev_props, const Tracker::set_of_individuals_t& active_individuals, std::unordered_map<Idx_t, Individual::segment_map::const_iterator>& individual_iterators) {
         std::map<std::string, std::set<FOI::fdx_t>> merge;
         
         if(n_found < n_prev-1) {
@@ -3082,11 +3082,11 @@ void Tracker::update_iterator_maps(long_t frame, const Tracker::set_of_individua
             if(it != fish->frame_segments().end() && (*it)->contains(frameIndex - 1)) {
                 // prev
                 auto idx = (*it)->basic_stuff(frameIndex - 1);
-                property.prev = idx != -1 ? fish->basic_stuff()[idx]->centroid : nullptr;
+                property.prev = idx != -1 ? fish->basic_stuff()[uint32_t(idx)]->centroid : nullptr;
                 
                 // current
                 idx = (*it)->basic_stuff(frameIndex);
-                property.current = idx != -1 ? fish->basic_stuff()[idx]->centroid : nullptr;
+                property.current = idx != -1 ? fish->basic_stuff()[uint32_t(idx)]->centroid : nullptr;
                 
             } else
                 property.prev = property.current = nullptr;
@@ -3094,7 +3094,7 @@ void Tracker::update_iterator_maps(long_t frame, const Tracker::set_of_individua
         
 #ifndef NDEBUG
         for(auto &fish : active_individuals) {
-            if((long_t)_warn_individual_status.size() <= fish->identity().ID()) {
+            if(_warn_individual_status.size() <= fish->identity().ID()) {
                 assert(!fish->has(frameIndex-1));
                 continue;
             }
@@ -3151,11 +3151,11 @@ void Tracker::update_iterator_maps(long_t frame, const Tracker::set_of_individua
             
 #ifndef NDEBUG
             for(auto id : segment_end) {
-                assert(individuals().at(id.id)->segment_for(frameIndex) != individuals().at(id.id)->segment_for(frameIndex-1));
+                assert(individuals().at(Idx_t(id.id))->segment_for(frameIndex) != individuals().at(Idx_t(id.id))->segment_for(frameIndex-1));
             }
             for(auto id : fdx) {
-                assert(!individuals().at(id.id)->has(frameIndex));
-                assert(frameIndex != start_frame() && _individuals.at(id.id)->has(frameIndex-1));
+                assert(!individuals().at(Idx_t(id.id))->has(frameIndex));
+                assert(frameIndex != start_frame() && _individuals.at(Idx_t(id.id))->has(frameIndex-1));
             }
 #endif
             
@@ -3335,7 +3335,7 @@ void Tracker::update_iterator_maps(long_t frame, const Tracker::set_of_individua
         }
         
         auto manual_identities = FAST_SETTINGS(manual_identities);
-        std::vector<idx_t> to_delete;
+        std::vector<Idx_t> to_delete;
         std::vector<Individual*> ptrs;
         for(auto && [fdx, fish] : _individuals) {
             fish->remove_frame(frameIndex);
@@ -3623,7 +3623,7 @@ void Tracker::update_iterator_maps(long_t frame, const Tracker::set_of_individua
         
         recognition_pool.wait();
         
-        using fdx_t = long_t;
+        using fdx_t = Idx_t;
         using range_t = FrameRange;
         using namespace Match;
         
@@ -3631,10 +3631,10 @@ void Tracker::update_iterator_maps(long_t frame, const Tracker::set_of_individua
             std::set<range_t> segments;
             std::map<range_t, Match::prob_t> probs;
             std::map<range_t, size_t> samples;
-            std::map<Rangel, idx_t> track_ids;
+            std::map<Rangel, Idx_t> track_ids;
         };
         
-        std::map<long_t, std::map<track::idx_t, int64_t>> automatic_matches;
+        std::map<long_t, std::map<Idx_t, int64_t>> automatic_matches;
         std::map<fdx_t, VirtualFish> virtual_fish;
         
         // wrong fish -> set of unassigned ranges
@@ -3648,7 +3648,7 @@ void Tracker::update_iterator_maps(long_t frame, const Tracker::set_of_individua
             return pair0.second < pair1.second;
         };*/
         
-        static const auto compare_greatest = [](const std::pair<long_t, Match::prob_t>& pair0, const std::pair<long_t, Match::prob_t>& pair1)
+        static const auto compare_greatest = [](const std::pair<Idx_t, Match::prob_t>& pair0, const std::pair<Idx_t, Match::prob_t>& pair1)
         {
             return pair0.second > pair1.second;
         };
@@ -3675,7 +3675,7 @@ void Tracker::update_iterator_maps(long_t frame, const Tracker::set_of_individua
                     if(n >= n_lower_bound || (segment.start() == fish->start_frame() && n > 0)) {
                         log(f, "fish %d: segment %d-%d has %d samples", fdx, segment.start(), segment.end(), n);
                         
-                        std::set<std::pair<long_t, Match::prob_t>, decltype(compare_greatest)> sorted(compare_greatest);
+                        std::set<std::pair<Idx_t, Match::prob_t>, decltype(compare_greatest)> sorted(compare_greatest);
                         sorted.insert(average.begin(), average.end());
                         
                         // check if the values for this segment are too close, this probably
@@ -3755,7 +3755,7 @@ void Tracker::update_iterator_maps(long_t frame, const Tracker::set_of_individua
                         virtual_fish[it->first].segments.insert(segment);
                         virtual_fish[it->first].probs[segment] = it->second;
                         virtual_fish[it->first].samples[segment] = n;
-                        virtual_fish[it->first].track_ids[segment.range] = (idx_t)fdx;
+                        virtual_fish[it->first].track_ids[segment.range] = fdx;
                         
                         assigned_ranges[fdx][segment.range] = it->first;
                     }
@@ -3817,7 +3817,7 @@ void Tracker::update_iterator_maps(long_t frame, const Tracker::set_of_individua
                 if(blob && blob->split() && blob->parent_id != -1)
                     manual_splits[segment.start()].insert(blob->parent_id);
                 
-                std::vector<long_t> blob_ids;
+                std::vector<int64_t> blob_ids;
                 for(long_t frame=segment.start(); frame<=segment.end(); ++frame) {
                     blob = track->compressed_blob(frame);
                     if(blob) {
@@ -3851,7 +3851,7 @@ void Tracker::update_iterator_maps(long_t frame, const Tracker::set_of_individua
                             tmp_assigned_ranges[fdx].erase(range);
                         
                         auto str = Meta::toStr(remove_from);
-                        Warning("While assigning %d,%d to %d -> same fish already assigned in ranges %S", frame, blob ? (long_t)blob->blob_id() : -1, fdx, &str);
+                        Warning("While assigning %d,%d to %d -> same fish already assigned in ranges %S", frame, blob ? (int64_t)blob->blob_id() : -1, fdx, &str);
                     }
                 }
                 
@@ -3892,7 +3892,7 @@ void Tracker::update_iterator_maps(long_t frame, const Tracker::set_of_individua
                 }
                 
                 if(next != fish->recognition_segments().end() && /*previous.start() != -1 &&*/ next->second.start() != -1) {
-                    fdx_t prev_id = -1, next_id = -1;
+                    Idx_t prev_id, next_id;
                     PhysicalProperties *prev_pos = nullptr, *next_pos = nullptr;
                     long_t prev_blob = -1;
                     
@@ -3950,7 +3950,7 @@ void Tracker::update_iterator_maps(long_t frame, const Tracker::set_of_individua
                         }
                     }
                     
-                    if(next_id != -1 && prev_id != -1 && next_id == prev_id && prev_pos && next_pos) {
+                    if(next_id.valid() && prev_id.valid() && next_id == prev_id && prev_pos && next_pos) {
                         //Debug("Fish %d: virtual prev_id %d == virtual next_id %d, assigning...", fdx, prev_id, next_id);
                         Vec2 pos_start(FLT_MAX), pos_end(FLT_MAX);
                         auto blob_start = fish->centroid_weighted(segment.start());
@@ -3963,7 +3963,7 @@ void Tracker::update_iterator_maps(long_t frame, const Tracker::set_of_individua
                         if(blob_start && blob_end) {
                             auto dprev = euclidean_distance(prev_pos->pos(), pos_start) / Tracker::time_delta(blob_start->frame(), prev_pos->frame());
                             auto dnext = euclidean_distance(next_pos->pos(), pos_end) / Tracker::time_delta(next_pos->frame(), blob_end->frame());
-                            long_t chosen_id = -1;
+                            Idx_t chosen_id;
                             
                             if(dnext < dprev) {
                                 if(dprev < FAST_SETTINGS(track_max_speed) * 0.1)
@@ -3971,18 +3971,18 @@ void Tracker::update_iterator_maps(long_t frame, const Tracker::set_of_individua
                             } else if(dnext < FAST_SETTINGS(track_max_speed) * 0.1)
                                 chosen_id = prev_id;
                             
-                            if(chosen_id != -1) {
+                            if(chosen_id.valid()) {
                                 if(segment.start() == 0) {
                                     log(f, "Fish %d: chosen_id %d, assigning %d-%d (%f / %f)...", fdx, chosen_id, segment.start(), segment.end(), dprev, dnext);
                                 }
                                 
-                                if(prev_blob != -1 && prev_id != -1) {
+                                if(prev_blob != -1 && prev_id.valid()) {
                                     // we found the previous blob/segment quickly:
-                                    auto range = _individuals.at((idx_t)prev_id)->get_segment_safe(prev_blob);
+                                    auto range = _individuals.at(prev_id)->get_segment_safe(prev_blob);
                                     if(!range.empty()) {
                                         long_t frame = range.end();
                                         while(frame >= range.start()) {
-                                            auto blob = _individuals.at((idx_t)prev_id)->compressed_blob(frame);
+                                            auto blob = _individuals.at(prev_id)->compressed_blob(frame);
                                             if(blob->split()) {
                                                 if(blob->parent_id != -1) {
                                                     //manual_splits[frame].insert(blob->parent_id());
@@ -4013,7 +4013,7 @@ void Tracker::update_iterator_maps(long_t frame, const Tracker::set_of_individua
                                 
                                 std::set<Rangel> remove_from;
                                 
-                                std::vector<long_t> blob_ids;
+                                std::vector<int64_t> blob_ids;
                                 for(long_t frame=segment.start(); frame<=segment.end(); ++frame) {
                                     auto blob = fish->compressed_blob(frame);
                                     
@@ -4039,9 +4039,9 @@ void Tracker::update_iterator_maps(long_t frame, const Tracker::set_of_individua
                                     //    automatically_assigned_ranges[chosen_id].erase(range);
                                     
                                     auto str = Meta::toStr(remove_from);
-                                    Warning("[ignore] While assigning %d-%d to %d -> same fish already assigned in ranges %S", segment.range.start, segment.range.end, chosen_id, &str);
+                                    Warning("[ignore] While assigning %d-%d to %d -> same fish already assigned in ranges %S", segment.range.start, segment.range.end, (uint32_t)chosen_id, &str);
                                 } else {
-                                    assert((long_t)blob_ids.size() == segment.range.end - segment.range.start + 1);
+                                    assert((int64_t)blob_ids.size() == segment.range.end - segment.range.start + 1);
                                     tmp_assigned_ranges[chosen_id][segment.range] = blob_ids;
                                     
                                     auto blob = fish->blob(segment.start());
@@ -4182,7 +4182,7 @@ pv::BlobPtr Tracker::find_blob_noisy(std::map<uint32_t, pv::BlobPtr>& blob_to_id
                         std::vector<uchar> image_data;
                         Size2 shape;
                         
-                        printf("tags for %d: ", fish->identity().ID());
+                        printf("tags for %u: ", (uint32_t)fish->identity().ID());
                         for(auto && [var, bid, ptr, frame] : *set) {
                             shape = Size2(ptr->cols, ptr->rows);
                             // had previous frame, lost in this frame (finalize segment)
diff --git a/Application/src/tracker/tracking/Tracker.h b/Application/src/tracker/tracking/Tracker.h
index 58dd0219f1df572c47bd69b47b10db3e42c9d16f..131ee84d97f6a09f60063b7e10b29abf6994233d 100644
--- a/Application/src/tracker/tracking/Tracker.h
+++ b/Application/src/tracker/tracking/Tracker.h
@@ -10,7 +10,7 @@
 #include <tracking/Border.h>
 #include <misc/Timer.h>
 #include <misc/BlobSizeRange.h>
-
+#include <misc/idx_t.h>
 #include <misc/create_struct.h>
 
 namespace Output {
@@ -34,7 +34,7 @@ namespace track {
         IndividualStatus() : prev(nullptr), current(nullptr) {}
     };
 
-using mmatches_t = std::map<long_t, std::map<idx_t, int64_t>>;
+using mmatches_t = std::map<long_t, std::map<Idx_t, int64_t>>;
 using msplits_t = std::map<long_t, std::set<int64_t>>;
 using inames_t = std::map<uint32_t, std::string>;
 using mapproved_t = std::map<long_t,long_t>;
@@ -68,7 +68,7 @@ CREATE_STRUCT(Settings,
   (float, matching_probability_threshold),
   (size_t, posture_direction_smoothing),
   (file::Path, tags_path),
-  (std::set<uint32_t>, manual_identities),
+  (std::set<Idx_t>, manual_identities),
   (std::vector<Vec2>, grid_points),
   (std::vector<std::vector<Vec2>>, recognition_shapes),
   (float, grid_points_scaling),
@@ -125,7 +125,7 @@ CREATE_STRUCT(Settings,
         uint32_t _current_midline_errors, _overall_midline_errors;
         
         //! All the individuals that have been detected and are being maintained
-        std::unordered_map<idx_t, Individual*> _individuals;
+        std::unordered_map<Idx_t, Individual*> _individuals;
         friend class Individual;
         
         set_of_individuals_t _active_individuals;
@@ -139,8 +139,8 @@ CREATE_STRUCT(Settings,
         GETTER_PTR(StaticBackground*, background)
         Recognition* _recognition;
         
-        std::unordered_map<long_t, Individual::segment_map::const_iterator> _individual_add_iterator_map;
-        std::unordered_map<long_t, size_t> _segment_map_known_capacity;
+        std::unordered_map<Idx_t, Individual::segment_map::const_iterator> _individual_add_iterator_map;
+        std::unordered_map<Idx_t, size_t> _segment_map_known_capacity;
         std::vector<IndividualStatus> _warn_individual_status;
         
     public:
@@ -187,7 +187,7 @@ CREATE_STRUCT(Settings,
         long_t _approximative_enabled_in_frame;
         
         GETTER(std::deque<Range<long_t>>, consecutive)
-        std::set<long_t, std::function<bool(long_t,long_t)>> _inactive_individuals;
+        std::set<Idx_t, std::function<bool(Idx_t,Idx_t)>> _inactive_individuals;
         
     public:
         Tracker();
@@ -231,8 +231,8 @@ CREATE_STRUCT(Settings,
         static const FrameProperties* add_next_frame(const FrameProperties&);
         static void clear_properties();
         
-        static long_t start_frame() { return (long_t)instance()->_startFrame; }
-        static long_t end_frame() { return (long_t)instance()->_endFrame; }
+        static Frame_t start_frame() { return Frame_t(instance()->_startFrame.load()); }
+        static Frame_t end_frame() { return Frame_t(instance()->_endFrame.load()); }
         static size_t number_frames() { return instance()->_added_frames.size(); }
         static bool blob_matches_shapes(const pv::BlobPtr&, const std::vector<std::vector<Vec2>>&);
         
@@ -240,7 +240,7 @@ CREATE_STRUCT(Settings,
         static void preprocess_frame(PPFrame &frame, const std::unordered_set<Individual*>& active_individuals, GenericThreadPool* pool, std::ostream* = NULL, bool do_history_split = true);
         
         friend class VisualField;
-        static const std::unordered_map<idx_t, Individual*>& individuals() {
+        static const std::unordered_map<Idx_t, Individual*>& individuals() {
             LockGuard guard("individuals()");
             return instance()->_individuals;
         }
@@ -265,7 +265,7 @@ CREATE_STRUCT(Settings,
         
         void update_history_log();
         
-        long_t update_with_manual_matches(const std::map<long_t, std::map<idx_t, int64_t>>& manual_matches);
+        long_t update_with_manual_matches(const std::map<long_t, std::map<Idx_t, int64_t>>& manual_matches);
         void check_segments_identities(bool auto_correct, std::function<void(float)> callback, const std::function<void(const std::string&, const std::function<void()>&, const std::string&)>& add_to_queue = [](auto,auto,auto){}, long_t after_frame = -1);
         void clear_segments_identities();
         void prepare_shutdown();
@@ -282,7 +282,7 @@ CREATE_STRUCT(Settings,
         static void global_segment_order_changed();
         static void auto_calculate_parameters(pv::File& video, bool quiet = false);
         static void emergency_finish();
-        static void delete_automatic_assignments(long_t fish_id, const FrameRange& frame_range);
+        static void delete_automatic_assignments(Idx_t fish_id, const FrameRange& frame_range);
         
         enum class AnalysisState {
             PAUSED,
@@ -298,7 +298,7 @@ CREATE_STRUCT(Settings,
         }
         
         void update_consecutive(const set_of_individuals_t& active, long_t frameIndex, bool update_dataset = false);
-        void update_warnings(long_t frameIndex, double time, long_t number_fish, long_t n_found, long_t n_prev, const FrameProperties *props, const FrameProperties *prev_props, const set_of_individuals_t& active_individuals, std::unordered_map<long_t, Individual::segment_map::const_iterator>& individual_iterators);
+        void update_warnings(long_t frameIndex, double time, long_t number_fish, long_t n_found, long_t n_prev, const FrameProperties *props, const FrameProperties *prev_props, const set_of_individuals_t& active_individuals, std::unordered_map<Idx_t, Individual::segment_map::const_iterator>& individual_iterators);
         
     private:
         static void filter_blobs(PPFrame& frame, GenericThreadPool *pool);
@@ -326,7 +326,7 @@ CREATE_STRUCT(Settings,
         void generate_pairdistances(long_t frameIndex);
         void check_save_tags(long_t frameIndex, const std::unordered_map<uint32_t, Individual*>&, const std::vector<tags::blob_pixel>&, const std::vector<tags::blob_pixel>&, const file::Path&);
         
-        Individual* create_individual(idx_t ID, set_of_individuals_t& active_individuals);
+        Individual* create_individual(Idx_t ID, set_of_individuals_t& active_individuals);
         
         struct PrefilterBlobs {
             std::vector<pv::BlobPtr> filtered;
@@ -350,7 +350,7 @@ CREATE_STRUCT(Settings,
         
         static void prefilter(std::shared_ptr<PrefilterBlobs>, std::vector<pv::BlobPtr>::const_iterator it, std::vector<pv::BlobPtr>::const_iterator end);
         
-        void update_iterator_maps(long_t frame, const set_of_individuals_t& active_individuals, std::unordered_map<long_t, Individual::segment_map::const_iterator>& individual_iterators);
+        void update_iterator_maps(long_t frame, const set_of_individuals_t& active_individuals, std::unordered_map<Idx_t, Individual::segment_map::const_iterator>& individual_iterators);
     };
 }
 
diff --git a/Application/src/tracker/tracking/TrainingData.cpp b/Application/src/tracker/tracking/TrainingData.cpp
index 8d758d56a3435eb6fae544807dbaf4013eb4cd7c..aa5f6f59ce9761a96623173f8ef2ce6255e7d457 100644
--- a/Application/src/tracker/tracking/TrainingData.cpp
+++ b/Application/src/tracker/tracking/TrainingData.cpp
@@ -107,7 +107,7 @@ TrainingData::DataRange::operator MetaObject() const {
     return MetaObject(ss.str(), "DataRange");
 }
 
-void TrainingData::add_frame(std::shared_ptr<TrainingData::DataRange> data, long_t frame_index, long_t id, long_t original_id, Image::Ptr image, const Vec2 & pos, size_t px, const FrameRange& from_range)
+void TrainingData::add_frame(std::shared_ptr<TrainingData::DataRange> data, long_t frame_index, Idx_t id, int64_t original_id, Image::Ptr image, const Vec2 & pos, size_t px, const FrameRange& from_range)
 {
     /*auto it = original_ids_check.find(image.get());
     if(it  == original_ids_check.end())
@@ -175,7 +175,7 @@ void TrainingData::add_frame(std::shared_ptr<TrainingData::DataRange> data, long
         _all_classes.insert(id);
 }
 
-void TrainingData::apply_mapping(const std::map<long_t, long_t>& mapping) {
+void TrainingData::apply_mapping(const std::map<Idx_t, Idx_t>& mapping) {
     bool found = false;
     for(auto && [id, ID] : mapping) {
         if(id != ID) {
@@ -201,7 +201,7 @@ void TrainingData::apply_mapping(const std::map<long_t, long_t>& mapping) {
             Debug("Changed mapping with %S for %d-%d", &str, data->frames.start, data->frames.end);
         }
         
-        std::map<long_t, DataRange::PerIndividual> map;
+        std::map<Idx_t, DataRange::PerIndividual> map;
         for(auto && [from, to] : mapping) {
             auto it = data->mappings.find(from);
             if(it != data->mappings.end())
@@ -237,11 +237,11 @@ void TrainingData::apply_mapping(const std::map<long_t, long_t>& mapping) {
     }
 }
 
-void TrainingData::set_classes(const std::set<uint32_t>& classes) {
+void TrainingData::set_classes(const std::set<Idx_t>& classes) {
     _all_classes = classes;
 }
 
-std::unique_ptr<Image> TrainingData::draw_coverage(const std::map<uint32_t, float>& unique_percentages, const std::vector<Rangel>& next_ranges, const std::vector<Rangel>& added_ranges, const std::map<uint32_t, float>& uniquenesses_temp, std::shared_ptr<TrainingData::DataRange> current_salt, const std::map<Rangel, std::tuple<double, FrameRange>>& assigned_unique_averages) const
+std::unique_ptr<Image> TrainingData::draw_coverage(const std::map<Frame_t, float>& unique_percentages, const std::vector<Rangel>& next_ranges, const std::vector<Rangel>& added_ranges, const std::map<Frame_t, float>& uniquenesses_temp, std::shared_ptr<TrainingData::DataRange> current_salt, const std::map<Rangel, std::tuple<double, FrameRange>>& assigned_unique_averages) const
 {
     auto analysis_range = Tracker::analysis_range();
     auto image = std::make_unique<Image>(500, 1800, 4);
@@ -255,7 +255,7 @@ std::unique_ptr<Image> TrainingData::draw_coverage(const std::map<uint32_t, floa
     float row_height = float(image->rows) / float(rows);
     float column_width = float(image->cols) / float(analysis_range.length());
     
-    auto draw_range = [column_width, row_height, analysis_range, &colors](cv::Mat& mat, const Rangel& range, long_t id, uint8_t alpha = 200){
+    auto draw_range = [column_width, row_height, analysis_range, &colors](cv::Mat& mat, const Rangel& range, Idx_t id, uint8_t alpha = 200){
         Vec2 topleft((range.start - analysis_range.start) * column_width, row_height * id);
         Vec2 bottomright((range.end - analysis_range.start) * column_width, row_height * (id + 1));
         cv::rectangle(mat, topleft, bottomright, colors[id].alpha(alpha * 0.5), cv::FILLED);
@@ -538,9 +538,9 @@ size_t TrainingData::size() const {
     return n;
 }
 
-std::tuple<std::vector<Image::Ptr>, std::vector<long_t>> TrainingData::join_arrays() const {
+std::tuple<std::vector<Image::Ptr>, std::vector<Idx_t>> TrainingData::join_arrays() const {
     std::vector<Image::Ptr> images;
-    std::vector<long_t> ids;
+    std::vector<Idx_t> ids;
     
     const size_t L = size();
     ids.reserve(L);
@@ -621,12 +621,12 @@ typename std::vector<T>::iterator
         );
 }
 
-long_t TrainingData::DataRange::map(long_t id) const {
+Idx_t TrainingData::DataRange::map(Idx_t id) const {
     if(applied_mapping.empty()) return id;
     return applied_mapping.at(id);
 }
 
-long_t TrainingData::DataRange::unmap(long_t id) const {
+Idx_t TrainingData::DataRange::unmap(Idx_t id) const {
     if(applied_mapping.empty()) return id;
     for (auto && [original, mapped] : applied_mapping) {
         if(mapped == id) {
@@ -647,7 +647,7 @@ void TrainingData::DataRange::reverse_mapping() {
     auto str = Meta::toStr(applied_mapping);
     Debug("Reversing mapping with %S for %d-%d", &str, frames.start, frames.end);
     
-    std::map<long_t, DataRange::PerIndividual> map;
+    std::map<Idx_t, DataRange::PerIndividual> map;
     for(auto && [to, from] : applied_mapping) {
         auto it = mappings.find(from);
         if(it != mappings.end()) {
@@ -664,12 +664,12 @@ void TrainingData::DataRange::reverse_mapping() {
 std::shared_ptr<TrainingData::DataRange> TrainingData::add_salt(const std::shared_ptr<TrainingData>& source, const std::string& purpose) {
     const size_t Nmax = 1000;
     
-    std::map<long_t, std::set<FrameRange>> individual_ranges;
-    std::map<long_t, std::tuple<size_t, size_t>> individual_samples;
+    std::map<Idx_t, std::set<FrameRange>> individual_ranges;
+    std::map<Idx_t, std::tuple<size_t, size_t>> individual_samples;
     
-    std::map<long_t, std::vector<FrameRange>> combined_ranges_per_individual;
+    std::map<Idx_t, std::vector<FrameRange>> combined_ranges_per_individual;
     
-    auto add_combined_range = [&combined_ranges_per_individual](const FrameRange& range, long_t id) {
+    auto add_combined_range = [&combined_ranges_per_individual](const FrameRange& range, Idx_t id) {
         auto& combined_ranges = combined_ranges_per_individual[id];
         
         bool found = false;
@@ -747,8 +747,8 @@ std::shared_ptr<TrainingData::DataRange> TrainingData::add_salt(const std::share
             maximum_samples_per_individual = sum;
     }
     
-    std::map<long_t, std::set<std::tuple<FrameRange, const DataRange::PerIndividual*, const DataRange*, long_t>>> ranges_to_add;
-    std::map<long_t, std::set<long_t>> source_frames_per_individual;
+    std::map<Idx_t, std::set<std::tuple<FrameRange, const DataRange::PerIndividual*, const DataRange*, long_t>>> ranges_to_add;
+    std::map<Idx_t, std::set<long_t>> source_frames_per_individual;
     
     auto add_range = std::make_shared<DataRange>(true);
     for(auto &d : data()) {
@@ -778,8 +778,8 @@ std::shared_ptr<TrainingData::DataRange> TrainingData::add_salt(const std::share
     }
     
     // add maximum of Nmax images per individual
-    std::map<long_t, std::tuple<size_t, size_t, size_t, size_t>> individual_added_salt;
-    std::map<long_t, std::tuple<size_t, size_t>> individual_samples_before_after;
+    std::map<Idx_t, std::tuple<size_t, size_t, size_t, size_t>> individual_added_salt;
+    std::map<Idx_t, std::tuple<size_t, size_t>> individual_samples_before_after;
     
     const double number_classes = SETTING(track_max_individuals).value<uint32_t>();
     const double gpu_max_sample_mb = double(SETTING(gpu_max_sample_gb).value<float>()) * 1000;
@@ -817,7 +817,7 @@ std::shared_ptr<TrainingData::DataRange> TrainingData::add_salt(const std::share
         
         size_t actually_added = 0;
         for(auto && [range, ptr, d, ID] : ranges) {
-            long_t step_size = max(1, ceil(SR / (max_images_per_class * double(range.length()) / double(N))));
+            size_t step_size = max(1u, (size_t)ceil(SR / (max_images_per_class * double(range.length()) / double(N))));
             
             std::vector<std::tuple<long_t, Image::Ptr, Vec2, size_t>> frames;
             for(size_t i=0; i<ptr->frame_indexes.size(); ++i) {
@@ -865,7 +865,7 @@ std::shared_ptr<TrainingData::DataRange> TrainingData::add_salt(const std::share
     return add_range;
 }
 
-bool TrainingData::generate(const std::string& step_description, pv::File & video_file, std::map<long_t, std::set<long_t> > individuals_per_frame, const std::function<void(float)>& callback, const TrainingData* source) {
+bool TrainingData::generate(const std::string& step_description, pv::File & video_file, std::map<Frame_t, std::set<Idx_t> > individuals_per_frame, const std::function<void(float)>& callback, const TrainingData* source) {
     auto frames = extract_keys(individuals_per_frame);
     
     Tracker::LockGuard guard("generate_training_data");
@@ -873,8 +873,7 @@ bool TrainingData::generate(const std::string& step_description, pv::File & vide
     const Size2 output_size = SETTING(recognition_image_size);
     const auto& custom_midline_lengths = filters();
     
-    std::map<long_t, std::set<long_t>> illegal_frames;
-    //std::map<long_t, std::set<long_t>> add_from_source;
+    std::map<Idx_t, std::set<Frame_t>> illegal_frames;
     
     for(auto && [frame, ids] : individuals_per_frame) {
         for(auto id : ids) {
@@ -901,13 +900,13 @@ bool TrainingData::generate(const std::string& step_description, pv::File & vide
         }
     }
     
-    std::map<long_t, long_t> lengths;
+    std::map<Idx_t, double> lengths;
     for(auto && [frame, ids] : individuals_per_frame) {
         for(auto id : ids)
             ++lengths[id];
     }
     
-    long_t fewest_samples = std::numeric_limits<long_t>::max(), most_samples = 0;
+    double fewest_samples = std::numeric_limits<double>::max(), most_samples = 0;
     for(auto && [id, L] : lengths) {
         if(L < fewest_samples)
             fewest_samples = L;
@@ -915,7 +914,7 @@ bool TrainingData::generate(const std::string& step_description, pv::File & vide
             most_samples = L;
     }
     
-    if(fewest_samples == std::numeric_limits<long_t>::max())
+    if(fewest_samples == std::numeric_limits<size_t>::max())
         fewest_samples = most_samples = 0;
     
     const double number_classes = FAST_SETTINGS(manual_identities).size();
@@ -935,7 +934,7 @@ bool TrainingData::generate(const std::string& step_description, pv::File & vide
     // sub-sample any classes that need sub-sampling
     for(auto && [id, L] : lengths) {
         if(L > percentile) {
-            float step_size = percentile / L;
+            auto step_size = percentile / L;
             //if(step_size == 1)
             //    continue;
             
@@ -943,9 +942,9 @@ bool TrainingData::generate(const std::string& step_description, pv::File & vide
             
             // collect all frames where this individual is present
             
-            std::set<long_t> empty_frames;
-            long_t count = 0, after = 0;
-            float acc = 0;
+            std::set<Frame_t> empty_frames;
+            size_t count = 0, after = 0;
+            double acc = 0;
             
             for(auto && [frame, ids] : individuals_per_frame) {
                 if(ids.find(id) != ids.end()) {
@@ -985,10 +984,9 @@ bool TrainingData::generate(const std::string& step_description, pv::File & vide
     Size2 minmum_size(FLT_MAX), maximum_size(0);
     Median<Float2_t> median_size_x, median_size_y;
     long_t inserted_start = std::numeric_limits<long_t>::max(), inserted_end = -1;
-    std::map<long_t, std::set<FrameRange>> added_from_source;
     
     // copy available images to map for easy access
-    std::map<long_t, std::map<long_t, std::tuple<long_t, Image::Ptr>>> available_images;
+    std::map<Idx_t, std::map<long_t, std::tuple<long_t, Image::Ptr>>> available_images;
     if(source) {
         for(auto & data : source->data()) {
             for(auto && [id, per] : data->mappings) {
@@ -1027,7 +1025,7 @@ bool TrainingData::generate(const std::string& step_description, pv::File & vide
     size_t N_validation_images = 0, N_training_images = 0;
     size_t N_reused_images = 0;
     const bool calculate_posture = FAST_SETTINGS(calculate_posture);
-    std::map<long_t, std::vector<std::tuple<long_t, Image::Ptr>>> individual_training_images;
+    std::map<Idx_t, std::vector<std::tuple<long_t, Image::Ptr>>> individual_training_images;
     size_t failed_blobs = 0, found_blobs = 0;
     
     for(auto frame : frames) {
@@ -1043,11 +1041,11 @@ bool TrainingData::generate(const std::string& step_description, pv::File & vide
         }
         
         // check so that we do not generate images again, that we have generated before
-        std::set<long_t> filtered_ids;
+        std::set<Idx_t> filtered_ids;
         
         for(auto id : FAST_SETTINGS(manual_identities)) {
-            if(individuals_per_frame.at(frame).find(id) != individuals_per_frame.at(frame).end())
-                filtered_ids.insert(id);
+            if(individuals_per_frame.at(frame).find(Idx_t(id)) != individuals_per_frame.at(frame).end())
+                filtered_ids.insert(Idx_t(id));
         }
         
         if(frame < inserted_start)
@@ -1252,9 +1250,9 @@ bool TrainingData::generate(const std::string& step_description, pv::File & vide
     return N_training_images + N_validation_images > 0;
 }
 
-std::tuple<std::vector<Image::Ptr>, std::vector<long_t>, std::vector<long_t>, std::map<long_t, Range<size_t>>> TrainingData::join_arrays_ordered() const
+std::tuple<std::vector<Image::Ptr>, std::vector<Idx_t>, std::vector<long_t>, std::map<Frame_t, Range<size_t>>> TrainingData::join_arrays_ordered() const
 {
-    using fdx_t = long_t;
+    using fdx_t = Idx_t;
     using frame_t = long_t;
     
     std::vector<Image::Ptr> images;
@@ -1282,11 +1280,11 @@ std::tuple<std::vector<Image::Ptr>, std::vector<long_t>, std::vector<long_t>, st
         }
     }
     
-    std::map<frame_t, Range<size_t>> start_indexes;
+    std::map<Frame_t, Range<size_t>> start_indexes;
     
     for(auto && [frame, data] : collector) {
         auto & [_ids, _images] = data;
-        start_indexes[frame] = Range<size_t>(ids.size(), ids.size() + _ids.size());
+        start_indexes[Frame_t(frame)] = Range<size_t>(ids.size(), ids.size() + _ids.size());
         
         images.insert(images.end(), _images.begin(), _images.end());
         ids.insert(ids.end(), _ids.begin(), _ids.end());
diff --git a/Application/src/tracker/tracking/TrainingData.h b/Application/src/tracker/tracking/TrainingData.h
index 3f561636dc908e93e05fa7356f1eea592aaf2795..1fe72ed74fd0520dc3c1f1f0f9ec76bb8268bb95 100644
--- a/Application/src/tracker/tracking/TrainingData.h
+++ b/Application/src/tracker/tracking/TrainingData.h
@@ -5,6 +5,7 @@
 #include <misc/Image.h>
 #include <pv.h>
 #include <tracker/misc/default_config.h>
+#include <tracker/misc/idx_t.h>
 
 namespace track {
 
@@ -39,10 +40,10 @@ public:
             std::set<FrameRange> ranges;
         };
         
-        std::map<long_t, PerIndividual> mappings;
-        std::map<long_t, long_t> applied_mapping;
-        std::set<long_t> classes;
-        std::vector<long_t> ids;
+        std::map<Idx_t, PerIndividual> mappings;
+        std::map<Idx_t, Idx_t> applied_mapping;
+        std::set<Idx_t> classes;
+        std::vector<Idx_t> ids;
         std::vector<Image::Ptr> images;
         
         Rangel frames;
@@ -54,8 +55,8 @@ public:
         
         DataRange(bool salt = false) : frames(-1, -1), salty(salt) {}
         
-        long_t map(long_t) const;
-        long_t unmap(long_t) const;
+        Idx_t map(Idx_t) const;
+        Idx_t unmap(Idx_t) const;
         void reverse_mapping();
         
         operator MetaObject() const;
@@ -65,13 +66,13 @@ public:
     };
     
     struct MidlineFilters {
-        std::map<long_t, std::map<FrameRange, TrainingFilterConstraints>> filters;
+        std::map<Idx_t, std::map<FrameRange, TrainingFilterConstraints>> filters;
         
         MidlineFilters(const decltype(filters)& filters = {})
             : filters(filters)
         {}
         
-        bool has(long_t ID, const FrameRange& range = FrameRange()) const {
+        bool has(Idx_t ID, const FrameRange& range = FrameRange()) const {
             if(range.empty())
                 return filters.count(ID) != 0;
             else {
@@ -89,7 +90,7 @@ public:
             }
         }
         
-        bool has(long_t ID, long_t frame) const {
+        bool has(Idx_t ID, long_t frame) const {
             auto it = filters.find(ID);
             if(it == filters.end())
                 return false;
@@ -112,7 +113,7 @@ public:
             return false;
         }
         
-        void set(long_t ID, const TrainingFilterConstraints& filter) {
+        void set(Idx_t ID, const TrainingFilterConstraints& filter) {
             if(has(ID))
                 Warning("[TrainingFilter] %d is already present. Replacing.", ID);
             
@@ -121,7 +122,7 @@ public:
             filters[ID][FrameRange()] = filter;
         }
         
-        void set(long_t ID, const FrameRange& range, const TrainingFilterConstraints& filter) {
+        void set(Idx_t ID, const FrameRange& range, const TrainingFilterConstraints& filter) {
             if(has(ID, range))
                 Warning("[TrainingFilter] %d in range %d-%d is already present. Replacing.", ID, range.start(), range.end());
             if(filters[ID].find(FrameRange()) != filters[ID].end())
@@ -130,7 +131,7 @@ public:
             filters[ID][range] = filter;
         }
         
-        const TrainingFilterConstraints& get(long_t ID, long_t frame) const {
+        const TrainingFilterConstraints& get(Idx_t ID, long_t frame) const {
             auto fit = filters.find(ID);
             if(fit == filters.end())
                 U_EXCEPTION("Cannot find ID %d in TrainingFilterConstraints.", ID);
@@ -163,10 +164,10 @@ private:
     
     using d_type = std::set<std::shared_ptr<DataRange>>;
     GETTER(d_type, data)
-    GETTER(std::set<uint32_t>, all_classes)
+    GETTER(std::set<Idx_t>, all_classes)
     GETTER_NCONST(MidlineFilters, filters)
     
-    using s_type = std::map<uint32_t, std::set<FrameRange>>;
+    using s_type = std::map<Idx_t, std::set<FrameRange>>;
     GETTER(s_type, included_segments)
     
     //FrameRanges frames;
@@ -190,9 +191,9 @@ public:
     class TrainingImageData : public Image::CustomData {
     public:
         ImageClass type;
-        const long_t original_id;
+        const int64_t original_id;
         const std::string source;
-        TrainingImageData(std::string source, long_t oid) : type(ImageClass::NONE), original_id(oid), source(source) {}
+        TrainingImageData(std::string source, int64_t oid) : type(ImageClass::NONE), original_id(oid), source(source) {}
         ~TrainingImageData() {}
     };
     
@@ -224,26 +225,26 @@ public:
     }
     
     TrainingAndValidation join_split_data() const;
-    std::tuple<std::vector<Image::Ptr>, std::vector<long_t>> join_arrays() const;
-    std::tuple<std::vector<Image::Ptr>, std::vector<long_t>, std::vector<long_t>, std::map<long_t, Range<size_t>>> join_arrays_ordered() const;
+    std::tuple<std::vector<Image::Ptr>, std::vector<Idx_t>> join_arrays() const;
+    std::tuple<std::vector<Image::Ptr>, std::vector<Idx_t>, std::vector<long_t>, std::map<Frame_t, Range<size_t>>> join_arrays_ordered() const;
     
-    bool generate(const std::string& step_description, pv::File& video_file, std::map<long_t, std::set<long_t> > individuals_per_frame, const std::function<void(float)>& callback, const TrainingData* source);
+    bool generate(const std::string& step_description, pv::File& video_file, std::map<Frame_t, std::set<Idx_t> > individuals_per_frame, const std::function<void(float)>& callback, const TrainingData* source);
     
     //bool generate(pv::File& video_file, const std::map<long_t, std::set<FrameRange>>&, const std::function<void(float)>& callback);
     
     std::shared_ptr<DataRange> add_salt(const std::shared_ptr<TrainingData>& source, const std::string& purpose);
     
-    void add_frame(std::shared_ptr<DataRange> ptr, long_t frame_index, long_t id, long_t original_id, Image::Ptr image, const Vec2& pos, size_t px, const FrameRange& from_range);
-    void apply_mapping(const std::map<long_t, long_t>&);
+    void add_frame(std::shared_ptr<DataRange> ptr, long_t frame_index, Idx_t id, int64_t original_id, Image::Ptr image, const Vec2& pos, size_t px, const FrameRange& from_range);
+    void apply_mapping(const std::map<Idx_t, Idx_t>&);
     operator MetaObject() const;
     static std::string class_name() {
         return "TrainingData";
     }
     
     //! used as an override for when data is just used to initialize the network and nothing more.
-    void set_classes(const std::set<uint32_t>& classes);
+    void set_classes(const std::set<Idx_t>& classes);
     
-    std::unique_ptr<Image> draw_coverage(const std::map<uint32_t, float>& uniquenesses = {}, const std::vector<Rangel>& = {}, const std::vector<Rangel>& added_ranges = {}, const std::map<uint32_t, float>& uniquenesses_temp = {}, std::shared_ptr<DataRange> current_salt = nullptr, const std::map<Rangel, std::tuple<double, FrameRange>>& assigned_unique_averages = {}) const;
+    std::unique_ptr<Image> draw_coverage(const std::map<Frame_t, float>& uniquenesses = {}, const std::vector<Rangel>& = {}, const std::vector<Rangel>& added_ranges = {}, const std::map<Frame_t, float>& uniquenesses_temp = {}, std::shared_ptr<DataRange> current_salt = nullptr, const std::map<Rangel, std::tuple<double, FrameRange>>& assigned_unique_averages = {}) const;
 };
 
 }
diff --git a/Application/src/tracker/tracking/VisualField.cpp b/Application/src/tracker/tracking/VisualField.cpp
index 0da695d4de7e86d06a7c801fb13233d3b478d8c3..15acdc5761514578206863ad6b5640337407fe01 100644
--- a/Application/src/tracker/tracking/VisualField.cpp
+++ b/Application/src/tracker/tracking/VisualField.cpp
@@ -8,7 +8,7 @@
 namespace track {
     static constexpr double right_angle = RADIANS(90);
     
-    VisualField::VisualField(uint32_t fish_id, long_t frame, const std::shared_ptr<Individual::BasicStuff>& basic, const std::shared_ptr<Individual::PostureStuff>& posture, bool blocking)
+    VisualField::VisualField(Idx_t fish_id, long_t frame, const std::shared_ptr<Individual::BasicStuff>& basic, const std::shared_ptr<Individual::PostureStuff>& posture, bool blocking)
     : max_d(SQR(Tracker::average().cols) + SQR(Tracker::average().rows)), _fish_id(fish_id), _frame(frame)
     {
         calculate(basic, posture, blocking);
@@ -16,8 +16,8 @@ namespace track {
     
     template<typename T>
     inline void correct_angle(T& angle) {
-        while (angle > M_PI) angle -= M_PI*2;
-        while (angle <= -M_PI) angle += M_PI*2;
+        while (angle > T(M_PI)) angle -= T(M_PI)*2;
+        while (angle <= -T(M_PI)) angle += T(M_PI)*2;
     }
     
     template<typename K, typename T = K, typename V = K>
@@ -48,7 +48,7 @@ namespace track {
             std::get<1>(t) = -1;
     };
     
-    void VisualField::plot_projected_line(eye& e, std::tuple<float, float>& tuple, double d, const Vec2& point, idx_t id, float hd)
+    void VisualField::plot_projected_line(eye& e, std::tuple<float, float>& tuple, double d, const Vec2& point, Idx_t id, float hd)
     {
         auto x0 = std::get<0>(tuple), x1 = std::get<1>(tuple);
         if(x0 == x1 && x0 == -1)
@@ -494,15 +494,15 @@ namespace track {
                     auto cd = distances[j]->get().row(int(i+range-frameNr));
                     
                     for(int i=0; i<(int)ids[j]->cols; i++) {
-                        auto id = e._visible_ids[i];
+                        auto id = e._visible_ids[i] != -1 ? Idx_t(e._visible_ids[i]) : Idx_t();
                         auto d = 255 - min(255, e._visible_head_distance[i]);
                         
                         Color clr(Black);
-                        if(id != -1) {
+                        if(id.valid()) {
                             if(id == selected->identity().ID())
                                 clr = White;
                             else {
-                                auto it = Tracker::individuals().find((idx_t)id);
+                                auto it = Tracker::individuals().find(id);
                                 if(it != Tracker::individuals().end()) {
                                     clr = it->second->identity().color().alpha(e._fov.data()[i]);
                                 }
diff --git a/Application/src/tracker/tracking/VisualField.h b/Application/src/tracker/tracking/VisualField.h
index e46aae3c86bfed8a13b7c19a1a722e35374866f4..1f0e7e5cbfddf0e236eedbe1cae63b283386868c 100644
--- a/Application/src/tracker/tracking/VisualField.h
+++ b/Application/src/tracker/tracking/VisualField.h
@@ -43,17 +43,17 @@ namespace track {
         GETTER(Vec2, fish_pos)
         GETTER(double, fish_angle)
         
-        GETTER(uint32_t, fish_id)
+        GETTER(Idx_t, fish_id)
         GETTER(long_t, frame)
         
     public:
-        VisualField(uint32_t fish_id, long_t frame,const std::shared_ptr<Individual::BasicStuff>& basic, const std::shared_ptr<Individual::PostureStuff>& posture, bool blocking);
+        VisualField(Idx_t fish_id, long_t frame,const std::shared_ptr<Individual::BasicStuff>& basic, const std::shared_ptr<Individual::PostureStuff>& posture, bool blocking);
         
         const decltype(_eyes)& eyes() const { return _eyes; }
         void calculate(const std::shared_ptr<Individual::BasicStuff>& basic, const std::shared_ptr<Individual::PostureStuff>& posture, bool blocking = true);
         void show(gui::DrawStructure &graph);
         static void show_ts(gui::DrawStructure &graph, long_t frameNr, Individual* selected);
-        void plot_projected_line(eye& e, std::tuple<float, float>& tuple, double d, const Vec2& point, idx_t id, float hd);
+        void plot_projected_line(eye& e, std::tuple<float, float>& tuple, double d, const Vec2& point, Idx_t id, float hd);
     };
 }
 
diff --git a/docs/parameters_trex.rst b/docs/parameters_trex.rst
index 0509ccca9ad533a0d83f42f811bc5417a300a3ff..88d84773f0820a00f873dadeaec43585476355fc 100644
--- a/docs/parameters_trex.rst
+++ b/docs/parameters_trex.rst
@@ -565,7 +565,7 @@ TRex parameters
 
 
 
-.. function:: gui_focus_group(array<uint>)
+.. function:: gui_focus_group(array<Idx_t>)
 
 	**default value:** []
 
@@ -1112,7 +1112,7 @@ TRex parameters
 
 
 
-.. function:: manual_identities(set<uint>)
+.. function:: manual_identities(set<Idx_t>)
 
 	**default value:** []
 
@@ -1121,7 +1121,7 @@ TRex parameters
 
 
 
-.. function:: manual_matches(map<int,map<int,int64>>)
+.. function:: manual_matches(map<int,map<Idx_t,int64>>)
 
 	**default value:** {}
 
@@ -1900,7 +1900,7 @@ TRex parameters
 
 .. function:: version(string)
 
-	**default value:** "1.0.4"
+	**default value:** "1.0.5"
 
 
 	Current application version.