Skip to content

Commit

Permalink
GeoDaCenter#1751 social weights: tests complete
Browse files Browse the repository at this point in the history
  • Loading branch information
lixun910 committed Nov 28, 2018
1 parent 2a630a6 commit 8811750
Show file tree
Hide file tree
Showing 10 changed files with 402 additions and 322 deletions.
101 changes: 81 additions & 20 deletions DialogTools/CreatingWeightDlg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,8 @@ void CreatingWeightDlg::CreateControls()

void CreatingWeightDlg::OnDistanceMetricVarsSel( wxCommandEvent& event )
{
int dist_metric = m_dist_choice_vars->GetSelection();
if (dist_metric > 0) {
int metric = m_dist_choice_vars->GetSelection();
if (metric > 0) {
m_nb_distance_methods->Enable();
} else {
m_thres_val_valid = false;
Expand All @@ -256,8 +256,8 @@ void CreatingWeightDlg::OnDistanceWeightsVarsSel( wxCommandEvent& event )
void CreatingWeightDlg::UpdateThresholdValuesMultiVars()
{
// distance metric
int dist_metric = m_dist_choice_vars->GetSelection();
if (dist_metric < 1) {
int metric = m_dist_choice_vars->GetSelection();
if (metric < 1) {
return;
}

Expand Down Expand Up @@ -289,7 +289,7 @@ void CreatingWeightDlg::UpdateThresholdValuesMultiVars()
if (dist_util) {
delete dist_util;
}
dist_util = new GeoDa::DistUtils(data, dist_metric);
dist_util = new GeoDa::DistUtils(data, metric);
m_thres_min_multivars = dist_util->GetMinThreshold();
m_thres_max_multivars = dist_util->GetMaxThreshold();
double thres_range = m_thres_max_multivars - m_thres_min_multivars;
Expand Down Expand Up @@ -880,8 +880,8 @@ void CreatingWeightDlg::InitDlg()

m_dist_choice_vars->Clear();
m_dist_choice_vars->Append("");
m_dist_choice_vars->Append("Euclidean Distance");
m_dist_choice_vars->Append("Manhattan Distance");
m_dist_choice_vars->Append("Euclidean Distance");
m_dist_choice_vars->SetSelection(0);

m_trans_choice_vars->Clear();
Expand Down Expand Up @@ -1083,18 +1083,42 @@ double CreatingWeightDlg::GetBandwidth()

bool CreatingWeightDlg::CheckTableVariableInput()
{
if (m_nb_distance_variables->GetSelection()> 0) {
// check selected variables
wxArrayInt selections;
m_Vars->GetSelections(selections);
if (selections.GetCount() == 0) {
wxString msg = _("Please select at least one variable.");
wxMessageDialog dlg(this, msg, _("Warning"), wxOK | wxICON_WARNING);
dlg.ShowModal();
return false;
}

// check distance metric
if (m_dist_choice_vars->GetSelection() == 0) {
wxString msg = _("Please specify distance metric.");
wxMessageDialog dlg(this, msg, _("Warning"), wxOK | wxICON_WARNING);
dlg.ShowModal();
return false;
}
// check threshold
int method = m_nb_distance_methods->GetSelection();
if ( method == 0 || method == 2) {
wxString not_valid_msg = _("The currently entered threshold value is not a valid number. Please move the slider, or enter a valid number.");

if ( !m_thres_val_valid || !m_bandwidth_thres_val_valid) {
wxMessageDialog dlg(this, not_valid_msg, _("Error"), wxOK | wxICON_ERROR);
dlg.ShowModal();
return false;
}
}
return true;
}

void CreatingWeightDlg::CreateWeightsFromTable(WeightsMetaInfo& wmi)
void CreatingWeightDlg::CreateWeightsFromTable(wxString id, wxString outputfile, WeightsMetaInfo& wmi)
{
if (CheckTableVariableInput() == false) {
return;
}
GeoDa::Weights w;
int metric = m_dist_choice_vars->GetSelection();
WeightsMetaInfo::DistanceMetricEnum dist_metric = metric == 1 ? WeightsMetaInfo::DM_manhattan : WeightsMetaInfo::DM_euclidean;

int method = m_nb_distance_methods->GetSelection();
if (method == 0) {
Expand All @@ -1110,6 +1134,7 @@ void CreatingWeightDlg::CreateWeightsFromTable(WeightsMetaInfo& wmi)
}
}
w = dist_util->CreateDistBandWeights(band, is_inverse, power);
wmi.SetToThres(id, dist_metric, WeightsMetaInfo::DU_unspecified, "", WeightsMetaInfo::DV_vars, band, power);

} else if ( method == 1) {
// kNN
Expand All @@ -1124,10 +1149,12 @@ void CreatingWeightDlg::CreateWeightsFromTable(WeightsMetaInfo& wmi)
}
}
w = dist_util->CreateKNNWeights(k, is_inverse, power);
wmi.SetToKnn(id, dist_metric, WeightsMetaInfo::DU_unspecified, "", WeightsMetaInfo::DV_vars, k, power);

} else if ( method == 2) {
// adaptive kernel
int kernel_type = m_kernel_methods->GetSelection();
wxString kernel = m_kernel_methods->GetString(kernel_type);
bool apply_kernel_to_diag = m_kernel_diagnals->GetValue();
double bandwidth = GetBandwidth();
bool is_adaptive_bandwidth = m_radio_adaptive_bandwidth->GetValue();
Expand All @@ -1138,7 +1165,26 @@ void CreatingWeightDlg::CreateWeightsFromTable(WeightsMetaInfo& wmi)
} else {
w = dist_util->CreateAdaptiveKernelWeights(kernel_type, k, is_adaptive_bandwidth, apply_kernel_to_diag);
}
wmi.SetToKernel(id, dist_metric, WeightsMetaInfo::DU_unspecified, "", WeightsMetaInfo::DV_vars, kernel, k, bandwidth, is_adaptive_bandwidth, apply_kernel_to_diag);
}

// save to file
GwtWeight* Wp = new GwtWeight;
Wp->num_obs = w.size();
Wp->is_symmetric = false;
Wp->symmetry_checked = true;
Wp->gwt = new GwtElement[Wp->num_obs];
for (size_t i=0; i<w.size(); i++) {
GwtElement& e = Wp->gwt[i];
e.alloc(w[i].size());
for (size_t j=0; j<w[i].size(); j++) {
GwtNeighbor neigh;
neigh.nbx = w[i][j].first;
neigh.weight = w[i][j].second;
e.Push(neigh);
}
}
WriteWeightFile(NULL, Wp, project->GetProjectTitle(), outputfile, id, wmi);
}

bool CreatingWeightDlg::CheckThresholdInput()
Expand Down Expand Up @@ -1171,14 +1217,15 @@ bool CreatingWeightDlg::CheckThresholdInput()
( !is_dist_band && m_bandwidth_thres_val*m_thres_delta_factor < m_thres_min) )
{
wxString msg;
if (is_dist_band)
if (is_dist_band) {
msg = wxString::Format(nbrless_msg, m_threshold_val, m_thres_min);
else
} else {
msg = wxString::Format(nbrless_msg, m_bandwidth_thres_val, m_thres_min);

}
wxMessageDialog dlg(this, msg, _("Warning"), wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION );
if (dlg.ShowModal() != wxID_YES)
if (dlg.ShowModal() != wxID_YES) {
return false;
}
}
return true;
}
Expand Down Expand Up @@ -1219,13 +1266,21 @@ void CreatingWeightDlg::CreateWeights()
dlg.ShowModal();
return;
}

