// $Id: gc_locus.cpp,v 1.35 2011/03/08 19:22:00 bobgian Exp $ /* Copyright 2002 Mary Kuhner, Jon Yamato, and Joseph Felsenstein This software is distributed free of charge for non-commercial use and is copyrighted. Of course, we do not guarantee that the software works, and are not responsible for any damage you may cause or have. */ #include #include "gc_creation_info.h" #include "gc_errhandling.h" #include "gc_data.h" // for ToWxString #include "gc_default.h" #include "gc_locus.h" #include "gc_locus_err.h" #include "gc_strings.h" #include "gc_strings_locus.h" #include "gc_structures_err.h" #include "wx/log.h" #include "wx/string.h" #include "wx/tokenzr.h" //------------------------------------------------------------------------------------ gcLocus::gcLocus() : m_blessed(false), m_hasRegion(false), m_regionId(gcdefault::badIndex), m_inducedByFile(false), m_fileId(gcdefault::badIndex), m_dataType(sdatatype_NONE_SET), m_hasNumMarkers(false), m_numMarkers(0), m_hasTotalLength(false), m_totalLength(0), m_hasLinkedUserValue(false), m_linkedUserValue(false), m_hasOffset(false), m_offset(1), m_hasMapPosition(false), m_mapPosition(1), m_hasUnphasedMarkers(false) { assert(m_unphasedMarkers.NumMarkers() == 0); m_locations.clear(); // shouldn't be necessary } gcLocus::~gcLocus() { } bool gcLocus::GetBlessed() const { return m_blessed; } void gcLocus::DebugDump(wxString prefix) const { wxLogDebug("%slocus %s (locus id %ld)", // EWDUMPOK prefix.c_str(), GetName().c_str(), (long)GetId()); wxLogDebug("%sdatatype %s",(prefix+gcstr::indent).c_str(),ToWxString(GetDataType()).c_str()); // EWDUMPOK wxLogDebug("%s%s markers",(prefix+gcstr::indent).c_str(),GetNumMarkersString().c_str()); // EWDUMPOK wxLogDebug("%s%s total length",(prefix+gcstr::indent).c_str(),GetLengthString().c_str()); // EWDUMPOK wxLogDebug("%s%s offset",(prefix+gcstr::indent).c_str(),GetOffsetString().c_str()); // EWDUMPOK wxLogDebug("%s%s map position",(prefix+gcstr::indent).c_str(),GetMapPositionString().c_str()); // EWDUMPOK wxLogDebug("%slocations:%s",(prefix+gcstr::indent).c_str(),GetLocationsAsString().c_str()); // EWDUMPOK if(GetLinked()) { wxLogDebug("%slinked",(prefix+gcstr::indent).c_str()); // EWDUMPOK } else { wxLogDebug("%sunlinked",(prefix+gcstr::indent).c_str()); // EWDUMPOK } } bool gcLocus::HasLocations() const { return !(m_locations.empty()); } std::vector gcLocus::GetLocations() const { return m_locations; } wxString gcLocus::GetLocationsAsString() const { wxString locationString = " "; for(size_t index=0; index < m_locations.size(); index++) { locationString += wxString::Format("%ld ",m_locations[index]); } return locationString; } bool gcLocus::HasLocationZero() const { for(size_t i = 0; i < m_locations.size(); i++) { long loc = m_locations[i]; if(loc == 0) return true; } return false; } wxString gcLocus::GetDataTypeString() const { return ToWxString(m_dataType); } gcSpecificDataType gcLocus::GetDataType() const { return m_dataType; } void gcLocus::SetDataType(gcSpecificDataType type) { m_dataType = type; } bool gcLocus::HasLength() const { if(HasTotalLength()) { return true; } if(GetDataType() == sdatatype_DNA) { return HasNumMarkers(); } return false; } size_t gcLocus::GetLength() const { if(HasTotalLength()) { return GetTotalLength(); } if(HasNumMarkers()) { if(GetDataType() == sdatatype_DNA) { return GetNumMarkers(); } if(GetNumMarkers() == 1) { return 1; } else { throw gc_locus_without_length(GetName()); } } return gcdefault::badLength; } wxString gcLocus::GetLengthString() const { if(HasLength()) { return wxString::Format("%d",(int)GetLength()); } return gcstr::unknown; } bool gcLocus::HasTotalLength() const { return m_hasTotalLength; } size_t gcLocus::GetTotalLength() const { assert(HasTotalLength()); return m_totalLength; } wxString gcLocus::GetTotalLengthString() const { if(HasTotalLength()) { return wxString::Format("%d",(int)GetTotalLength()); } return gcstr::unknown; } void gcLocus::SetTotalLength(size_t totalLength) { if(HasNumMarkers()) { if(totalLength < GetNumMarkers()) { throw gc_locus_err(wxString::Format(gcerr::lengthTooShort,(int)totalLength,(int)GetNumMarkers()).c_str()); } } m_hasTotalLength = true; m_totalLength = totalLength; } void gcLocus::UnsetTotalLength() { m_hasTotalLength = false; } bool gcLocus::HasNumMarkers() const { return m_hasNumMarkers; } size_t gcLocus::GetNumMarkers() const { if(!HasNumMarkers()) { wxString msg = wxString::Format(gcerr_locus::unsetNumMarkers,GetName().c_str()); throw gc_implementation_error(msg.c_str()); } return m_numMarkers; } wxString gcLocus::GetNumMarkersString() const { if(HasNumMarkers()) { return wxString::Format("%d",(int)GetNumMarkers()); } return gcstr::unknown; } void gcLocus::SetNumMarkers(size_t numMarkers) { if(numMarkers == 0) { throw gc_num_markers_zero(); } m_hasNumMarkers = true; m_numMarkers = numMarkers; } bool gcLocus::HasOffset() const { return m_hasOffset; } long gcLocus::GetOffset() const { if(!HasOffset()) { wxString msg = wxString::Format(gcerr_locus::unsetOffset,GetName().c_str()); throw gc_implementation_error(msg.c_str()); } return m_offset; } wxString gcLocus::GetOffsetString() const { if(HasOffset()) { return wxString::Format("%d",(int)GetOffset()); } return gcstr::unknown; } void gcLocus::UnsetNumMarkers() { m_hasNumMarkers = false; } bool gcLocus::HasRegion() const { return m_hasRegion; } size_t gcLocus::GetRegionId() const { if(!HasRegion()) { wxString msg = wxString::Format(gcerr::unsetRegionId,GetName().c_str()); throw gc_implementation_error(msg.c_str()); } return m_regionId; } void gcLocus::SetFileId(size_t id) { m_inducedByFile = true; m_fileId = id; } void gcLocus::UnsetFileId() { m_inducedByFile = false; } void gcLocus::SetRegionId(size_t id) { m_hasRegion = true; m_regionId = id; } void gcLocus::UnsetRegionId() { m_hasRegion = false; } bool gcLocus::HasLinkedUserValue() const { return m_hasLinkedUserValue; } bool gcLocus::GetLinkedUserValue() const { if(!HasLinkedUserValue()) { wxString msg = wxString::Format(gcerr_locus::unsetLinkedUserValue,GetName().c_str()); throw gc_implementation_error(msg.c_str()); } return m_linkedUserValue; } bool gcLocus::GetLinked() const { if(HasLinkedUserValue()) { return GetLinkedUserValue(); } if(HasTotalLength()) { return true; } if(HasLocations()) { return true; } switch(GetDataType()) { case sdatatype_NONE_SET: // EWFIX.P4 -- should be able to determine values // by reading data structures return true; break; case sdatatype_DNA: case sdatatype_SNP: return true; break; case sdatatype_KALLELE: case sdatatype_MICROSAT: return false; break; } assert(false); return true; } wxString gcLocus::GetLinkedString() const { bool val = GetLinked(); if(val) return gcstr::linkageYes; return gcstr::linkageNo; } wxString gcLocus::GetLinkedUserValueString() const { if(HasLinkedUserValue()) { bool val = GetLinkedUserValue(); if(val) return gcstr::linkageYes; return gcstr::linkageNo; } else { return gcstr::unknown; } } void gcLocus::SetLinkedUserValue(bool linked) { if(! linked) { if(GetDataType() == sdatatype_DNA || GetDataType() == sdatatype_SNP) { throw gc_unlinked_nuc(); } } m_hasLinkedUserValue = true; m_linkedUserValue = linked; } bool gcLocus::HasMapPosition() const { return m_hasMapPosition; } long gcLocus::GetMapPosition() const { if(!HasMapPosition()) { wxString msg = wxString::Format(gcerr::unsetMapPosition,GetName().c_str()); throw gc_implementation_error(msg.c_str()); } return m_mapPosition; } wxString gcLocus::GetMapPositionString() const { if(HasMapPosition()) { return wxString::Format("%d",(int)GetMapPosition()); } return gcstr::unknown; } void gcLocus::SetMapPosition(long mapPosition) { // we don't test the value since during use of the // GUI, the user needs to pass through impossible // states m_hasMapPosition = true; m_mapPosition = mapPosition; } void gcLocus::UnsetMapPosition() { m_hasMapPosition = false; } bool gcLocus::HasUnphasedMarkers() const { return m_hasUnphasedMarkers; } const gcUnphasedMarkers * gcLocus::GetUnphasedMarkers() const { assert(HasUnphasedMarkers()); return &m_unphasedMarkers; } wxString gcLocus::GetUnphasedMarkersAsString() const { assert(HasUnphasedMarkers()); return m_unphasedMarkers.AsString(); } void gcLocus::SetUnphasedMarkers(gcUnphasedMarkers markers) { m_hasUnphasedMarkers = true; m_unphasedMarkers = markers; } void gcLocus::SetBlessed(bool blessed) { m_blessed = blessed; } void gcLocus::SetCreationInfo(const gcCreationInfo & creationInfo) { m_creationInfo = creationInfo; } void gcLocus::SetOffset(long offset) { // we don't test the value since during use of the // GUI, the user needs to pass through impossible // states m_offset = offset; m_hasOffset = true; } void gcLocus::SetLocations(wxString locationString) { wxStringTokenizer tokenizer(locationString); m_locations.clear(); while(tokenizer.HasMoreTokens()) { wxString token = tokenizer.GetNextToken(); long location; if(!token.ToLong(&location)) { wxString msg = wxString::Format(gcerr::notALocation,locationString.c_str()); throw gc_data_error(msg.c_str()); } if(!m_locations.empty()) // cannot check the first one! { long previous = m_locations.back(); if(location <= previous) { throw gc_locations_out_of_order(GetName(),previous,location); } } m_locations.push_back(location); } if(HasNumMarkers()) { if(m_locations.size() != GetNumMarkers()) { throw gc_set_locations_err(GetName(),locationString,GetNumMarkers(),m_locations.size()); } } else { SetNumMarkers(m_locations.size()); } } void gcLocus::LocusMergeLogic(bool doSettings, gcLocus & locusRef) { // data type if(GetDataType() != sdatatype_NONE_SET) { if(locusRef.GetDataType() != sdatatype_NONE_SET) { if(locusRef.GetDataType() != GetDataType()) { throw gc_locus_user_data_type_mismatch(GetName(),locusRef.GetName(),GetDataType(),locusRef.GetDataType()); } } } // num Markers if(HasNumMarkers()) { if(locusRef.HasNumMarkers()) { if(locusRef.GetNumMarkers() != GetNumMarkers()) { throw gc_locus_site_count_mismatch(GetName(),locusRef.GetName(),GetNumMarkers(),locusRef.GetNumMarkers()); } } } // EWFIX.P3 -- this is probably not correct // total length if(HasTotalLength()) { if(locusRef.HasTotalLength()) { if(locusRef.GetLength() != GetLength()) { throw gc_locus_length_mismatch(GetName(),locusRef.GetName(),GetLength(),locusRef.GetLength()); } } } // user-set linked value if(HasLinkedUserValue()) { if(locusRef.HasLinkedUserValue()) { if(locusRef.GetLinkedUserValue() != GetLinkedUserValue()) { throw gc_locus_user_linked_mismatch(GetName(),locusRef.GetName(),GetLinkedUserValue(),locusRef.GetLinkedUserValue()); } } } // offset if(HasOffset()) { if(locusRef.HasOffset()) { if(locusRef.GetOffset() != GetOffset()) { throw gc_locus_offset_mismatch(GetName(),locusRef.GetName(),GetOffset(),locusRef.GetOffset()); } } } // map position if(HasMapPosition()) { if(locusRef.HasMapPosition()) { if(locusRef.GetMapPosition() != GetMapPosition()) { throw gc_locus_map_position_mismatch(GetName(),locusRef.GetName(),GetMapPosition(),locusRef.GetMapPosition()); } } } if(doSettings) // this is a real merge { // order is important -- setting data type and then num Markers can // result in setting the length if(GetDataType() == sdatatype_NONE_SET) SetDataType(locusRef.GetDataType()); if(!HasNumMarkers() && locusRef.HasNumMarkers()) SetNumMarkers(locusRef.GetNumMarkers()); if(!HasTotalLength() && locusRef.HasTotalLength()) SetTotalLength(locusRef.GetTotalLength()); if(!HasLinkedUserValue() && locusRef.HasLinkedUserValue()) SetLinkedUserValue(locusRef.GetLinkedUserValue()); if(!HasOffset() && locusRef.HasOffset()) SetOffset(locusRef.GetOffset()); if(!HasMapPosition() && locusRef.HasMapPosition()) SetMapPosition(locusRef.GetMapPosition()); } } bool gcLocus::CanMergeWith(gcLocus & locus) { try { LocusMergeLogic(false,locus); } catch (const gc_locus_err& e) { return false; } return true; } void gcLocus::MergeWith(gcLocus & locus) { LocusMergeLogic(true,locus); } wxString gcLocus::GetLongName() const { return wxString::Format("%s %s",GetName().c_str(),m_creationInfo.GetDescriptiveName().c_str()); } //____________________________________________________________________________________