Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer 3 // * License and Disclaimer * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/ 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. 9 // * include a list of copyright holders. * 10 // * 10 // * * 11 // * Neither the authors of this software syst 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitatio 16 // * for the full disclaimer and the limitation of liability. * 17 // * 17 // * * 18 // * This code implementation is the result 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboratio 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distri 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you ag 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publicati 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Sof 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************* 24 // ******************************************************************** 25 // 25 // 26 // << 27 /// \file medical/GammaTherapy/src/DetectorMes << 28 /// \brief Implementation of the DetectorMesse << 29 // << 30 // ------------------------------------------- 26 // ------------------------------------------------------------- 31 // GEANT4 test IBREM 27 // GEANT4 test IBREM 32 // 28 // 33 // Authors: V.Grichine, V.Ivanchenko 29 // Authors: V.Grichine, V.Ivanchenko 34 // 30 // 35 // Modified: 31 // Modified: 36 // 32 // 37 // 18-02-03 V.Ivanchenko create 33 // 18-02-03 V.Ivanchenko create 38 // 34 // 39 // ------------------------------------------- 35 // ------------------------------------------------------------- 40 36 41 //....oooOO0OOooo........oooOO0OOooo........oo << 37 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 42 //....oooOO0OOooo........oooOO0OOooo........oo << 38 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 43 39 44 #include "DetectorMessenger.hh" 40 #include "DetectorMessenger.hh" 45 << 46 #include "DetectorConstruction.hh" 41 #include "DetectorConstruction.hh" 47 << 42 #include "Histo.hh" >> 43 #include "G4UIdirectory.hh" 48 #include "G4UIcmdWithABool.hh" 44 #include "G4UIcmdWithABool.hh" 49 #include "G4UIcmdWithADoubleAndUnit.hh" << 50 #include "G4UIcmdWithAString.hh" 45 #include "G4UIcmdWithAString.hh" 51 #include "G4UIcmdWithAnInteger.hh" 46 #include "G4UIcmdWithAnInteger.hh" >> 47 #include "G4UIcmdWithADoubleAndUnit.hh" 52 #include "G4UIcmdWithoutParameter.hh" 48 #include "G4UIcmdWithoutParameter.hh" 53 #include "G4UIdirectory.hh" << 54 49 55 //....oooOO0OOooo........oooOO0OOooo........oo << 50 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 56 51 57 DetectorMessenger::DetectorMessenger(DetectorC << 52 DetectorMessenger::DetectorMessenger(DetectorConstruction* h): >> 53 hDet(h) 58 { 54 { 59 fDetDir = new G4UIdirectory("/testem/"); << 55 detDir = new G4UIdirectory("/testem/"); 60 fDetDir->SetGuidance("General commands"); << 56 detDir->SetGuidance("General commands"); 61 fDetDir1 = new G4UIdirectory("/testem/physic << 57 detDir1= new G4UIdirectory("/testem/physics/"); 62 fDetDir1->SetGuidance(" commands to define p << 58 detDir1->SetGuidance(" commands to define physics"); 63 fDetDir2 = new G4UIdirectory("/testem/gun/") << 59 detDir2= new G4UIdirectory("/testem/gun/"); 64 fDetDir2->SetGuidance(" commands to define g << 60 detDir2->SetGuidance(" commands to define gun"); 65 << 61 66 fAbsMaterCmd = new G4UIcmdWithAString("/test << 62 AbsMaterCmd = new G4UIcmdWithAString("/testem/target1Material",this); 67 fAbsMaterCmd->SetGuidance("Select Material o << 63 AbsMaterCmd->SetGuidance("Select Material of the target1."); 68 fAbsMaterCmd->SetParameterName("Material1", << 64 AbsMaterCmd->SetParameterName("Material1",false); 69 fAbsMaterCmd->AvailableForStates(G4State_Pre << 65 AbsMaterCmd->AvailableForStates(G4State_PreInit,G4State_Idle); 70 << 66 71 fWorldMaterCmd = new G4UIcmdWithAString("/te << 67 WorldMaterCmd = new G4UIcmdWithAString("/testem/target2Material",this); 72 fWorldMaterCmd->SetGuidance("Select Material << 68 WorldMaterCmd->SetGuidance("Select Material of the target2."); 73 fWorldMaterCmd->SetParameterName("Material2" << 69 WorldMaterCmd->SetParameterName("Material2",false); 74 fWorldMaterCmd->AvailableForStates(G4State_P << 70 WorldMaterCmd->AvailableForStates(G4State_PreInit,G4State_Idle); 75 << 71 76 fAbsThickCmd = new G4UIcmdWithADoubleAndUnit << 72 AbsThickCmd = new G4UIcmdWithADoubleAndUnit("/testem/mylarZ",this); 77 fAbsThickCmd->SetGuidance("Set mylarZ"); << 73 AbsThickCmd->SetGuidance("Set mylarZ"); 78 fAbsThickCmd->SetParameterName("mylarZ", fal << 74 AbsThickCmd->SetParameterName("mylarZ",false); 79 fAbsThickCmd->SetUnitCategory("Length"); << 75 AbsThickCmd->SetUnitCategory("Length"); 80 fAbsThickCmd->AvailableForStates(G4State_Pre << 76 AbsThickCmd->AvailableForStates(G4State_PreInit,G4State_Idle); 81 << 77 82 fAbsGapCmd = new G4UIcmdWithADoubleAndUnit(" << 78 AbsGapCmd = new G4UIcmdWithADoubleAndUnit("/testem/delta",this); 83 fAbsGapCmd->SetGuidance("Set gap between abs << 79 AbsGapCmd->SetGuidance("Set gap between absorbers"); 84 fAbsGapCmd->SetParameterName("delta", false) << 80 AbsGapCmd->SetParameterName("delta",false); 85 fAbsGapCmd->SetUnitCategory("Length"); << 81 AbsGapCmd->SetUnitCategory("Length"); 86 fAbsGapCmd->AvailableForStates(G4State_PreIn << 82 AbsGapCmd->AvailableForStates(G4State_PreInit,G4State_Idle); 87 << 83 88 fAbsSizYZCmd = new G4UIcmdWithADoubleAndUnit << 84 AbsSizYZCmd = new G4UIcmdWithADoubleAndUnit("/testem/target1Z",this); 89 fAbsSizYZCmd->SetGuidance("Set targeet1Z"); << 85 AbsSizYZCmd->SetGuidance("Set targeet1Z"); 90 fAbsSizYZCmd->SetParameterName("target1Z", f << 86 AbsSizYZCmd->SetParameterName("target1Z",false); 91 fAbsSizYZCmd->SetUnitCategory("Length"); << 87 AbsSizYZCmd->SetUnitCategory("Length"); 92 fAbsSizYZCmd->AvailableForStates(G4State_Pre << 88 AbsSizYZCmd->AvailableForStates(G4State_PreInit,G4State_Idle); 93 << 89 94 fWorldXCmd = new G4UIcmdWithADoubleAndUnit(" << 90 WorldXCmd = new G4UIcmdWithADoubleAndUnit("/testem/target2Z",this); 95 fWorldXCmd->SetGuidance("Set target2Z"); << 91 WorldXCmd->SetGuidance("Set target2Z"); 96 fWorldXCmd->SetParameterName("target2Z", fal << 92 WorldXCmd->SetParameterName("target2Z",false); 97 fWorldXCmd->SetUnitCategory("Length"); << 93 WorldXCmd->SetUnitCategory("Length"); 98 fWorldXCmd->AvailableForStates(G4State_PreIn << 94 WorldXCmd->AvailableForStates(G4State_PreInit,G4State_Idle); 99 << 95 100 fXMagFieldCmd = new G4UIcmdWithADoubleAndUni << 96 UpdateCmd = new G4UIcmdWithoutParameter("/testem/update",this); 101 fXMagFieldCmd->SetGuidance("Define checkShft << 97 UpdateCmd->SetGuidance("Update calorimeter geometry."); 102 fXMagFieldCmd->SetParameterName("CheckSZ", f << 98 UpdateCmd->SetGuidance("This command MUST be applied before \"beamOn\" "); 103 fXMagFieldCmd->SetUnitCategory("Length"); << 99 UpdateCmd->SetGuidance("if you changed geometrical value(s)."); 104 fXMagFieldCmd->AvailableForStates(G4State_Pr << 100 UpdateCmd->AvailableForStates(G4State_PreInit,G4State_Idle); 105 << 101 106 fYMagFieldCmd = new G4UIcmdWithADoubleAndUni << 102 XMagFieldCmd = new G4UIcmdWithADoubleAndUnit("/testem/checkShiftZ",this); 107 fYMagFieldCmd->SetGuidance("Define sensitive << 103 XMagFieldCmd->SetGuidance("Define checkShftZ"); 108 fYMagFieldCmd->SetParameterName("sdZ", false << 104 XMagFieldCmd->SetParameterName("CheckSZ",false); 109 fYMagFieldCmd->SetUnitCategory("Length"); << 105 XMagFieldCmd->SetUnitCategory("Length"); 110 fYMagFieldCmd->AvailableForStates(G4State_Pr << 106 XMagFieldCmd->AvailableForStates(G4State_PreInit,G4State_Idle); 111 << 107 112 fZMagFieldCmd = new G4UIcmdWithADoubleAndUni << 108 YMagFieldCmd = new G4UIcmdWithADoubleAndUnit("/testem/sdZ",this); 113 fZMagFieldCmd->SetGuidance("Define shift of << 109 YMagFieldCmd->SetGuidance("Define sensitive detector Z"); 114 fZMagFieldCmd->SetParameterName("sdShiftZ", << 110 YMagFieldCmd->SetParameterName("sdZ",false); 115 fZMagFieldCmd->SetUnitCategory("Length"); << 111 YMagFieldCmd->SetUnitCategory("Length"); 116 fZMagFieldCmd->AvailableForStates(G4State_Pr << 112 YMagFieldCmd->AvailableForStates(G4State_PreInit,G4State_Idle); 117 << 113 118 fNumOfAbsCmd = new G4UIcmdWithAnInteger("/te << 114 ZMagFieldCmd = new G4UIcmdWithADoubleAndUnit("/testem/sdShiftZ",this); 119 fNumOfAbsCmd->SetGuidance("Set number divisi << 115 ZMagFieldCmd->SetGuidance("Define shift of sensitive detector"); 120 fNumOfAbsCmd->SetParameterName("NR", false); << 116 ZMagFieldCmd->SetParameterName("sdShiftZ",false); 121 fNumOfAbsCmd->AvailableForStates(G4State_Pre << 117 ZMagFieldCmd->SetUnitCategory("Length"); 122 << 118 ZMagFieldCmd->AvailableForStates(G4State_PreInit,G4State_Idle); 123 fNumOfEvt = new G4UIcmdWithAnInteger("/teste << 119 124 fNumOfEvt->SetGuidance("Set number of divisi << 120 HistoCmd = new G4UIcmdWithAString("/testem/histoName",this); 125 fNumOfEvt->SetParameterName("NZ", false); << 121 HistoCmd->SetGuidance("Set the name of the histo file"); 126 fNumOfEvt->AvailableForStates(G4State_PreIni << 122 HistoCmd->SetParameterName("histo",false); 127 << 123 HistoCmd->AvailableForStates(G4State_PreInit,G4State_Idle); 128 fVerbCmd = new G4UIcmdWithAnInteger("/testem << 124 129 fVerbCmd->SetGuidance("Set verbose for "); << 125 HistoTCmd = new G4UIcmdWithAString("/testem/histoType",this); 130 fVerbCmd->SetParameterName("verb", false); << 126 HistoTCmd->SetGuidance("Set the type of the histo file"); 131 fVerbCmd->AvailableForStates(G4State_PreInit << 127 HistoTCmd->SetParameterName("histoT",false); 132 << 128 HistoTCmd->AvailableForStates(G4State_PreInit,G4State_Idle); 133 fIntCmd = new G4UIcmdWithAnInteger("/testem/ << 129 134 fIntCmd->SetGuidance("Set number of division << 130 ntupCmd = new G4UIcmdWithABool("/testem/ntuple",this); 135 fIntCmd->SetParameterName("NZ", false); << 131 ntupCmd->SetGuidance("Set ntuple to fill"); 136 fIntCmd->AvailableForStates(G4State_PreInit) << 132 ntupCmd->SetParameterName("ntuple",false); 137 << 133 ntupCmd->AvailableForStates(G4State_PreInit,G4State_Idle); 138 fDeltaECmd = new G4UIcmdWithADoubleAndUnit(" << 134 139 fDeltaECmd->SetGuidance("Define scale of sec << 135 NumOfAbsCmd = new G4UIcmdWithAnInteger("/testem/numberDivR",this); 140 fDeltaECmd->SetParameterName("DeltaE", false << 136 NumOfAbsCmd->SetGuidance("Set number divisions R"); 141 fDeltaECmd->SetUnitCategory("Energy"); << 137 NumOfAbsCmd->SetParameterName("NR",false); 142 fDeltaECmd->AvailableForStates(G4State_PreIn << 138 NumOfAbsCmd->AvailableForStates(G4State_PreInit,G4State_Idle); >> 139 >> 140 NumOfEvt = new G4UIcmdWithAnInteger("/testem/numberDivZ",this); >> 141 NumOfEvt->SetGuidance("Set number of divisions Z"); >> 142 NumOfEvt->SetParameterName("NZ",false); >> 143 NumOfEvt->AvailableForStates(G4State_PreInit,G4State_Idle); >> 144 >> 145 verbCmd = new G4UIcmdWithAnInteger("/testem/verbose",this); >> 146 verbCmd->SetGuidance("Set verbose for "); >> 147 verbCmd->SetParameterName("verb",false); >> 148 verbCmd->AvailableForStates(G4State_PreInit,G4State_Idle); >> 149 >> 150 intCmd = new G4UIcmdWithAnInteger("/testem/numberDivE",this); >> 151 intCmd->SetGuidance("Set number of divisions E"); >> 152 intCmd->SetParameterName("NZ",false); >> 153 intCmd->AvailableForStates(G4State_PreInit); >> 154 >> 155 nhistCmd = new G4UIcmdWithAnInteger("/testem/histoNumber",this); >> 156 nhistCmd->SetGuidance("Set number of histograms to fill"); >> 157 nhistCmd->SetParameterName("HistoNumber",false); >> 158 nhistCmd->AvailableForStates(G4State_PreInit,G4State_Idle); >> 159 >> 160 nDebugSCmd = new G4UIcmdWithAnInteger("/testem/nFirstEventToDebug",this); >> 161 nDebugSCmd->SetGuidance("Set number of the first event to debug"); >> 162 nDebugSCmd->SetParameterName("nFirstEventToDebug",false); >> 163 nDebugSCmd->AvailableForStates(G4State_PreInit,G4State_Idle); >> 164 >> 165 nDebugECmd = new G4UIcmdWithAnInteger("/testem/nLastEventToDebug",this); >> 166 nDebugECmd->SetGuidance("Set number of the last event to debug"); >> 167 nDebugECmd->SetParameterName("nLastEventToDebug",false); >> 168 nDebugECmd->AvailableForStates(G4State_PreInit,G4State_Idle); >> 169 >> 170 DeltaECmd = new G4UIcmdWithADoubleAndUnit("/testem/maxEnergy",this); >> 171 DeltaECmd->SetGuidance("Define scale of secondary energy histogram"); >> 172 DeltaECmd->SetParameterName("DeltaE",false); >> 173 DeltaECmd->SetUnitCategory("Energy"); >> 174 DeltaECmd->AvailableForStates(G4State_PreInit,G4State_Idle); >> 175 143 } 176 } 144 177 145 //....oooOO0OOooo........oooOO0OOooo........oo << 178 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 146 179 147 DetectorMessenger::~DetectorMessenger() 180 DetectorMessenger::~DetectorMessenger() 148 { 181 { 149 delete fDetDir; << 182 delete NumOfAbsCmd; 150 delete fDetDir1; << 183 delete AbsMaterCmd; 151 delete fDetDir2; << 184 delete AbsThickCmd; 152 << 185 delete AbsGapCmd; 153 delete fAbsMaterCmd; << 186 delete AbsSizYZCmd; 154 delete fAbsThickCmd; << 187 delete WorldMaterCmd; 155 delete fAbsGapCmd; << 188 delete WorldXCmd; 156 delete fAbsSizYZCmd; << 189 delete UpdateCmd; 157 delete fWorldMaterCmd; << 190 delete XMagFieldCmd; 158 delete fWorldXCmd; << 191 delete YMagFieldCmd; 159 delete fXMagFieldCmd; << 192 delete ZMagFieldCmd; 160 delete fYMagFieldCmd; << 193 delete HistoCmd; 161 delete fZMagFieldCmd; << 194 delete HistoTCmd; 162 delete fNumOfAbsCmd; << 195 delete NumOfEvt; 163 delete fNumOfEvt; << 196 delete verbCmd; 164 delete fVerbCmd; << 197 delete intCmd; 165 delete fIntCmd; << 198 delete nhistCmd; 166 delete fDeltaECmd; << 199 delete nDebugSCmd; >> 200 delete nDebugECmd; >> 201 delete detDir; >> 202 delete detDir1; >> 203 delete detDir2; >> 204 delete DeltaECmd; >> 205 delete ntupCmd; 167 } 206 } 168 207 169 //....oooOO0OOooo........oooOO0OOooo........oo << 208 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 170 209 171 void DetectorMessenger::SetNewValue(G4UIcomman << 210 void DetectorMessenger::SetNewValue(G4UIcommand* command,G4String newValue) 172 { 211 { 173 if (command == fAbsMaterCmd) { << 212 if( command == AbsMaterCmd ) 174 fDetector->SetTarget1Material(newValue); << 213 { hDet->setTarget1Material(newValue);} 175 } << 214 176 << 215 if( command == WorldMaterCmd ) 177 if (command == fWorldMaterCmd) { << 216 { hDet->setTarget2Material(newValue);} 178 fDetector->SetTarget2Material(newValue); << 217 179 } << 218 if( command == AbsThickCmd ) 180 << 219 { hDet->setMylarZ(AbsThickCmd->GetNewDoubleValue(newValue));} 181 if (command == fAbsThickCmd) { << 220 182 fDetector->SetMylarZ(fAbsThickCmd->GetNewD << 221 if( command == AbsGapCmd ) 183 } << 222 { hDet->setGap(AbsGapCmd->GetNewDoubleValue(newValue));} 184 << 223 185 if (command == fAbsGapCmd) { << 224 if( command == AbsSizYZCmd ) 186 fDetector->SetGap(fAbsGapCmd->GetNewDouble << 225 { hDet->setTarget1Z(AbsSizYZCmd->GetNewDoubleValue(newValue));} 187 } << 226 188 << 227 if( command == WorldXCmd ) 189 if (command == fAbsSizYZCmd) { << 228 { hDet->setTarget2Z(WorldXCmd->GetNewDoubleValue(newValue));} 190 fDetector->SetTarget1Z(fAbsSizYZCmd->GetNe << 229 191 } << 230 if( command == UpdateCmd ) 192 << 231 { hDet->UpdateGeometry(); } 193 if (command == fWorldXCmd) { << 232 194 fDetector->SetTarget2Z(fWorldXCmd->GetNewD << 233 if( command == XMagFieldCmd ) 195 } << 234 { hDet->setCheckShiftZ(XMagFieldCmd->GetNewDoubleValue(newValue));} 196 << 235 197 if (command == fXMagFieldCmd) { << 236 if( command == YMagFieldCmd ) 198 fDetector->SetCheckShiftZ(fXMagFieldCmd->G << 237 { G4double x = YMagFieldCmd->GetNewDoubleValue(newValue); 199 } << 238 hDet->setAbsorberZ(x); 200 << 239 } 201 if (command == fYMagFieldCmd) { << 240 202 G4double x = fYMagFieldCmd->GetNewDoubleVa << 241 if( command == ZMagFieldCmd ) 203 fDetector->SetAbsorberZ(x); << 242 { hDet->setAbsorberShiftZ(ZMagFieldCmd->GetNewDoubleValue(newValue));} 204 } << 243 205 << 244 if( command == HistoCmd ) 206 if (command == fZMagFieldCmd) { << 245 { (Histo::GetPointer())->SetHistoName(newValue);} 207 fDetector->SetAbsorberShiftZ(fZMagFieldCmd << 246 208 } << 247 if( command == HistoTCmd ) 209 << 248 { (Histo::GetPointer())->SetHistoType(newValue);} 210 if (command == fNumOfAbsCmd) { << 249 211 fDetector->SetNumberDivR(fNumOfAbsCmd->Get << 250 if( command == ntupCmd ) 212 } << 251 { (Histo::GetPointer())->SetNtuple(ntupCmd->GetNewBoolValue(newValue));} 213 << 252 214 if (command == fNumOfEvt) { << 253 if( command == NumOfAbsCmd ) 215 fDetector->SetNumberDivZ(fNumOfEvt->GetNew << 254 {(Histo::GetPointer())->SetNumberDivR(NumOfAbsCmd->GetNewIntValue(newValue));} 216 } << 255 217 << 256 if( command == NumOfEvt ) 218 if (command == fIntCmd) { << 257 {(Histo::GetPointer())->SetNumberDivZ(NumOfEvt->GetNewIntValue(newValue));} 219 fDetector->SetNumberDivE(fIntCmd->GetNewIn << 258 220 } << 259 if( command == verbCmd ){ 221 if (command == fDeltaECmd) { << 260 G4int ver = verbCmd->GetNewIntValue(newValue); 222 fDetector->SetMaxEnergy(fDeltaECmd->GetNew << 261 (Histo::GetPointer())->SetVerbose(ver); 223 } << 262 } 224 << 263 225 if (command == fVerbCmd) { << 264 if( command == intCmd ) 226 G4int ver = fVerbCmd->GetNewIntValue(newVa << 265 {(Histo::GetPointer())->SetNumberDivE(intCmd->GetNewIntValue(newValue));} 227 fDetector->SetVerbose(ver); << 266 228 } << 267 if( command == nhistCmd ) >> 268 { (Histo::GetPointer())->SetHistoNumber(nhistCmd->GetNewIntValue(newValue));} >> 269 >> 270 if( command == nDebugSCmd ) >> 271 {(Histo::GetPointer())->SetFirstEventToDebug(nDebugSCmd->GetNewIntValue(newValue));} >> 272 >> 273 if( command == nDebugECmd ) >> 274 {(Histo::GetPointer())->SetLastEventToDebug(nDebugECmd->GetNewIntValue(newValue));} >> 275 >> 276 if( command == DeltaECmd ) >> 277 {(Histo::GetPointer()) ->SetMaxEnergy(DeltaECmd->GetNewDoubleValue(newValue));} >> 278 229 } 279 } 230 280 231 //....oooOO0OOooo........oooOO0OOooo........oo << 281 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 232 282