if (!CheckThresholdInput())
return;

wxString id = m_id_field->GetString(m_id_field->GetSelection());
if (!CheckID(id))
if (!CheckID(id)) {
return;
}

if (m_nb_distance_variables->GetSelection() == 1) {
if (CheckTableVariableInput() == false) {
return;
}
} else {
if (!CheckThresholdInput()) {
return;
}
}

wxString wildcard;
wxString defaultFile(project->GetProjectTitle());
Expand Down Expand Up @@ -1258,11 +1313,17 @@ void CreatingWeightDlg::CreateWeights()
wxLogMessage("CreateWeights()");
wxLogMessage(outputfile);

// 1/2 case social weights:
if (m_nb_distance_variables->GetSelection() == 1) {
CreateWeightsFromTable(id, outputfile, wmi);
return;
}

// 2/2 other cases:
int m_ooC = m_spincont->GetValue();
int m_kNN = m_spinneigh->GetValue();
int m_kernel_kNN = m_spinn_kernel->GetValue();
int m_alpha = 1;

bool done = false;

wxString str_X = m_X->GetString(m_X->GetSelection());
Expand Down
3 changes: 2 additions & 1 deletion DialogTools/CreatingWeightDlg.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,8 @@ public TableStateObserver, public WeightsManStateObserver
bool CheckID(const wxString& id);
bool CheckThresholdInput();
bool CheckTableVariableInput();
void CreateWeightsFromTable(WeightsMetaInfo& wmi);
void CreateWeightsFromTable(wxString id, wxString outputfile,
WeightsMetaInfo& wmi);
double GetBandwidth();
bool IsSaveAsGwt(); // determine if save type will be GWT or GAL.
bool WriteWeightFile(GalWeight* Wp_gal, GwtWeight* Wp_gwt,
Expand Down
4 changes: 4 additions & 0 deletions ShapeOperations/WeightsManPtree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ void WeightsManPtree::ReadPtree(const boost::property_tree::ptree& pt,
wxString s = v.second.data();
if (s == "euclidean") {
e.wmi.dist_metric = WeightsMetaInfo::DM_euclidean;
} else if (s == "manhattan") {
e.wmi.dist_metric = WeightsMetaInfo::DM_manhattan;
} else if (s == "arc") {
e.wmi.dist_metric = WeightsMetaInfo::DM_arc;
} else if (s == "unspecified" || s.IsEmpty()) {
Expand Down Expand Up @@ -332,6 +334,8 @@ void WeightsManPtree::WritePtree(boost::property_tree::ptree& pt,

if (e.wmi.dist_metric == WeightsMetaInfo::DM_euclidean) {
sssub.put("dist_metric", "euclidean");
} else if (e.wmi.dist_metric == WeightsMetaInfo::DM_manhattan) {
sssub.put("dist_metric", "manhattan");
} else if (e.wmi.dist_metric == WeightsMetaInfo::DM_arc) {
sssub.put("dist_metric", "arc");
}
Expand Down
2 changes: 2 additions & 0 deletions VarCalc/WeightsMetaInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,8 @@ wxString WeightsMetaInfo::DistMetricToStr() const
{
if (dist_metric == DM_euclidean) {
return "Euclidean";
} else if (dist_metric == DM_manhattan) {
return "Manhattan";
} else if (dist_metric == DM_arc) {
return "arc";
}
Expand Down
2 changes: 1 addition & 1 deletion VarCalc/WeightsMetaInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ struct WeightsMetaInfo
DV_unspecified, DV_centroids, DV_mean_centers, DV_vars, DV_coordinates
};
enum DistanceMetricEnum {
DM_unspecified, DM_euclidean, DM_arc
DM_unspecified, DM_euclidean, DM_arc, DM_manhattan
};
enum DistanceUnitsEnum {
DU_unspecified, DU_km, DU_mile
Expand Down
40 changes: 16 additions & 24 deletions Weights/DistUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,8 @@ GeoDa::Weights DistUtils::CreateKNNWeights(int k, bool is_inverse, int power)
GeoDa::Weights weights;

double w;
ANNidxArray nnIdx = new ANNidx[k];
ANNdistArray dists = new ANNdist[k];
ANNidxArray nnIdx = new ANNidx[k+1];
ANNdistArray dists = new ANNdist[k+1];
for (size_t i=0; i<n_rows; i++) {
// k+1, because data[i] will be always returned
kdTree->annkSearch(data[i], k+1, nnIdx, dists);
Expand Down Expand Up @@ -161,8 +161,8 @@ GeoDa::Weights DistUtils::CreateAdaptiveKernelWeights(int kernel_type, int k,
GeoDa::Weights weights;
double w;
double max_knn_bandwidth = 0;
ANNidxArray nnIdx = new ANNidx[k];
ANNdistArray dists = new ANNdist[k];
ANNidxArray nnIdx = new ANNidx[k+1];
ANNdistArray dists = new ANNdist[k+1];

if (is_adaptive_bandwidth) {
for (size_t i=0; i<n_rows; i++) {
Expand All @@ -171,21 +171,17 @@ GeoDa::Weights DistUtils::CreateAdaptiveKernelWeights(int kernel_type, int k,
std::vector<std::pair<int, double> > nbrs;
double local_band = 0;
for (size_t j=0; j<k+1; j++) {
// iter each neighbor
if (nnIdx[j] != i) {
if (dists[j] > local_band) {
local_band = dists[j];
}
// iter each neighbor, include itself
if (dists[j] > local_band) {
local_band = dists[j];
}
}
local_band = ANN_ROOT(local_band);
for (size_t j=0; j<k+1; j++) {
// iter each neighbor
if (nnIdx[j] != i) {
w = ANN_ROOT(dists[j]);
w = local_band > 0 ? w / local_band : 0;
nbrs.push_back(std::make_pair(nnIdx[j], w));
}
w = ANN_ROOT(dists[j]);
w = local_band > 0 ? w / local_band : 0;
nbrs.push_back(std::make_pair(nnIdx[j], w));
}
weights.push_back(nbrs);
}
Expand All @@ -197,12 +193,10 @@ GeoDa::Weights DistUtils::CreateAdaptiveKernelWeights(int kernel_type, int k,
std::vector<std::pair<int, double> > nbrs;
for (size_t j=0; j<k+1; j++) {
// iter each neighbor
if (nnIdx[j] != i) {
w = ANN_ROOT(dists[j]);
nbrs.push_back(std::make_pair(nnIdx[j], w));
if (w > max_knn_bandwidth) {
max_knn_bandwidth = w;
}
w = ANN_ROOT(dists[j]);
nbrs.push_back(std::make_pair(nnIdx[j], w));
if (w > max_knn_bandwidth) {
max_knn_bandwidth = w;
}
}
weights.push_back(nbrs);
Expand Down Expand Up @@ -237,10 +231,8 @@ GeoDa::Weights DistUtils::CreateAdaptiveKernelWeights(int kernel_type, double ba
std::vector<std::pair<int, double> > nbrs;
for (size_t j=0; j<k; j++) {
// iter each neighbor
if (nnIdx[j] != i) {
w = ANN_ROOT(dists[j]) / band;
nbrs.push_back(std::make_pair(nnIdx[j],w));
}
w = ANN_ROOT(dists[j]) / band;
nbrs.push_back(std::make_pair(nnIdx[j],w));
}
weights.push_back(nbrs);
delete[] nnIdx;
Expand Down
1 change: 1 addition & 0 deletions kNN/ANN.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

using namespace std; // make std:: accessible

int ANN_DIST_TYPE = 2;

double ANN_POW(double v)
{
Expand Down
2 changes: 1 addition & 1 deletion kNN/ANN/ANN.h
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ const ANNbool ANN_ALLOW_SELF_MATCH = ANNtrue;
// uncomment the appropriate set of macros below.
//----------------------------------------------------------------------

static int ANN_DIST_TYPE = 2;
extern int ANN_DIST_TYPE;

double ANN_POW(double v);
double ANN_ROOT(double x);
Expand Down
Loading

0 comments on commit 8811750

Please sign in to comment.