Skip to content

Commit 5128b91

Browse files
authored
Merge pull request #276 from AdityaSavara/tuningCorrector-updates
Tuning corrector updates
2 parents d08ba81 + 0f1d6f6 commit 5128b91

File tree

211 files changed

+3694
-2584
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

211 files changed

+3694
-2584
lines changed

MSRESOLVE.py

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1289,6 +1289,25 @@ def CorrectionValuesObtain(ReferenceData):
12891289
listOfNeededMolecules = ReferenceData.molecules #intentionally grab molecule list from the original data object fed in.
12901290
ReferenceDataOriginalStandardTuning = copy.deepcopy(ReferenceData) #This is mainly needed for G.referenceFileStandardTuning
12911291
ReferenceDataStandardTuning = createReferenceDataObject ( G.referenceFileStandardTuning[0], G.referenceFileStandardTuning[1], AllMID_ObjectsDict=G.AllMID_ObjectsDict)
1292+
#TODO: Make the below block of code a function. This block is actually the copy of a block from tuning correction.
1293+
if (G.calculateUncertaintiesInConcentrations == True) and (type(G.referenceFileUncertainties) != type(None)):
1294+
if type(G.referenceFileUncertainties) == type(float(5)) or type(G.referenceFileUncertainties) == type(int(5)) :
1295+
#TODO: Low priority. The below results in "nan" values. It could be better to change it to make zeros using a numpy "where" statement.
1296+
G.referenceFileUncertainties = float(G.referenceFileUncertainties) #Make sure we have a float.
1297+
#Get what we need.
1298+
provided_reference_patterns = ReferenceDataStandardTuning.provided_reference_patterns
1299+
provided_reference_patterns_without_masses = ReferenceDataStandardTuning.provided_reference_patterns[:,1:] #[:,0] is mass fragments, so we slice to remove those.
1300+
#Make our variables ready.
1301+
absolute_standard_uncertainties = provided_reference_patterns*1.0 #First we make a copy.
1302+
absolute_standard_uncertainties_without_masses = (provided_reference_patterns_without_masses/provided_reference_patterns_without_masses)*G.referenceFileUncertainties #We do the division to get an array of ones. Then we multiply to get an array of the same size.
1303+
#now we populate our copy's non-mass area.
1304+
absolute_standard_uncertainties[:,1:] = absolute_standard_uncertainties_without_masses
1305+
ReferenceDataStandardTuning.absolute_standard_uncertainties = absolute_standard_uncertainties
1306+
#We can't convert to relative uncertainties yet because the file may not be standardized yet.
1307+
else:
1308+
print("WARNING: Line 1325 of MSRESOLVE.py else statement has not been programmed. ReferenceDataStandardTuning currently only receives uncertainties if there is an integer in the referenceFileUncertainties.")
1309+
ReferenceDataStandardTuning.absolute_standard_uncertainties = ReferenceDataStandardTuning.provided_reference_patterns*1.0 #First we make a copy.
1310+
ReferenceDataStandardTuning.absolute_standard_uncertainties[:,1:] = 0
12921311
listOfStandardTuningMoleculePatternsAvailable = copy.deepcopy(ReferenceDataStandardTuning.molecules)
12931312
#get a list of molecules to remove from the ReferenceDataStandardTuning file.
12941313
listOfMoleculesToRemove = []
@@ -1317,11 +1336,22 @@ def CorrectionValuesObtain(ReferenceData):
13171336
ReferenceDataStandardTuning, addedReferenceSlice = extendReferencePattern(ReferenceDataStandardTuning, ReferenceDataOriginalStandardTuning)
13181337
#This is the ReferenceDataObject to carry forward.
13191338
ReferenceDataStandardTuning.exportReferencePattern("ExportedReferencePatternStandardForCorrectionValuesMixedStandardTuning.csv")
1339+
if G.createMixedTuningPattern == False:
1340+
listOfMoleculesToRemove = []
1341+
for moleculeName in ReferenceDataStandardTuning.molecules:
1342+
if moleculeName not in ReferenceData.molecules:
1343+
listOfMoleculesToRemove.append(moleculeName)
1344+
ReferenceDataStandardTuning = ReferenceDataStandardTuning.removeMolecules(listOfMoleculesToRemove)
13201345
#rearrange the molecules to the right order.
13211346
ReferenceDataStandardTuning = rearrangeReferenceData(ReferenceData=ReferenceDataStandardTuning, desiredMoleculesOrder=ReferenceData.molecules)
13221347
ReferenceDataStandardTuning.exportReferencePattern("ExportedReferencePatternStandardForCorrectionValuesMixedStandardTuningRearranged.csv")
13231348
#move the pointer.
13241349
ReferenceDataForCorrectionValues = ReferenceDataStandardTuning
1350+
#Before the below, ReferenceDataForCorrectionValues and ReferenceData must be made the same size and width. To do that, we will extend each to have any rows missing that the other has.
1351+
ReferenceDataMassFragments = ReferenceData.standardized_reference_patterns[:,0]
1352+
ReferenceDataForCorrectionValuesMassFragments = ReferenceDataForCorrectionValues.standardized_reference_patterns[:,0]
1353+
ReferenceData.extendMassFragments(ReferenceDataForCorrectionValuesMassFragments)
1354+
ReferenceDataForCorrectionValues.extendMassFragments(ReferenceDataMassFragments)
13251355
reference_width = len(ReferenceDataForCorrectionValues.standardized_reference_patterns[0,:]) #This is number of molecules plus 1 because of the mass fragments column.
13261356
reference_height = len(ReferenceDataForCorrectionValues.standardized_reference_patterns[:,0]) #this is the number of mass fragments.
13271357
correction_values_direct = ReferenceDataForCorrectionValues.standardized_reference_patterns*1.0 #just initializing as same size, but note that this has the mass fragments column.
@@ -3012,7 +3042,7 @@ def __init__(self, provided_reference_patterns, electronnumbers, molecules, mole
30123042
self.moleculeIonizationType = ['unknown']* len(self.molecules)
30133043
self.provided_mass_fragments = self.provided_reference_patterns[:,0]
30143044
#clear ClearZeroRowsFromProvidedReferenceIntensities
3015-
self.ClearZeroRowsFromProvidedReferenceIntensities()
3045+
#self.ClearZeroRowsFromProvidedReferenceIntensities() #commenting this out to avoid problems for now.
30163046
#initialize the standardized_reference_patterns
30173047
self.standardized_reference_patterns=StandardizeReferencePattern(self.provided_reference_patterns,len(self.molecules))
30183048

@@ -3189,7 +3219,19 @@ def ClearZeroRowsFromStandardizedReferenceIntensities(self):
31893219
print("Warning: line 2897 was unable to update the relative uncertainties of a reference pattern.")
31903220
self.ExportCollector("ClearZeroRowsFromStandardizedReferenceIntensities", use_provided_reference_patterns=False)
31913221

3192-
3222+
def extendMassFragments(self, massFragmentsToExtendBy):
3223+
#This will add in rows of zeros to the standardized_reference_patterns and also the uncertainties arrays.
3224+
self.standardized_reference_patterns_mass_fragments = self.standardized_reference_patterns[:,0]*1.0
3225+
self.standardized_reference_patterns = DataFunctions.extendXYYYtoZYYY(self.standardized_reference_patterns, massFragmentsToExtendBy)
3226+
#Check if the absolute_standard_uncertainties is the right length. If it is, we will be extending it also.
3227+
if hasattr(self, "absolute_standard_uncertainties"):
3228+
print("line 3270", self.standardized_reference_patterns[:,0], numpy.shape(self.standardized_reference_patterns))
3229+
print("line 3270", self.absolute_standard_uncertainties[:,0], numpy.shape(self.absolute_standard_uncertainties))
3230+
if len(self.absolute_standard_uncertainties[:,0] == self.standardized_reference_patterns_mass_fragments):
3231+
self.absolute_standard_uncertainties = DataFunctions.extendXYYYtoZYYY(self.absolute_standard_uncertainties, massFragmentsToExtendBy)
3232+
#For the relative uncertainties, we will use the built in function.
3233+
print('line 3275', numpy.shape(self.absolute_standard_uncertainties), numpy.shape(self.standardized_reference_patterns))
3234+
self.update_relative_standard_uncertainties()
31933235

31943236
#This class function converts the XYXY data to an XYYY format
31953237
def FromXYXYtoXYYY(self):
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
The setting of useExtentOfSLSUniqueSolvable was used. The best combination is the last in this file.
2-
Time taken:1.1674611568450928
2+
Time taken:1.194232702255249
33
[(28.0, 31.0, 44.0, 57.0), (28.0, 31.0, 45.0, 57.0), (28.0, 31.0, 46.0, 57.0), (28.0, 31.0, 50.0, 57.0), (28.0, 31.0, 51.0, 57.0), (28.0, 31.0, 53.0, 57.0), (28.0, 31.0, 54.0, 57.0), (28.0, 31.0, 55.0, 57.0), (28.0, 31.0, 57.0, 71.0), (28.0, 31.0, 57.0, 72.0)]

UnitTests/ConcentrationFinder/LogFile.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Tue Nov 9 16:21:19 2021
1+
Tue Nov 9 20:23:42 2021
22

33
referenceFileName = ['AcetaldehydeNISTRefMixed2_test_2.csv', 'AcetaldehydeNISTRefMixed2_test_2.csv']
44
form = ['xyyy', 'xyyy']
@@ -20,5 +20,5 @@ scaleRawDataFactor = 1.0
2020
resolvedScaledConcentrationsOutputName = ScaledConcentrations.csv
2121
concentrationsOutputName = ResolvedConcentrations.csv
2222
simulatedSignalsOutputName = SimulatedRawSignals.csv
23-
Run Time 0.23048 seconds
23+
Run Time 0.60301 seconds
2424
######################################################################

UnitTests/ExtractReferencePatternFromData/LogFile.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Tue Nov 9 16:21:39 2021
1+
Tue Nov 9 20:24:02 2021
22

33
referenceFileName = ['AcetaldehydeNISTRefMixed2.csv']
44
form = ['xyyy']
@@ -27,5 +27,5 @@ scaleRawDataFactor = 1.0
2727
resolvedScaledConcentrationsOutputName = ScaledConcentrations.csv
2828
concentrationsOutputName = ResolvedConcentrations.csv
2929
simulatedSignalsOutputName = SimulatedRawSignals.csv
30-
Run Time 3.68472 seconds
30+
Run Time 3.32647 seconds
3131
######################################################################

UnitTests/FinalOptimizer/LogFile.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Tue Nov 9 16:21:45 2021
1+
Tue Nov 9 20:24:08 2021
22

33
referenceFileName = ['ConvertedSpectra.csv']
44
form = ['xyyy']
@@ -20,5 +20,5 @@ scaleRawDataFactor = 1.0
2020
resolvedScaledConcentrationsOutputName = ScaledConcentrations.csv
2121
concentrationsOutputName = ResolvedConcentrations.csv
2222
simulatedSignalsOutputName = SimulatedRawSignals.csv
23-
Run Time 4.42243 seconds
23+
Run Time 4.42341 seconds
2424
######################################################################

UnitTests/IonizationFactors/LogFile.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Tue Nov 9 16:21:54 2021
1+
Tue Nov 9 20:24:18 2021
22

33
referenceFileName = ['AcetaldehydeNISTRefDefault.csv']
44
form = ['xyyy']
@@ -17,5 +17,5 @@ scaleRawDataFactor = 1.0
1717
resolvedScaledConcentrationsOutputName = ScaledConcentrations.csv
1818
concentrationsOutputName = ResolvedConcentrations.csv
1919
simulatedSignalsOutputName = SimulatedRawSignals.csv
20-
Run Time 0.10617 seconds
20+
Run Time 0.09788 seconds
2121
######################################################################

UnitTests/IterativeAnalysis/LogFile.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Tue Nov 9 16:21:57 2021
1+
Tue Nov 9 20:24:21 2021
22

33
referenceFileName = ['AcetaldehydeNISTRefMixed2.csv']
44
form = ['xyyy']
@@ -24,5 +24,5 @@ scaleRawDataFactor = 1.0
2424
resolvedScaledConcentrationsOutputName = ScaledConcentrations.csv
2525
concentrationsOutputName = ResolvedConcentrations.csv
2626
simulatedSignalsOutputName = SimulatedRawSignals.csv
27-
Run Time 1.75765 seconds
27+
Run Time 1.96085 seconds
2828
######################################################################

UnitTests/IterativeAnalysis/_iter_1/LogFile.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Tue Nov 9 16:21:58 2021
1+
Tue Nov 9 20:24:22 2021
22

33
referenceFileName = ['AcetaldehydeNISTRefMixed2_iter_1.csv']
44
form = ['xyyy']
@@ -26,5 +26,5 @@ scaleRawDataFactor = 1.0
2626
resolvedScaledConcentrationsOutputName = ScaledConcentrations.csv
2727
concentrationsOutputName = ResolvedConcentrations.csv
2828
simulatedSignalsOutputName = SimulatedRawSignals.csv
29-
Run Time 0.44900 seconds
29+
Run Time 0.47060 seconds
3030
######################################################################

UnitTests/IterativeAnalysis/_iter_1/UserInput_iter_1.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@
112112
TotalConcentrationsOutputName = 'TotalConcentrations.csv'
113113
ExportAtEachStep = 'yes'
114114
generatePercentages = 'no'
115-
checkpoint = 3.0687719
116-
start = 3.0687716
115+
checkpoint = 3.3668313
116+
start = 3.3668311
117117
timeSinceLastCheckpoint = ''
118118
iterationNumber = 1
119119

UnitTests/IterativeAnalysis/_iter_2/LogFile.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Tue Nov 9 16:21:58 2021
1+
Tue Nov 9 20:24:22 2021
22

33
referenceFileName = ['AcetaldehydeNISTRefMixed2_iter_2.csv']
44
form = ['xyyy']
@@ -21,5 +21,5 @@ scaleRawDataFactor = 1.0
2121
resolvedScaledConcentrationsOutputName = ScaledConcentrations.csv
2222
concentrationsOutputName = ResolvedConcentrations.csv
2323
simulatedSignalsOutputName = SimulatedRawSignals.csv
24-
Run Time 0.34426 seconds
24+
Run Time 0.35016 seconds
2525
######################################################################

UnitTests/IterativeAnalysis/_iter_2/UserInput_iter_2.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,9 @@
112112
TotalConcentrationsOutputName = 'TotalConcentrations.csv'
113113
ExportAtEachStep = 'yes'
114114
generatePercentages = 'no'
115-
checkpoint = 3.5177747
116-
start = 3.0687716
117-
timeSinceLastCheckpoint = 0.2388444999999999
115+
checkpoint = 3.8374273
116+
start = 3.3668311
117+
timeSinceLastCheckpoint = 0.24987629999999994
118118
iterationNumber = 1
119119

120120
__var_list__ = ['referenceFileNamesList','referenceFormsList','collectedFileName','referencePatternTimeRanges','ionizationDataFileName','iterativeAnalysis','iterationNumber','iterationSuffix','unusedMolecules','oldReferenceFileName','oldCollectedFileName','nextRefFileName','nextExpFileName','preProcessing','dataAnalysis','dataSimulation','grapher','stopAtGraphs','timeRangeLimit','timeRangeStart','timeRangeFinish','specificMolecules','chosenMoleculesNames','specificMassFragments','chosenMassFragments','moleculeLikelihoods','sensitivityValues','linearBaselineCorrectionSemiAutomatic','baselineType','massesToBackgroundCorrect','earlyBaselineTimes','lateBaselineTimes','backgroundMassFragment','backgroundSlopes','backgroundIntercepts','interpolateYorN','marginalChangeRestriction','ignorableDeltaYThreshold','dataLowerBound','dataUpperBound','dataRangeSpecifierYorN','signalOrConcentrationRange','csvFile','moleculesToRestrict','csvFileName','bruteIncrements','permutationNum','maxPermutations','scaleRawDataOption','scaleRawDataFactor','measuredReferenceYorN','referenceFileStandardTuning','createMixedTuningPattern','referenceFileExistingTuning','referenceFileDesiredTuning','referenceCorrectionCoefficients','referenceCorrectionCoefficients_cov','extractReferencePatternFromDataOption','rpcMoleculesToChange','rpcMoleculesToChangeMF','rpcTimeRanges','minimalReferenceValue','referenceValueThreshold','referenceSignificantFragmentThresholds','lowerBoundThresholdChooser','massesToLowerBoundThresholdFilter','lowerBoundThresholdPercentage','lowerBoundThresholdAbsolute','dataSmootherYorN','dataSmootherChoice','dataSmootherTimeRadius','dataSmootherPointRadius','dataSmootherHeadersToConfineTo','polynomialOrder','rawSignalThresholdMethod','rawSignalThresholdValue','sensitivityThresholdValue','rawSignalThresholdDivider','rawSignalThresholdLimit','rawSignalThresholdLimitPercent','negativeAnalyzerYorN','NegativeAnalyzerTopNContributors','NegativeAnalyzerBaseNumberOfGridIntervals','calculateUncertaintiesInConcentrations','referenceFileUncertainties','collectedFileUncertainties','referenceCorrectionCoefficientsUncertainties','referenceCorrectionCoefficientsIonizationUncertainties','answer','uniqueOrCommon','slsWeighting','slsFinish','slsUniquePositiveConcentrationsOnly','objectiveFunctionType','distinguished','fullBrute','SLSUniqueExport','implicitSLScorrection','finalOptimization','concentrationFinder','moleculesTSC_List','TSC_List_Type','moleculeSignalTSC_List','massNumberTSC_List','moleculeConcentrationTSC_List','unitsTSC','preProcessedDataOutputName','resolvedScaledConcentrationsOutputName','scaledConcentrationsPercentages','concentrationsOutputName','simulatedSignalsOutputName','TotalConcentrationsOutputName','ExportAtEachStep','generatePercentages','checkpoint','start','timeSinceLastCheckpoint','iterationNumber']

UnitTests/IterativeAnalysis/_iter_3/LogFile.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Tue Nov 9 16:21:59 2021
1+
Tue Nov 9 20:24:23 2021
22

33
referenceFileName = ['AcetaldehydeNISTRefMixed2_iter_3.csv']
44
form = ['xyyy']
@@ -21,5 +21,5 @@ scaleRawDataFactor = 1.0
2121
resolvedScaledConcentrationsOutputName = ScaledConcentrations.csv
2222
concentrationsOutputName = ResolvedConcentrations.csv
2323
simulatedSignalsOutputName = SimulatedRawSignals.csv
24-
Run Time 0.36059 seconds
24+
Run Time 0.36289 seconds
2525
######################################################################

UnitTests/IterativeAnalysis/_iter_3/UserInput_iter_3.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,9 @@
112112
TotalConcentrationsOutputName = 'TotalConcentrations.csv'
113113
ExportAtEachStep = 'yes'
114114
generatePercentages = 'no'
115-
checkpoint = 3.9920898
116-
start = 3.64783
117-
timeSinceLastCheckpoint = 0.22920850000000037
115+
checkpoint = 4.2981038
116+
start = 3.9479398
117+
timeSinceLastCheckpoint = 0.22425789999999957
118118
iterationNumber = 2
119119

120120
__var_list__ = ['referenceFileNamesList','referenceFormsList','collectedFileName','referencePatternTimeRanges','ionizationDataFileName','iterativeAnalysis','iterationNumber','iterationSuffix','unusedMolecules','oldReferenceFileName','oldCollectedFileName','nextRefFileName','nextExpFileName','preProcessing','dataAnalysis','dataSimulation','grapher','stopAtGraphs','timeRangeLimit','timeRangeStart','timeRangeFinish','specificMolecules','chosenMoleculesNames','specificMassFragments','chosenMassFragments','moleculeLikelihoods','sensitivityValues','linearBaselineCorrectionSemiAutomatic','baselineType','massesToBackgroundCorrect','earlyBaselineTimes','lateBaselineTimes','backgroundMassFragment','backgroundSlopes','backgroundIntercepts','interpolateYorN','marginalChangeRestriction','ignorableDeltaYThreshold','dataLowerBound','dataUpperBound','dataRangeSpecifierYorN','signalOrConcentrationRange','csvFile','moleculesToRestrict','csvFileName','bruteIncrements','permutationNum','maxPermutations','scaleRawDataOption','scaleRawDataFactor','measuredReferenceYorN','referenceFileStandardTuning','createMixedTuningPattern','referenceFileExistingTuning','referenceFileDesiredTuning','referenceCorrectionCoefficients','referenceCorrectionCoefficients_cov','extractReferencePatternFromDataOption','rpcMoleculesToChange','rpcMoleculesToChangeMF','rpcTimeRanges','minimalReferenceValue','referenceValueThreshold','referenceSignificantFragmentThresholds','lowerBoundThresholdChooser','massesToLowerBoundThresholdFilter','lowerBoundThresholdPercentage','lowerBoundThresholdAbsolute','dataSmootherYorN','dataSmootherChoice','dataSmootherTimeRadius','dataSmootherPointRadius','dataSmootherHeadersToConfineTo','polynomialOrder','rawSignalThresholdMethod','rawSignalThresholdValue','sensitivityThresholdValue','rawSignalThresholdDivider','rawSignalThresholdLimit','rawSignalThresholdLimitPercent','negativeAnalyzerYorN','NegativeAnalyzerTopNContributors','NegativeAnalyzerBaseNumberOfGridIntervals','calculateUncertaintiesInConcentrations','referenceFileUncertainties','collectedFileUncertainties','referenceCorrectionCoefficientsUncertainties','referenceCorrectionCoefficientsIonizationUncertainties','answer','uniqueOrCommon','slsWeighting','slsFinish','slsUniquePositiveConcentrationsOnly','objectiveFunctionType','distinguished','fullBrute','SLSUniqueExport','implicitSLScorrection','finalOptimization','concentrationFinder','moleculesTSC_List','TSC_List_Type','moleculeSignalTSC_List','massNumberTSC_List','moleculeConcentrationTSC_List','unitsTSC','preProcessedDataOutputName','resolvedScaledConcentrationsOutputName','scaledConcentrationsPercentages','concentrationsOutputName','simulatedSignalsOutputName','TotalConcentrationsOutputName','ExportAtEachStep','generatePercentages','checkpoint','start','timeSinceLastCheckpoint','iterationNumber']

UnitTests/IterativeAnalysis/_iter_4/LogFile.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Tue Nov 9 16:21:59 2021
1+
Tue Nov 9 20:24:23 2021
22

33
referenceFileName = ['AcetaldehydeNISTRefMixed2_iter_4.csv']
44
form = ['xyyy']
@@ -21,5 +21,5 @@ scaleRawDataFactor = 1.0
2121
resolvedScaledConcentrationsOutputName = ScaledConcentrations.csv
2222
concentrationsOutputName = ResolvedConcentrations.csv
2323
simulatedSignalsOutputName = SimulatedRawSignals.csv
24-
Run Time 0.32445 seconds
24+
Run Time 0.33896 seconds
2525
######################################################################

0 commit comments

Comments
 (0)