void BSlowContextMenu::ClearMenu() { RemoveItems(0, CountItems(), true); fMenuBuilt = false; }
void DormantNodeView::_updateList( int32 addOnID) { D_INTERNAL(("DormantNodeView::_updateList(%ld)\n", addOnID)); // init the resizable node-info buffer BMediaRoster *roster = BMediaRoster::CurrentRoster(); const int32 bufferInc = 64; int32 bufferSize = bufferInc; dormant_node_info *infoBuffer = new dormant_node_info[bufferSize]; int32 numNodes; // fill the buffer while (true) { numNodes = bufferSize; status_t error = roster->GetDormantNodes(infoBuffer, &numNodes); if (error) { return; } if (numNodes < bufferSize) { break; } // reallocate buffer & try again delete [] infoBuffer; bufferSize += bufferInc; infoBuffer = new dormant_node_info[bufferSize]; } // sort the list by add-on id to avoid multiple searches through // the list SortItems(compareAddOnID); // Remove all nodes managed by this add-on int32 start; for (start = 0; start < CountItems(); start++) { DormantNodeListItem *item = dynamic_cast<DormantNodeListItem *>(ItemAt(start)); if (item && (item->info().addon == addOnID)) { break; } } int32 count = 0; for (int32 i = start; start < CountItems(); i++) { DormantNodeListItem *item = dynamic_cast<DormantNodeListItem *>(ItemAt(i)); if (!item || (item->info().addon != addOnID)) { break; } count++; } RemoveItems(start, count); // add the items for (int32 i = 0; i < numNodes; i++) { if (infoBuffer[i].addon != addOnID) { continue; } AddItem(new DormantNodeListItem(infoBuffer[i])); } SortItems(compareName); }
bool ColumnListView::RemoveItem(CLVListItem* item) { if(item == NULL || !fFullItemList.HasItem(item)) return false; if(fHierarchical) { int32 ItemsToRemove = 1 + FullListNumberOfSubitems(item); return RemoveItems(fFullItemList.IndexOf(item),ItemsToRemove); } else return BListView::RemoveItem((BListItem*)item); }
void TExpandoMenuBar::DetachedFromWindow() { BMenuBar::DetachedFromWindow(); StopMonitoringWindows(); BMessenger self(this); BMessage message(kUnsubscribe); message.AddMessenger("messenger", self); be_app->PostMessage(&message); RemoveItems(0, CountItems(), true); }
void BSlowContextMenu::ClearMenuBuildingState() { delete fContainer; fContainer = NULL; // item list is non-owning, need to delete the items because // they didn't get added to the menu if (fItemList) { RemoveItems(0, fItemList->CountItems(), true); delete fItemList; fItemList = NULL; } }
void TMenu::BuildMenu() { RemoveItems(0, CountItems(), true); add_query_menu_items(this, fAttribute, fMessage, NULL, fPopup); if (fAddRandom && CountItems() > 0) { AddItem(new BSeparatorItem(), 0); BMessage *msg = new BMessage(M_RANDOM_SIG); if (!fPopup) { AddItem(new BMenuItem(B_TRANSLATE("Random"), msg, '0'), 0); } else { AddItem(new BMenuItem(B_TRANSLATE("Random"), msg), 0); } } }
BListItem* ColumnListView::RemoveItem(int32 fullListIndex) { if(fHierarchical) { CLVListItem* TheItem = (CLVListItem*)fFullItemList.ItemAt(fullListIndex); if(TheItem) { int32 ItemsToRemove = 1 + FullListNumberOfSubitems(TheItem); if(RemoveItems(fullListIndex,ItemsToRemove)) return TheItem; else return NULL; } else return NULL; } else return BListView::RemoveItem(fullListIndex); }
void HandleScriptEffect(SpellEffIndex /* effIndex */) { if (Player* player = GetHitPlayer()) { for (uint8 i = 0; i < 21; ++i) { if (player->HasAura(FetchIngredients[i][0])) { player->CastSpell(player, SPELL_THROW_INGREDIENT); player->RemoveAura(FetchIngredients[i][0]); if (player->HasAura(FetchIngredients[i][1])) { player->RemoveAura(FetchIngredients[i][1]); player->DestroyItemCount(FetchIngredients[i][2], 1, true); if (i < 15) { if (Creature* finklestein = GetClosestCreatureWithEntry(player, NPC_FINKLESTEIN, 25.0f)) finklestein->AI()->SetData(1, 1); return; } else { if (player->GetQuestStatus(QUEST_THE_ALCHEMIST_APPRENTICE_DAILY) == QUEST_STATUS_INCOMPLETE) { player->RemoveAura(SPELL_ALCHEMIST_APPRENTICE_INVISBUFF); player->CastSpell(player, SPELL_KILL_CREDIT); } } } else { RemoveItems(player); player->RemoveAura(SPELL_ALCHEMIST_APPRENTICE_INVISBUFF); if (Creature* finklestein = GetClosestCreatureWithEntry(player, NPC_FINKLESTEIN, 25.0f)) finklestein->AI()->Talk(SAY_RUINED, player); return; } } } } }
void _AmControlMenu::Build(const AmTrack* track) { AmFilterHolderI* holder = track->Filter(DESTINATION_PIPELINE); ArpCRef<AmDeviceI> device = NULL; if (holder && holder->Filter()) device = holder->Filter()->Device(); RemoveItems(0, CountItems(), true); for (uint32 k = 0; k < AM_CONTROLLER_SIZE; k++) { BString cn; if (device) cn = device->ControlName(k, true); if (cn.Length() < 1) cn << k; const char* label = NULL; if (cn.Length() > 0) label = cn.String(); if (!label) label = am_control_name(k); if (!label) { cn << k; label = cn.String(); } AddControlItem(k, label); } }
void TExpandoMenuBar::DetachedFromWindow() { BMenuBar::DetachedFromWindow(); if (sMonThread != B_ERROR) { sDoMonitor = false; status_t returnCode; wait_for_thread(sMonThread, &returnCode); sMonThread = B_ERROR; } BMessenger self(this); BMessage message(kUnsubscribe); message.AddMessenger("messenger", self); be_app->PostMessage(&message); RemoveItems(0, CountItems(), true); }
void PriorityMenu::Update() { BRow* selected = fTeamListView->CurrentSelection(NULL); int32 priority; bool enabled = selected != NULL; if (enabled && fTeamListView->CurrentSelection(selected) == NULL && !selected->HasLatch()) priority = ((ThreadItem *)selected)->priority; else priority = -1; if (priority != fPriority || fEnabled != enabled) { fPriority = priority; fEnabled = enabled; if (CountItems() > 0) RemoveItems(0, CountItems(), true); if (CountItems() < 1) BuildMenu(); } }
void TWindowMenu::AttachedToWindow() { SetFont(be_plain_font); RemoveItems(0, CountItems(), true); int32 miniCount = 0; bool dragging = false; TBarView* barview =(static_cast<TBarApp*>(be_app))->BarView(); if (barview && barview->LockLooper()) { // 'dragging' mode set in BarView::CacheDragData // invoke in MouseEnter in ExpandoMenuBar dragging = barview->Dragging(); if (dragging) { // We don't want to show the menu when dragging, but it's not // possible to remove a submenu once it exists, so we simply hide it // Don't call BMenu::Hide(), it causes the menu to pop up every now // and then. Window()->Hide(); // if in expando (horizontal or vertical) if (barview->Expando()) { SetTrackingHook(barview->MenuTrackingHook, barview->GetTrackingHookData()); } barview->DragStart(); } barview->UnlockLooper(); } int32 parentMenuItems = 0; int32 numTeams = fTeam->CountItems(); for (int32 i = 0; i < numTeams; i++) { team_id theTeam = (team_id)fTeam->ItemAt(i); int32 count = 0; int32* tokens = get_token_list(theTeam, &count); for (int32 j = 0; j < count; j++) { client_window_info* wInfo = get_window_info(tokens[j]); if (wInfo == NULL) continue; if (WindowShouldBeListed(wInfo->feel) && (wInfo->show_hide_level <= 0 || wInfo->is_mini)) { // Don't add new items if we're expanded. We've already done // this, they've just been moved. int32 numItems = CountItems(); int32 addIndex = 0; for (; addIndex < numItems; addIndex++) if (strcasecmp(ItemAt(addIndex)->Label(), wInfo->name) > 0) break; if (!fExpanded) { TWindowMenuItem* item = new TWindowMenuItem(wInfo->name, wInfo->server_token, wInfo->is_mini, ((1 << current_workspace()) & wInfo->workspaces) != 0, dragging); // disable app's window dropping for now if (dragging) item->SetEnabled(false); AddItem(item, TWindowMenuItem::InsertIndexFor(this, 0, item)); } else { TTeamMenuItem* parentItem = static_cast<TTeamMenuItem*>(Superitem()); if (parentItem->ExpandedWindowItem(wInfo->server_token)) { TWindowMenuItem* item = parentItem->ExpandedWindowItem( wInfo->server_token); if (item == NULL) continue; item->SetTo(wInfo->name, wInfo->server_token, wInfo->is_mini, ((1 << current_workspace()) & wInfo->workspaces) != 0, dragging); parentMenuItems++; } } if (wInfo->is_mini) miniCount++; } free(wInfo); } free(tokens); } int32 itemCount = CountItems() + parentMenuItems; if (itemCount < 1) { TWindowMenuItem* noWindowsItem = new TWindowMenuItem("No windows", -1, false, false); noWindowsItem->SetEnabled(false); AddItem(noWindowsItem); // if an application has no windows, this feature makes it easy to quit // it. (but we only add this option if the application is not Tracker.) if (fApplicationSignature.ICompare(kTrackerSignature) != 0) { AddSeparatorItem(); AddItem(new TShowHideMenuItem("Quit application", fTeam, B_QUIT_REQUESTED)); } } else { // if we are in drag mode, then don't add the window controls // to the menu if (!dragging) { TShowHideMenuItem* hide = new TShowHideMenuItem("Hide all", fTeam, B_MINIMIZE_WINDOW); TShowHideMenuItem* show = new TShowHideMenuItem("Show all", fTeam, B_BRING_TO_FRONT); TShowHideMenuItem* close = new TShowHideMenuItem("Close all", fTeam, B_QUIT_REQUESTED); if (miniCount == itemCount) hide->SetEnabled(false); else if (miniCount == 0) show->SetEnabled(false); if (!parentMenuItems) AddSeparatorItem(); AddItem(hide); AddItem(show); AddItem(close); } } BMenu::AttachedToWindow(); }
void MemoryBarMenu::Pulse() { system_info sinfo; get_system_info(&sinfo); int committedMemory = int(sinfo.used_pages * B_PAGE_SIZE / 1024); int cachedMemory = int(sinfo.cached_pages * B_PAGE_SIZE / 1024); Window()->BeginViewTransaction(); // create the list of items to remove, for their team is gone. Update the old teams. int lastRecycle = 0; int firstRecycle = 0; int k; MemoryBarMenuItem* item; int total = 0; for (k = 1; (item = (MemoryBarMenuItem*)ItemAt(k)) != NULL; k++) { int m = item->UpdateSituation(committedMemory); if (m < 0) { if (lastRecycle == fRecycleCount) { fRecycleCount += EXTRA; fRecycleList = (MRecycleItem*)realloc(fRecycleList, sizeof(MRecycleItem) * fRecycleCount); } fRecycleList[lastRecycle].index = k; fRecycleList[lastRecycle++].item = item; } else { if (lastRecycle > 0) { RemoveItems(fRecycleList[0].index, lastRecycle, true); k -= lastRecycle; lastRecycle = 0; } total += m; } } // Look new teams that have appeared. Create an item for them, or recycle from the list. int32 cookie = 0; info_pack infos; item = NULL; while (get_next_team_info(&cookie, &infos.team_info) == B_OK) { int j = 0; while (j < fTeamCount && infos.team_info.team != fTeamList[j]) { j++; } if (infos.team_info.team != fTeamList[j]) { // new team team_info info; j = 0; while (j < fTeamCount && fTeamList[j] != -1) { if (get_team_info(fTeamList[j], &info) != B_OK) fTeamList[j] = -1; else j++; } if (j == fTeamCount) { fTeamCount += 10; fTeamList = (team_id*)realloc(fTeamList, sizeof(team_id) * fTeamCount); } fTeamList[j] = infos.team_info.team; if (!get_team_name_and_icon(infos, true)) { // the team is already gone! delete infos.team_icon; fTeamList[j] = -1; } else { if (!item && firstRecycle < lastRecycle) item = fRecycleList[firstRecycle++].item; if (item) item->Reset(infos.team_name, infos.team_info.team, infos.team_icon, true); else { AddItem(item = new MemoryBarMenuItem(infos.team_name, infos.team_info.team, infos.team_icon, true, NULL)); } int m = item->UpdateSituation(committedMemory); if (m >= 0) { total += m; item = NULL; } else fTeamList[j] = -1; } } } if (item) { RemoveItem(item); delete item; } // Delete the items that haven't been recycled. if (firstRecycle < lastRecycle) { RemoveItems(IndexOf(fRecycleList[firstRecycle].item), lastRecycle - firstRecycle, true); } fLastTotalTime = system_time(); KernelMemoryBarMenuItem *kernelItem; if ((kernelItem = (KernelMemoryBarMenuItem*)ItemAt(0)) != NULL) kernelItem->UpdateSituation(committedMemory, cachedMemory); Window()->EndViewTransaction(); Window()->Flush(); }
void TTeamMenu::AttachedToWindow() { RemoveItems(0, CountItems(), true); // remove all items BMessenger self(this); BList teamList; TBarApp::Subscribe(self, &teamList); TBarView* barview = (dynamic_cast<TBarApp*>(be_app))->BarView(); bool dragging = barview && barview->Dragging(); int32 iconSize = static_cast<TBarApp*>(be_app)->IconSize(); desk_settings* settings = ((TBarApp*)be_app)->Settings(); float width = sMinimumWindowWidth - iconSize - 4; if (settings->sortRunningApps) teamList.SortItems(CompareByName); int32 count = teamList.CountItems(); for (int32 i = 0; i < count; i++) { // add items back BarTeamInfo* barInfo = (BarTeamInfo*)teamList.ItemAt(i); TTeamMenuItem* item = new TTeamMenuItem(barInfo->teams, barInfo->icon, barInfo->name, barInfo->sig, width, -1, !settings->hideLabels, true); if (settings->trackerAlwaysFirst && strcmp(barInfo->sig, kTrackerSignature) == 0) { AddItem(item, 0); } else AddItem(item); if (dragging && item != NULL) { bool canhandle = (dynamic_cast<TBarApp*>(be_app))->BarView()-> AppCanHandleTypes(item->Signature()); if (item->IsEnabled() != canhandle) item->SetEnabled(canhandle); BMenu* menu = item->Submenu(); if (menu) menu->SetTrackingHook(barview->MenuTrackingHook, barview->GetTrackingHookData()); } } if (CountItems() == 0) { BMenuItem* item = new BMenuItem("no application running", NULL); item->SetEnabled(false); AddItem(item); } if (dragging && barview->LockLooper()) { SetTrackingHook(barview->MenuTrackingHook, barview->GetTrackingHookData()); barview->DragStart(); barview->UnlockLooper(); } BMenu::AttachedToWindow(); }
void CApplicationImpl::DeleteItems(int* pBuf, int nSize, bool bConfirm /*= true*/) { RemoveItems(pBuf, nSize, bConfirm, FALSE); }
bool Star::AutoFind(const usImage& image, int extraEdgeAllowance, int searchRegion) { if (!image.Subframe.IsEmpty()) { Debug.AddLine("Autofind called on subframe, returning error"); return false; // not found } wxBusyCursor busy; Debug.AddLine(wxString::Format("Star::AutoFind called with edgeAllowance = %d searchRegion = %d", extraEdgeAllowance, searchRegion)); // run a 3x3 median first to eliminate hot pixels usImage smoothed; smoothed.CopyFrom(image); Median3(smoothed); // convert to floating point FloatImg conv(smoothed); // downsample the source image const int downsample = 1; if (downsample > 1) { FloatImg tmp; Downsample(tmp, conv, downsample); conv.Swap(tmp); } // run the PSF convolution { FloatImg tmp; psf_conv(tmp, conv); conv.Swap(tmp); } enum { CONV_RADIUS = 4 }; int dw = conv.Size.GetWidth(); // width of the downsampled image int dh = conv.Size.GetHeight(); // height of the downsampled image wxRect convRect(CONV_RADIUS, CONV_RADIUS, dw - 2 * CONV_RADIUS, dh - 2 * CONV_RADIUS); // region containing valid data SaveImage(conv, "PHD2_AutoFind.fit"); enum { TOP_N = 100 }; // keep track of the brightest stars std::set<Peak> stars; // sorted by ascending intensity double global_mean, global_stdev; GetStats(&global_mean, &global_stdev, conv, convRect); Debug.AddLine("AutoFind: global mean = %.1f, stdev %.1f", global_mean, global_stdev); const double threshold = 0.1; Debug.AddLine("AutoFind: using threshold = %.1f", threshold); // find each local maximum int srch = 4; for (int y = convRect.GetTop() + srch; y <= convRect.GetBottom() - srch; y++) { for (int x = convRect.GetLeft() + srch; x <= convRect.GetRight() - srch; x++) { float val = conv.px[dw * y + x]; bool ismax = false; if (val > 0.0) { ismax = true; for (int j = -srch; j <= srch; j++) { for (int i = -srch; i <= srch; i++) { if (i == 0 && j == 0) continue; if (conv.px[dw * (y + j) + (x + i)] > val) { ismax = false; break; } } } } if (!ismax) continue; // compare local maximum to mean value of surrounding pixels const int local = 7; double local_mean, local_stdev; wxRect localRect(x - local, y - local, 2 * local + 1, 2 * local + 1); localRect.Intersect(convRect); GetStats(&local_mean, &local_stdev, conv, localRect); // this is our measure of star intensity double h = (val - local_mean) / global_stdev; if (h < threshold) { // Debug.AddLine(wxString::Format("AG: local max REJECT [%d, %d] PSF %.1f SNR %.1f", imgx, imgy, val, SNR)); continue; } // coordinates on the original image int imgx = x * downsample + downsample / 2; int imgy = y * downsample + downsample / 2; stars.insert(Peak(imgx, imgy, h)); if (stars.size() > TOP_N) stars.erase(stars.begin()); } } for (std::set<Peak>::const_reverse_iterator it = stars.rbegin(); it != stars.rend(); ++it) Debug.AddLine("AutoFind: local max [%d, %d] %.1f", it->x, it->y, it->val); // merge stars that are very close into a single star { const int minlimitsq = 5 * 5; repeat: for (std::set<Peak>::const_iterator a = stars.begin(); a != stars.end(); ++a) { std::set<Peak>::const_iterator b = a; ++b; for (; b != stars.end(); ++b) { int dx = a->x - b->x; int dy = a->y - b->y; int d2 = dx * dx + dy * dy; if (d2 < minlimitsq) { // very close, treat as single star Debug.AddLine("AutoFind: merge [%d, %d] %.1f - [%d, %d] %.1f", a->x, a->y, a->val, b->x, b->y, b->val); // erase the dimmer one stars.erase(a); goto repeat; } } } } // exclude stars that would fit within a single searchRegion box { // build a list of stars to be excluded std::set<int> to_erase; const int extra = 5; // extra safety margin const int fullw = searchRegion + extra; for (std::set<Peak>::const_iterator a = stars.begin(); a != stars.end(); ++a) { std::set<Peak>::const_iterator b = a; ++b; for (; b != stars.end(); ++b) { int dx = abs(a->x - b->x); int dy = abs(a->y - b->y); if (dx <= fullw && dy <= fullw) { // stars closer than search region, exclude them both // but do not let a very dim star eliminate a very bright star if (b->val / a->val >= 5.0) { Debug.AddLine("AutoFind: close dim-bright [%d, %d] %.1f - [%d, %d] %.1f", a->x, a->y, a->val, b->x, b->y, b->val); } else { Debug.AddLine("AutoFind: too close [%d, %d] %.1f - [%d, %d] %.1f", a->x, a->y, a->val, b->x, b->y, b->val); to_erase.insert(std::distance(stars.begin(), a)); to_erase.insert(std::distance(stars.begin(), b)); } } } } RemoveItems(stars, to_erase); } // exclude stars too close to the edge { enum { MIN_EDGE_DIST = 40 }; int edgeDist = MIN_EDGE_DIST + extraEdgeAllowance; std::set<Peak>::iterator it = stars.begin(); while (it != stars.end()) { std::set<Peak>::iterator next = it; ++next; if (it->x <= edgeDist || it->x >= image.Size.GetWidth() - edgeDist || it->y <= edgeDist || it->y >= image.Size.GetHeight() - edgeDist) { Debug.AddLine("AutoFind: too close to edge [%d, %d] %.1f", it->x, it->y, it->val); stars.erase(it); } it = next; } } // At first I tried running Star::Find on the survivors to find the best // star. This had the unfortunate effect of locating hot pixels which // the psf convolution so nicely avoids. So, don't do that! -ag // find the brightest non-saturated star. If no non-saturated stars, settle for a saturated star. bool allowSaturated = false; while (true) { Debug.AddLine("AutoSelect: finding best star allowSaturated = %d", allowSaturated); for (std::set<Peak>::reverse_iterator it = stars.rbegin(); it != stars.rend(); ++it) { Star tmp; tmp.Find(&image, searchRegion, it->x, it->y, FIND_CENTROID); if (tmp.WasFound()) { if (tmp.GetError() == STAR_SATURATED && !allowSaturated) { Debug.AddLine("Autofind: star saturated [%d, %d] %.1f Mass %.f SNR %.1f", it->x, it->y, it->val, tmp.Mass, tmp.SNR); continue; } SetXY(it->x, it->y); Debug.AddLine("Autofind returns star at [%d, %d] %.1f Mass %.f SNR %.1f", it->x, it->y, it->val, tmp.Mass, tmp.SNR); return true; } } if (allowSaturated) break; // no stars found Debug.AddLine("AutoFind: could not find a non-saturated star!"); allowSaturated = true; } Debug.AddLine("Autofind: no star found"); return false; }
void ItemsListModel::handleItemsRemoved (const QSet<IDType_t>& items) { RemoveItems (items); }
void SeqNavMenu::Rewind() { RemoveItems( 0, CountItems(), true ); mMenuBuilt = false; ClearMenuBuildingState(); }
bool Star::AutoFind(const usImage& image, int extraEdgeAllowance, int searchRegion) { if (!image.Subframe.IsEmpty()) { Debug.AddLine("Autofind called on subframe, returning error"); return false; // not found } wxBusyCursor busy; Debug.Write(wxString::Format("Star::AutoFind called with edgeAllowance = %d searchRegion = %d\n", extraEdgeAllowance, searchRegion)); // run a 3x3 median first to eliminate hot pixels usImage smoothed; smoothed.CopyFrom(image); Median3(smoothed); // convert to floating point FloatImg conv(smoothed); // downsample the source image const int downsample = 1; if (downsample > 1) { FloatImg tmp; Downsample(tmp, conv, downsample); conv.Swap(tmp); } // run the PSF convolution { FloatImg tmp; psf_conv(tmp, conv); conv.Swap(tmp); } enum { CONV_RADIUS = 4 }; int dw = conv.Size.GetWidth(); // width of the downsampled image int dh = conv.Size.GetHeight(); // height of the downsampled image wxRect convRect(CONV_RADIUS, CONV_RADIUS, dw - 2 * CONV_RADIUS, dh - 2 * CONV_RADIUS); // region containing valid data SaveImage(conv, "PHD2_AutoFind.fit"); enum { TOP_N = 100 }; // keep track of the brightest stars std::set<Peak> stars; // sorted by ascending intensity double global_mean, global_stdev; GetStats(&global_mean, &global_stdev, conv, convRect); Debug.Write(wxString::Format("AutoFind: global mean = %.1f, stdev %.1f\n", global_mean, global_stdev)); const double threshold = 0.1; Debug.Write(wxString::Format("AutoFind: using threshold = %.1f\n", threshold)); // find each local maximum int srch = 4; for (int y = convRect.GetTop() + srch; y <= convRect.GetBottom() - srch; y++) { for (int x = convRect.GetLeft() + srch; x <= convRect.GetRight() - srch; x++) { float val = conv.px[dw * y + x]; bool ismax = false; if (val > 0.0) { ismax = true; for (int j = -srch; j <= srch; j++) { for (int i = -srch; i <= srch; i++) { if (i == 0 && j == 0) continue; if (conv.px[dw * (y + j) + (x + i)] > val) { ismax = false; break; } } } } if (!ismax) continue; // compare local maximum to mean value of surrounding pixels const int local = 7; double local_mean, local_stdev; wxRect localRect(x - local, y - local, 2 * local + 1, 2 * local + 1); localRect.Intersect(convRect); GetStats(&local_mean, &local_stdev, conv, localRect); // this is our measure of star intensity double h = (val - local_mean) / global_stdev; if (h < threshold) { // Debug.Write(wxString::Format("AG: local max REJECT [%d, %d] PSF %.1f SNR %.1f\n", imgx, imgy, val, SNR)); continue; } // coordinates on the original image int imgx = x * downsample + downsample / 2; int imgy = y * downsample + downsample / 2; stars.insert(Peak(imgx, imgy, h)); if (stars.size() > TOP_N) stars.erase(stars.begin()); } } for (std::set<Peak>::const_reverse_iterator it = stars.rbegin(); it != stars.rend(); ++it) Debug.Write(wxString::Format("AutoFind: local max [%d, %d] %.1f\n", it->x, it->y, it->val)); // merge stars that are very close into a single star { const int minlimitsq = 5 * 5; repeat: for (std::set<Peak>::const_iterator a = stars.begin(); a != stars.end(); ++a) { std::set<Peak>::const_iterator b = a; ++b; for (; b != stars.end(); ++b) { int dx = a->x - b->x; int dy = a->y - b->y; int d2 = dx * dx + dy * dy; if (d2 < minlimitsq) { // very close, treat as single star Debug.Write(wxString::Format("AutoFind: merge [%d, %d] %.1f - [%d, %d] %.1f\n", a->x, a->y, a->val, b->x, b->y, b->val)); // erase the dimmer one stars.erase(a); goto repeat; } } } } // exclude stars that would fit within a single searchRegion box { // build a list of stars to be excluded std::set<int> to_erase; const int extra = 5; // extra safety margin const int fullw = searchRegion + extra; for (std::set<Peak>::const_iterator a = stars.begin(); a != stars.end(); ++a) { std::set<Peak>::const_iterator b = a; ++b; for (; b != stars.end(); ++b) { int dx = abs(a->x - b->x); int dy = abs(a->y - b->y); if (dx <= fullw && dy <= fullw) { // stars closer than search region, exclude them both // but do not let a very dim star eliminate a very bright star if (b->val / a->val >= 5.0) { Debug.Write(wxString::Format("AutoFind: close dim-bright [%d, %d] %.1f - [%d, %d] %.1f\n", a->x, a->y, a->val, b->x, b->y, b->val)); } else { Debug.Write(wxString::Format("AutoFind: too close [%d, %d] %.1f - [%d, %d] %.1f\n", a->x, a->y, a->val, b->x, b->y, b->val)); to_erase.insert(std::distance(stars.begin(), a)); to_erase.insert(std::distance(stars.begin(), b)); } } } } RemoveItems(stars, to_erase); } // exclude stars too close to the edge { enum { MIN_EDGE_DIST = 40 }; int edgeDist = MIN_EDGE_DIST + extraEdgeAllowance; std::set<Peak>::iterator it = stars.begin(); while (it != stars.end()) { std::set<Peak>::iterator next = it; ++next; if (it->x <= edgeDist || it->x >= image.Size.GetWidth() - edgeDist || it->y <= edgeDist || it->y >= image.Size.GetHeight() - edgeDist) { Debug.Write(wxString::Format("AutoFind: too close to edge [%d, %d] %.1f\n", it->x, it->y, it->val)); stars.erase(it); } it = next; } } // At first I tried running Star::Find on the survivors to find the best // star. This had the unfortunate effect of locating hot pixels which // the psf convolution so nicely avoids. So, don't do that! -ag // try to identify the saturation point // first, find the peak pixel overall unsigned short maxVal = 0; for (unsigned int i = 0; i < image.NPixels; i++) if (image.ImageData[i] > maxVal) maxVal = image.ImageData[i]; // next see if any of the stars has a flat-top bool foundSaturated = false; for (std::set<Peak>::reverse_iterator it = stars.rbegin(); it != stars.rend(); ++it) { Star tmp; tmp.Find(&image, searchRegion, it->x, it->y, FIND_CENTROID); if (tmp.WasFound() && tmp.GetError() == STAR_SATURATED) { if ((maxVal - tmp.PeakVal) * 255U > maxVal) { // false positive saturation, flat top but below maxVal Debug.Write(wxString::Format("AutoSelect: false positive saturation peak = %hu, max = %hu\n", tmp.PeakVal, maxVal)); } else { // a saturated star was found foundSaturated = true; break; } } } unsigned int sat_level; // saturation level, including pedestal if (foundSaturated) { // use the peak overall pixel value as the saturation limit Debug.Write(wxString::Format("AutoSelect: using saturation level peakVal = %hu\n", maxVal)); sat_level = maxVal; // includes pedestal } else { // no staurated stars found, can't make any assumption about whether the max val is saturated Debug.Write(wxString::Format("AutoSelect: using saturation level from BPP %u and pedestal %hu\n", image.BitsPerPixel, image.Pedestal)); sat_level = ((1U << image.BitsPerPixel) - 1) + image.Pedestal; if (sat_level > 65535) sat_level = 65535; } unsigned int diff = sat_level > image.Pedestal ? sat_level - image.Pedestal : 0U; // "near-saturation" threshold at 90% saturation unsigned short sat_thresh = (unsigned short)((unsigned int) image.Pedestal + 9 * diff / 10); Debug.Write(wxString::Format("AutoSelect: BPP = %u, saturation at %u, pedestal %hu, thresh = %hu\n", image.BitsPerPixel, sat_level, image.Pedestal, sat_thresh)); // Final star selection // pass 1: find brightest star with peak value < 90% saturation AND SNR > 6 // this pass will reject saturated and nearly-saturated stars // pass 2: find brightest non-saturated star // pass 3: find brightest star, even if saturated for (int pass = 1; pass <= 3; pass++) { Debug.Write(wxString::Format("AutoSelect: finding best star pass %d\n", pass)); for (std::set<Peak>::reverse_iterator it = stars.rbegin(); it != stars.rend(); ++it) { Star tmp; tmp.Find(&image, searchRegion, it->x, it->y, FIND_CENTROID); if (tmp.WasFound()) { if (pass == 1) { if (tmp.PeakVal > sat_thresh) { Debug.Write(wxString::Format("Autofind: near-saturated [%d, %d] %.1f Mass %.f SNR %.1f Peak %hu\n", it->x, it->y, it->val, tmp.Mass, tmp.SNR, tmp.PeakVal)); continue; } if (tmp.GetError() == STAR_SATURATED || tmp.SNR < 6.0) continue; } else if (pass == 2) { if (tmp.GetError() == STAR_SATURATED) { Debug.Write(wxString::Format("Autofind: star saturated [%d, %d] %.1f Mass %.f SNR %.1f\n", it->x, it->y, it->val, tmp.Mass, tmp.SNR)); continue; } } // star accepted SetXY(it->x, it->y); Debug.Write(wxString::Format("Autofind returns star at [%d, %d] %.1f Mass %.f SNR %.1f\n", it->x, it->y, it->val, tmp.Mass, tmp.SNR)); return true; } } if (pass == 1) Debug.Write("AutoFind: could not find a star on Pass 1\n"); else if (pass == 2) Debug.Write("AutoFind: could not find a non-saturated star!\n"); } Debug.Write("Autofind: no star found\n"); return false; }