11 #include "ControlNet.h"
19 #include <QMutexLocker>
21 #include <QScopedPointer>
23 #include <QStringList>
28 #include <boost/numeric/ublas/symmetric.hpp>
29 #include <boost/numeric/ublas/io.hpp>
31 #include "Application.h"
32 #include "CameraFactory.h"
33 #include "ControlMeasure.h"
34 #include "ControlNetVersioner.h"
35 #include "ControlPoint.h"
38 #include "IException.h"
41 #include "SerialNumberList.h"
42 #include "SpecialPixel.h"
43 #include "Statistics.h"
47 using namespace boost::numeric::ublas;
52 void ControlNet::nullify() {
70 p_created = Application::DateTime();
71 p_modified = Application::DateTime();
72 m_coordType = coordType;
75 ControlNet::ControlNet(
const ControlNet &other) {
82 for (
int cpIndex = 0; cpIndex < other.
GetNumPoints(); cpIndex++) {
107 ControlNet::ControlNet(
const QString &ptfile,
Progress *progress,
116 m_coordType = coordType;
119 ReadControl(ptfile, progress);
122 QString msg =
"Invalid control network [" + ptfile +
"]";
123 throw IException(e, IException::Io, msg, _FILEINFO_);
133 ControlNet::~ControlNet() {
154 emit measureModified(measure, type, oldValue, newValue);
168 emit pointModified(point, type, oldValue, newValue);
180 void ControlNet::clear() {
184 if (GetNumPoints() > 0) {
186 QHashIterator<QString, ControlPoint*> i(*points);
187 while (i.hasNext()) {
189 delete(*points)[i.key()];
190 (*points)[i.key()] = NULL;
198 m_controlGraph.clear();
230 throw IException(IException::Programmer,
"Ownership has already been taken",
239 for (
int i = 0; i < points.size(); i++) {
240 points[i]->parentNetwork = NULL;
271 void ControlNet::ReadControl(
const QString &filename,
Progress *progress) {
276 p_networkId = versionedReader.
netId();
277 p_userName = versionedReader.
userName();
282 int numPoints = versionedReader.
numPoints();
285 progress->
SetText(
"Adding Control Points to Network...");
290 for (
int i = 0; i < numPoints; i++) {
311 void ControlNet::Write(
const QString &ptfile,
bool pvl) {
317 network = versionedWriter.
toPvl();
320 QString msg =
"Failed to convert control network to Pvl format.";
321 throw IException(e, IException::Programmer, msg, _FILEINFO_);
325 network.
write(ptfile);
328 QString msg =
"Failed writing control network to file [" + ptfile +
"]";
329 throw IException(e, IException::Io, msg, _FILEINFO_);
337 QString msg =
"Failed writing control network to file [" + ptfile +
"]";
338 throw IException(e, IException::Io, msg, _FILEINFO_);
354 IString msg =
"Null pointer passed to ControlNet::AddPoint!";
355 throw IException(IException::Programmer, msg, _FILEINFO_);
358 if (ContainsPoint(point->
GetId())) {
359 IString msg =
"ControlPoint must have unique Id";
360 throw IException(IException::Programmer, msg, _FILEINFO_);
363 QString pointId = point->
GetId();
364 points->insert(pointId, point);
365 pointIds->append(pointId);
372 emit networkStructureModified();
386 IString msg =
"NULL point passed to "
387 "ControlNet::pointAdded!";
388 throw IException(IException::Programmer, msg, _FILEINFO_);
391 if (!ContainsPoint(point->
GetId())) {
392 QString msg =
"ControlNet does not contain the point [";
393 msg += point->
GetId() +
"]";
394 throw IException(IException::Programmer, msg, _FILEINFO_);
398 for (
int i = 0; i < point->GetNumMeasures(); i++) {
401 if (!m_vertexMap.contains(sn)) {
403 newImage.serial = sn;
404 ImageVertex newVertex = boost::add_vertex(newImage, m_controlGraph);
405 m_vertexMap.insert(sn, newVertex);
406 emit networkModified(GraphModified);
411 for(
int i = 0; i < measures.size(); i++) {
415 m_controlGraph[m_vertexMap[serial]].measures[measure->Parent()] = measure;
419 if (!point->IsIgnored() && !measure->IsIgnored()) {
420 for (
int j = i + 1; j < measures.size(); j++) {
422 if (!cm->IsIgnored()) {
429 emit newPoint(point);
442 bool ControlNet::addEdge(QString sourceSerial, QString targetSerial) {
449 boost::tie(connection, edgeAdded) = boost::add_edge(m_vertexMap[sourceSerial],
450 m_vertexMap[targetSerial],
452 m_controlGraph[connection].strength++;
454 emit networkModified(GraphModified);
471 bool ControlNet::removeEdge(QString sourceSerial, QString targetSerial) {
474 boost::tie(connection, edgeExists) = boost::edge(m_vertexMap[sourceSerial],
475 m_vertexMap[targetSerial],
478 m_controlGraph[connection].strength--;
479 if (m_controlGraph[connection].strength <= 0) {
480 boost::remove_edge(m_vertexMap[sourceSerial],
481 m_vertexMap[targetSerial],
483 emit networkModified(GraphModified);
497 QString ControlNet::GraphToString()
const {
505 foreach(QString imageSerial, images) {
509 if (!point->IsIgnored()) {
510 pointIds.append(point->
GetId());
514 imagePointIds.insert(imageSerial, pointIds);
517 foreach(QString imageSerial, images) {
518 QStringList adjacentImages = getAdjacentImages(imageSerial);
519 adjacentImages.sort();
520 foreach(QString adjacentSerial, adjacentImages) {
521 if (QString::compare(adjacentSerial, imageSerial) < 0) {
528 while (imageIt != imagePointIds[imageSerial].cend() &&
529 adjacentIt != imagePointIds[adjacentSerial].cend()) {
530 int stringDiff = QString::compare(*imageIt, *adjacentIt);
531 if (stringDiff < 0) {
534 else if(stringDiff == 0) {
535 commonPoints.append(*imageIt);
544 std::pair<ImageConnection, bool> result = boost::edge(m_vertexMap[imageSerial],
545 m_vertexMap[adjacentSerial],
547 QString edgeStrength =
"UNKNOWN";
549 edgeStrength =
toString(m_controlGraph[result.first].strength);
552 graphString.append(imageSerial);
553 graphString.append(
" ----(");
554 graphString.append(edgeStrength);
555 graphString.append(
") [");
556 graphString.append(commonPoints.join(
","));
557 graphString.append(
"]---- ");
558 graphString.append(adjacentSerial);
559 graphString.append(
"\n");
582 IString msg =
"NULL measure passed to "
583 "ControlNet::measureAdded!";
584 throw IException(IException::Programmer, msg, _FILEINFO_);
589 IString msg =
"Control measure with NULL parent passed to "
590 "ControlNet::measureAdded!";
591 throw IException(IException::Programmer, msg, _FILEINFO_);
594 if (!ContainsPoint(point->
GetId())) {
595 QString msg =
"ControlNet does not contain the point [";
596 msg += point->
GetId() +
"]";
597 throw IException(IException::Programmer, msg, _FILEINFO_);
603 if (!m_vertexMap.contains(serial)) {
605 newImage.serial = serial;
606 ImageVertex newVertex = boost::add_vertex(newImage, m_controlGraph);
607 m_vertexMap.insert(serial, newVertex);
608 emit networkModified(GraphModified);
611 m_controlGraph[m_vertexMap[serial]].measures[measure->Parent()] = measure;
615 if (!point->IsIgnored() && !measure->IsIgnored()) {
616 for (
int i = 0; i < point->GetNumMeasures(); i++) {
618 if (!cm->IsIgnored()) {
622 if (QString::compare(sn, serial) != 0) {
628 emit newMeasure(measure);
639 IString msg =
"NULL point passed to "
640 "ControlNet::pointUnIgnored!";
641 throw IException(IException::Programmer, msg, _FILEINFO_);
646 for (
int i = 0; i < validMeasures.size(); i++) {
650 if (!ValidateSerialNumber(sourceSerial)) {
651 QString msg =
"Node does not exist for [";
652 msg += sourceSerial +
"]";
653 throw IException(IException::Programmer, msg, _FILEINFO_);
656 for(
int j = i+1; j < validMeasures.size(); j++) {
660 if (!ValidateSerialNumber(targetSerial)) {
661 QString msg =
"Node does not exist for [";
662 msg += targetSerial +
"]";
663 throw IException(IException::Programmer, msg, _FILEINFO_);
665 addEdge(sourceSerial, targetSerial);
685 IString msg =
"NULL measure passed to "
686 "ControlNet::measureUnIgnored!";
687 throw IException(IException::Programmer, msg, _FILEINFO_);
692 IString msg =
"Control measure with NULL parent passed to "
693 "ControlNet::measureUnIgnored!";
694 throw IException(IException::Programmer, msg, _FILEINFO_);
697 if (!ContainsPoint(point->
GetId())) {
698 QString msg =
"ControlNet does not contain the point [";
699 msg += point->
GetId() +
"]";
700 throw IException(IException::Programmer, msg, _FILEINFO_);
704 for (
int i = 0; i < point->GetNumMeasures(); i++) {
707 if (!adjacentMeasure->IsIgnored() && !m_vertexMap.contains(sn)) {
708 QString msg =
"Node does not exist for [";
710 throw IException(IException::Programmer, msg, _FILEINFO_);
714 if (!point->IsIgnored()) {
719 for (
int i = 0; i < point->GetNumMeasures(); i++) {
721 if (!cm->IsIgnored()) {
724 if (QString::compare(sn, serial) != 0) {
741 void ControlNet::UpdatePointReference(
ControlPoint *point, QString oldId) {
742 points->remove(oldId);
743 (*points)[point->
GetId()] = point;
744 (*pointIds)[pointIds->indexOf((QString) oldId)] = (QString)point->
GetId();
757 ASSERT(m_vertexMap.contains(serial));
759 emit measureRemoved(measure);
762 if (!measure->IsIgnored() && !measure->Parent()->IsIgnored()) {
764 measureIgnored(measure);
770 m_controlGraph[m_vertexMap[serial]].measures.remove(measure->Parent());
781 IString msg =
"NULL point passed to "
782 "ControlNet::pointIgnored!";
783 throw IException(IException::Programmer, msg, _FILEINFO_);
788 for (
int i = 0; i < validMeasures.size(); i++) {
792 if (!ValidateSerialNumber(sourceSerial)) {
793 QString msg =
"Node does not exist for [";
794 msg += sourceSerial +
"]";
795 throw IException(IException::Programmer, msg, _FILEINFO_);
798 for(
int j = i+1; j < validMeasures.size(); j++) {
802 if (!ValidateSerialNumber(targetSerial)) {
803 QString msg =
"Node does not exist for [";
804 msg += targetSerial +
"]";
805 throw IException(IException::Programmer, msg, _FILEINFO_);
807 removeEdge(sourceSerial, targetSerial);
823 IString msg =
"NULL measure passed to "
824 "ControlNet::measureIgnored!";
825 throw IException(IException::Programmer, msg, _FILEINFO_);
830 IString msg =
"Control measure with NULL parent passed to "
831 "ControlNet::measureIgnored!";
832 throw IException(IException::Programmer, msg, _FILEINFO_);
836 if (!ValidateSerialNumber(serial)) {
837 QString msg =
"Node does not exist for [";
839 throw IException(IException::Programmer, msg, _FILEINFO_);
844 for (
int i = 0; i < point->GetNumMeasures(); i++) {
847 if (!adjacentMeasure->IsIgnored() && m_vertexMap.contains(sn)) {
848 if (QString::compare(serial, sn) !=0) {
849 removeEdge(serial, sn);
862 m_coordType = coordType;
869 void ControlNet::emitNetworkStructureModified() {
870 emit networkStructureModified();
880 if (points->values().contains(point)) {
881 return DeletePoint(point->
GetId());
886 msg +=
"] does not exist in the network";
887 throw IException(IException::User, msg, _FILEINFO_);
899 int ControlNet::DeletePoint(QString pointId) {
900 if (!points->contains(pointId)) {
901 IString msg =
"point Id [" + pointId +
"] does not exist in the network";
902 throw IException(IException::User, msg, _FILEINFO_);
907 if (point->IsEditLocked())
908 return ControlPoint::PointLocked;
910 bool wasIgnored = point->IsIgnored();
917 emit pointDeleted(point);
920 points->remove(pointId);
921 pointIds->removeAt(pointIds->indexOf(pointId));
926 emit networkStructureModified();
927 return ControlPoint::Success;
936 int ControlNet::DeletePoint(
int index) {
937 if (index < 0 || index >= pointIds->size()) {
939 throw IException(IException::Programmer, msg, _FILEINFO_);
942 return DeletePoint(pointIds->at(index));
951 bool ControlNet::ContainsPoint(QString pointId)
const {
952 return points->contains(pointId);
974 for (
int i = 0; i < serials.size(); i++) {
975 boost::put(indexMapAdaptor, m_vertexMap[serials[i]], i);
980 int numComponents = boost::connected_components(m_controlGraph, componentAdaptor,
981 boost::vertex_index_map(indexMapAdaptor));
984 for (
int i = 0; i < numComponents; i++) {
986 islandStrings.append(tempList);
988 std::map<ImageVertex, size_t>::iterator it = componentMap.begin();
989 while(it != componentMap.end())
991 QString serial = m_controlGraph[it->first].serial;
992 int group = (int) it->second;
993 islandStrings[group].append(serial);
996 return islandStrings;
1003 int ControlNet::getEdgeCount()
const {
1004 return boost::num_edges(m_controlGraph);
1017 return m_vertexMap.keys();
1029 bool ControlNet::ValidateSerialNumber(QString serialNumber)
const {
1030 return m_vertexMap.contains(serialNumber);
1042 if (!ValidateSerialNumber(serialNumber)) {
1043 QString msg =
"Cube Serial Number [" + serialNumber +
"] not found in "
1045 throw IException(IException::Programmer, msg, _FILEINFO_);
1051 boost::tie(adjIt, adjEnd) = boost::adjacent_vertices(m_vertexMap[serialNumber], m_controlGraph);
1052 for( ; adjIt != adjEnd; adjIt++) {
1053 adjacentSerials.append(m_controlGraph[*adjIt].serial);
1056 return adjacentSerials;
1066 if( !ValidateSerialNumber(serialNumber) ) {
1067 IString msg =
"Cube Serial Number [" + serialNumber +
"] not found in "
1069 throw IException(IException::Programmer, msg, _FILEINFO_);
1072 return m_controlGraph[m_vertexMap[serialNumber]].measures.values();
1088 if (!measure->IsIgnored())
1089 validMeasures.append(measure);
1092 return validMeasures;
1104 if (
this != &other) {
1105 this->m_accessor = other.m_accessor;
1118 bool ControlNet::ControlMeasureLessThanFunctor::operator()
1121 return (a->*this->m_accessor)() < (b->*this->m_accessor)();
1134 double min,
double max) {
1140 int nObjPts = this->GetNumPoints();
1141 for (
int i=0;i<nObjPts;i++) {
1143 if (point->IsIgnored())
continue;
1146 int nObs = point->GetNumMeasures();
1147 for (
int j=0;j<nObs;j++) {
1149 if (measure->IsIgnored())
continue;
1150 double temp = (measure->*statFunc)();
1152 if (min <= temp && temp <= max) measures.push_back(measure);
1158 qSort(measures.begin(),measures.end(),lessThan);
1169 void ControlNet::ComputeResiduals() {
1172 QHashIterator< QString, ControlPoint * > i(*points);
1173 while (i.hasNext()) {
1175 i.value()->ComputeResiduals();
1185 void ControlNet::ComputeApriori() {
1187 QHashIterator< QString, ControlPoint * > i(*points);
1188 while (i.hasNext()) {
1191 if ( !point->IsIgnored() )
1203 double ControlNet::AverageResidual() {
1205 double avgResidual = 0.0;
1207 QHashIterator< QString, ControlPoint * > i(*points);
1208 while (i.hasNext()) {
1211 if (!point->IsIgnored()) {
1213 &ControlMeasure::GetResidualMagnitude).
Average();
1219 avgResidual /= count;
1233 return p_cameraList[index];
1244 QString ControlNet::CreatedDate()
const {
1254 QString ControlNet::Description()
const {
1255 return p_description;
1272 double sample,
double line) {
1274 if (!ValidateSerialNumber(serialNumber)) {
1275 QString msg =
"serialNumber [";
1276 msg += serialNumber;
1277 msg +=
"] not found in ControlNet";
1278 throw IException(IException::Programmer, msg, _FILEINFO_);
1281 const double SEARCH_DISTANCE = 99999999.0;
1282 double minDist = SEARCH_DISTANCE;
1287 for (
int i = 0; i < measures.size(); i++) {
1291 double dx = fabs(sample - measureToCheck->GetSample());
1292 double dy = fabs(line - measureToCheck->GetLine());
1294 double dist = sqrt((dx * dx) + (dy * dy));
1296 if (dist < minDist) {
1298 closestPoint = measureToCheck->Parent();
1302 if (!closestPoint) {
1303 IString msg =
"No point found within ";
1304 msg +=
IString(SEARCH_DISTANCE);
1305 msg +=
"pixels of sample/line [";
1310 throw IException(IException::Programmer, msg, _FILEINFO_);
1313 return closestPoint;
1323 double ControlNet::GetMaximumResidual() {
1326 double maxResidual = 0.0;
1329 &ControlMeasure::GetResidualMagnitude).
Maximum();
1330 if (residual > maxResidual)
1331 maxResidual = residual;
1338 QString ControlNet::GetNetworkId()
const {
1349 int ControlNet::GetNumEditLockMeasures() {
1350 int numLockedMeasures = 0;
1355 return numLockedMeasures;
1364 int ControlNet::GetNumEditLockPoints() {
1365 int editLockPoints = 0;
1367 if (p->IsEditLocked())
1371 return editLockPoints;
1381 int ControlNet::GetNumIgnoredMeasures() {
1382 int numIgnoredMeasures = 0;
1387 return numIgnoredMeasures;
1399 int ControlNet::GetNumberOfValidMeasuresInImage(
const QString &serialNumber) {
1401 if (p_cameraList.size() > 0) {
1402 return p_cameraValidMeasuresMap[serialNumber];
1404 return GetValidMeasuresInCube(serialNumber).size();
1413 int ControlNet::GetNumberOfJigsawRejectedMeasuresInImage(
const QString &serialNumber) {
1414 return p_cameraRejectedMeasuresMap[serialNumber];
1423 void ControlNet::ClearJigsawRejected() {
1434 void ControlNet::IncrementNumberOfRejectedMeasuresInImage(
const QString &serialNumber) {
1435 p_cameraRejectedMeasuresMap[serialNumber]++;
1443 void ControlNet::DecrementNumberOfRejectedMeasuresInImage(
const QString &serialNumber) {
1444 if (p_cameraRejectedMeasuresMap[serialNumber] > 0)
1445 p_cameraRejectedMeasuresMap[serialNumber]--;
1454 int ControlNet::GetNumMeasures()
const {
1455 int numMeasures = 0;
1457 numMeasures += p->GetNumMeasures();
1465 int ControlNet::GetNumPoints()
const {
1466 return points->size();
1479 int ControlNet::GetNumValidMeasures() {
1480 int numValidMeasures = 0;
1482 if (!p->IsIgnored())
1486 return numValidMeasures;
1495 int ControlNet::GetNumValidPoints() {
1496 int validPoints = 0;
1498 if (!p->IsIgnored())
1507 QString ControlNet::GetTarget()
const {
1508 return p_targetName;
1513 QString ControlNet::GetUserName()
const {
1518 QString ControlNet::GetLastModified()
const {
1527 for (
int i = 0; i < pointIds->size(); i++) {
1528 pointsList.append(GetPoint(i));
1546 void ControlNet::SetCreatedDate(
const QString &date) {
1556 void ControlNet::SetDescription(
const QString &newDescription) {
1557 p_description = newDescription;
1566 void ControlNet::SetImages(
const QString &imageListFile) {
1589 if (p_cameraList.size() > 0) {
1593 if (progress != NULL) {
1594 progress->
SetText(
"Setting input images...");
1599 for (
int i = 0; i < list.
size(); i++) {
1601 QString filename = list.
fileName(i);
1602 Cube cube(filename,
"r");
1606 p_cameraMap[serialNumber] = cam;
1607 p_cameraValidMeasuresMap[serialNumber] = 0;
1608 p_cameraRejectedMeasuresMap[serialNumber] = 0;
1609 p_cameraList.push_back(cam);
1612 QString msg =
"Unable to create camera for cube file ";
1614 throw IException(e, IException::Unknown, msg, _FILEINFO_);
1617 if (progress != NULL)
1622 QHashIterator< QString, ControlPoint * > p(*points);
1623 while (p.hasNext()) {
1628 for (
int m = 0; m < serialNums.size(); m++) {
1633 curMeasure->
SetCamera(p_cameraMap[serialNumber]);
1636 if (!curMeasure->IsIgnored()) p_cameraValidMeasuresMap[serialNumber]++;
1641 "] does not have a cube with a matching serial number";
1642 throw IException(IException::User, msg, _FILEINFO_);
1654 void ControlNet::SetModifiedDate(
const QString &date) {
1666 void ControlNet::SetMutex(QMutex *mutex) {
1676 void ControlNet::SetNetworkId(
const QString &
id) {
1692 void ControlNet::SetTarget(
const QString &target) {
1693 p_targetName = target;
1704 void ControlNet::SetTarget(
Pvl label) {
1708 mapping = label.
findGroup(
"Mapping", Pvl::Traverse);
1712 p_targetName = mapping[
"TargetName"][0];
1715 && label.
findObject(
"IsisCube").hasGroup(
"Instrument")
1716 && label.
findObject(
"IsisCube").findGroup(
"Instrument").hasKeyword(
"TargetName")) {
1717 p_targetName = label.
findObject(
"IsisCube").findGroup(
"Instrument").findKeyword(
"TargetName")[0];
1730 void ControlNet::SetUserName(
const QString &name) {
1750 std::swap(points, other.
points);
1751 std::swap(pointIds, other.
pointIds);
1753 std::swap(m_mutex, other.m_mutex);
1766 QHashIterator< QString, ControlPoint * > i(*points);
1767 while (i.hasNext()) {
1768 i.next().value()->parentNetwork =
this;
1771 QHashIterator< QString, ControlPoint * > i2(*other.
points);
1772 while (i2.hasNext()) {
1773 i2.next().value()->parentNetwork = &other;
1776 m_vertexMap.
clear();
1777 VertexIterator v, vend;
1778 for (boost::tie(v, vend) = vertices(m_controlGraph); v != vend; ++v) {
1779 ImageVertex imVertex = *v;
1780 QString serialNum = m_controlGraph[*v].serial;
1781 m_vertexMap[serialNum] = imVertex;
1784 other.m_vertexMap.clear();
1785 VertexIterator v2, vend2;
1786 for (boost::tie(v2, vend2) = vertices(other.
m_controlGraph); v2 != vend2; ++v2) {
1787 ImageVertex imVertex = *v2;
1789 other.m_vertexMap[serialNum] = imVertex;
1792 emit networkModified(ControlNet::Swapped);
1805 if (
this != &other) {
1815 const ControlPoint *ControlNet::GetPoint(QString
id)
const {
1816 if (!points->contains(
id)) {
1817 IString msg =
"The control network has no control points with an ID "
1818 "equal to [" +
id +
"]";
1819 throw IException(IException::Programmer, msg, _FILEINFO_);
1822 return points->value(
id);
1826 ControlPoint *ControlNet::GetPoint(QString
id) {
1827 if (!points->contains(
id)) {
1828 IString msg =
"The control network has no control points with an ID "
1829 "equal to [" +
id +
"]";
1830 throw IException(IException::Programmer, msg, _FILEINFO_);
1833 return (*points)[id];
1837 const ControlPoint *ControlNet::GetPoint(
int index)
const {
1838 if (index < 0 || index >= pointIds->size()) {
1839 IString msg =
"Index [" + IString(index) +
"] out of range";
1840 throw IException(IException::Programmer, msg, _FILEINFO_);
1843 return GetPoint(pointIds->at(index));
1847 ControlPoint *ControlNet::GetPoint(
int index) {
1848 if (index < 0 || index >= pointIds->size()) {
1849 IString msg =
"Index [" + IString(index) +
"] out of range";
1850 throw IException(IException::Programmer, msg, _FILEINFO_);
1853 return GetPoint(pointIds->at(index));
1866 const ControlPoint *ControlNet::operator[](QString
id)
const {
1867 return GetPoint(
id);
1871 ControlPoint *ControlNet::operator[](QString
id) {
1872 return GetPoint(
id);
1876 const ControlPoint *ControlNet::operator[](
int index)
const {
1877 return GetPoint(index);
1881 ControlPoint *ControlNet::operator[](
int index) {
1882 return GetPoint(index);