diff --git a/L1Trigger/L1TMuonEndCap/interface/SectorProcessorLUT.h b/L1Trigger/L1TMuonEndCap/interface/SectorProcessorLUT.h index 74ec08339445e..b1f6637437b72 100644 --- a/L1Trigger/L1TMuonEndCap/interface/SectorProcessorLUT.h +++ b/L1Trigger/L1TMuonEndCap/interface/SectorProcessorLUT.h @@ -11,7 +11,7 @@ class SectorProcessorLUT { explicit SectorProcessorLUT(); ~SectorProcessorLUT(); - void read(int pc_lut_version); + void read(bool pc_lut_data, int pc_lut_version); uint32_t get_ph_init(int fw_endcap, int fw_sector, int pc_lut_id) const; diff --git a/L1Trigger/L1TMuonEndCap/python/simEmtfDigis_cfi.py b/L1Trigger/L1TMuonEndCap/python/simEmtfDigis_cfi.py index 795c6ed7d3258..ae48f493a8fe5 100644 --- a/L1Trigger/L1TMuonEndCap/python/simEmtfDigis_cfi.py +++ b/L1Trigger/L1TMuonEndCap/python/simEmtfDigis_cfi.py @@ -21,10 +21,10 @@ # * 'simCscTriggerPrimitiveDigis','MPCSORTED' : simulated trigger primitives (LCTs) from re-emulating CSC digis # * 'csctfDigis' : real trigger primitives as received by CSCTF (legacy trigger), available only in 2016 data # * 'emtfStage2Digis' : real trigger primitives as received by EMTF, unpacked in EventFilter/L1TRawToDigi/ - CSCInput = cms.InputTag('simCscTriggerPrimitiveDigis','MPCSORTED'), - RPCInput = cms.InputTag('simMuonRPCDigis'), + CSCInput = cms.InputTag('simCscTriggerPrimitiveDigis','MPCSORTED'), + RPCInput = cms.InputTag('simMuonRPCDigis'), CPPFInput = cms.InputTag('simCPPFDigis'), ## Cannot use in MC workflow, does not exist yet. CPPFEnable set to False - AWB 01.06.18 - GEMInput = cms.InputTag('simMuonGEMPadDigis'), + GEMInput = cms.InputTag('simMuonGEMPadDigis'), # Run with CSC, RPC, GEM CSCEnable = cms.bool(True), # Use CSC LCTs from the MPCs in track-building @@ -47,7 +47,7 @@ # Sector processor primitive-conversion parameters spPCParams16 = cms.PSet( - PrimConvLUT = cms.int32(1), # v0 and v1 LUTs used at different times, "-1" for local CPPF files (only works if FWConfig = False) + PrimConvLUT = cms.int32(2), # v0, v1, and v2 LUTs used at different times, "-1" for local CPPF files (only works if FWConfig = False) ZoneBoundaries = cms.vint32(0,41,49,87,127), # Vertical boundaries of track-building zones, in integer theta (5 for 4 zones) # ZoneBoundaries = cms.vint32(0,36,54,96,127), # New proposed zone boundaries ZoneOverlap = cms.int32(2), # Overlap between zones @@ -125,6 +125,7 @@ GEMInput = cms.InputTag('muonGEMPadDigis'), CPPFEnable = cms.bool(True), # Use CPPF-emulated clustered RPC hits from CPPF as the RPC hits + ) simEmtfDigis = simEmtfDigisMC.clone() diff --git a/L1Trigger/L1TMuonEndCap/src/ConditionHelper.cc b/L1Trigger/L1TMuonEndCap/src/ConditionHelper.cc index cdacb1fc4ebf2..7c220c26d8cf6 100644 --- a/L1Trigger/L1TMuonEndCap/src/ConditionHelper.cc +++ b/L1Trigger/L1TMuonEndCap/src/ConditionHelper.cc @@ -79,7 +79,12 @@ unsigned int ConditionHelper::get_pc_lut_version() const { // Hack until we figure out why the database is returning "0" for 2017 data - AWB 04.08.17 // std::cout << " - Getting hacked PC LUT version from ConditionHelper: version = " << (params_->firmwareVersion_ >= 50000) << std::endl; - if (params_->firmwareVersion_ < 50000) // for 2016 + if (params_->firmwareVersion_ < 50000) { // For 2016 return 0; - return 1; + } else if (params_->firmwareVersion_ < 1537467271) { // From the beginning of 2017 + return 1; // Corresponding to FW timestamps before Sept. 20, 2018 + } else { + return 2; // Starting September 26, 2018 with run 323556 (data only, not in MC) + } + } diff --git a/L1Trigger/L1TMuonEndCap/src/SectorProcessorLUT.cc b/L1Trigger/L1TMuonEndCap/src/SectorProcessorLUT.cc index c038a6d38dbd9..f51cef11c8071 100644 --- a/L1Trigger/L1TMuonEndCap/src/SectorProcessorLUT.cc +++ b/L1Trigger/L1TMuonEndCap/src/SectorProcessorLUT.cc @@ -19,18 +19,25 @@ SectorProcessorLUT::~SectorProcessorLUT() { } -void SectorProcessorLUT::read(int pc_lut_version) { +void SectorProcessorLUT::read(bool pc_lut_data, int pc_lut_version) { if (version_ == pc_lut_version) return; - edm::LogInfo("L1T") << "EMTF using pc_lut_ver: " << pc_lut_version; + edm::LogInfo("L1T") << "EMTF using pc_lut_ver: " << pc_lut_version + << ", configured for " << (pc_lut_data ? "data" : "MC"); std::string coord_lut_dir = ""; if (pc_lut_version == 0) - coord_lut_dir = "ph_lut_v1"; // All year 2016 + coord_lut_dir = "ph_lut_v1"; // All year 2016 else if (pc_lut_version == 1) - coord_lut_dir = "ph_lut_v2"; // Beginning of 2017 + coord_lut_dir = "ph_lut_v2"; // Beginning of 2017, improved alignment from ideal CMS geometry (MC) + else if (pc_lut_version == 2 && pc_lut_data) + coord_lut_dir = "ph_lut_v3_data"; // Update in September 2017 from ReReco alignment, data only + else if (pc_lut_version == 2) + coord_lut_dir = "ph_lut_v2"; // MC still uses ideal CMS aligment + else if (pc_lut_version == -1 && pc_lut_data) + coord_lut_dir = "ph_lut_v3_data"; // September 2017 data LCT alignment, but use local CPPF LUTs for RPC else if (pc_lut_version == -1) - coord_lut_dir = "ph_lut_v2"; // Beginning of 2017, use local CPPF LUTs + coord_lut_dir = "ph_lut_v2"; // MC using ideal CMS LCT alignment, but use local CPPF LUTs for RPC else throw cms::Exception("SectorProcessorLUT") << "Trying to use EMTF pc_lut_version = " << pc_lut_version << ", does not exist!"; diff --git a/L1Trigger/L1TMuonEndCap/src/TrackFinder.cc b/L1Trigger/L1TMuonEndCap/src/TrackFinder.cc index ff05b3e86ee88..fde0711e82a01 100644 --- a/L1Trigger/L1TMuonEndCap/src/TrackFinder.cc +++ b/L1Trigger/L1TMuonEndCap/src/TrackFinder.cc @@ -153,7 +153,7 @@ void TrackFinder::process( // Run each sector processor // Reload primitive conversion LUTs if necessary - sector_processor_lut_.read(fwConfig_ ? condition_helper_.get_pc_lut_version() : primConvLUT_); + sector_processor_lut_.read(iEvent.isRealData(), fwConfig_ ? condition_helper_.get_pc_lut_version() : primConvLUT_); // Reload pT LUT if necessary pt_assign_engine_->load(condition_helper_.get_pt_lut_version(), &(condition_helper_.getForest())); diff --git a/L1Trigger/L1TMuonEndCap/test/tools/MakeCoordLUT.cc b/L1Trigger/L1TMuonEndCap/test/tools/MakeCoordLUT.cc index 58949e8d4f59c..6f8822b785d00 100644 --- a/L1Trigger/L1TMuonEndCap/test/tools/MakeCoordLUT.cc +++ b/L1Trigger/L1TMuonEndCap/test/tools/MakeCoordLUT.cc @@ -220,42 +220,41 @@ void MakeCoordLUT::generateLUTs_init() { return; } +// values for ph and th init values hardcoded in verilog zones.v +// these are with offset relative to actual init values to allow for chamber displacement +// [station_5][chamber_16] +// ME1 chambers 13,14,15,16 are neighbor sector chambers 3,6,9,12 +// ME2 chambers 10,11 are neighbor sector chambers 3,9 +// NOTE: since Sep 2016, th_init_hard and ph_cover_hard are not being used anymore +static const int ph_init_hard[5][16] = { + {39, 57, 76, 39, 58, 76, 41, 60, 79, 39, 57, 76, 21, 21, 23, 21}, + {95, 114, 132, 95, 114, 133, 98, 116, 135, 95, 114, 132, 0, 0, 0, 0}, + {38, 76, 113, 39, 58, 76, 95, 114, 132, 1, 21, 0, 0, 0, 0, 0}, + {38, 76, 113, 39, 58, 76, 95, 114, 132, 1, 21, 0, 0, 0, 0, 0}, + {38, 76, 113, 38, 57, 76, 95, 113, 132, 1, 20, 0, 0, 0, 0, 0} +}; + +static const int th_init_hard[5][16] = { + {1,1,1,42,42,42,94,94,94,1,1, 1,1,42,94, 1}, + {1,1,1,42,42,42,94,94,94,1,1, 1,0, 0, 0, 0}, + {1,1,1,48,48,48,48,48,48,1,48,0,0, 0, 0, 0}, + {1,1,1,40,40,40,40,40,40,1,40,0,0, 0, 0, 0}, + {2,2,2,34,34,34,34,34,34,2,34,0,0, 0, 0, 0} +}; + +// hardcoded chamber ph coverage in verilog prim_conv.v +static const int ph_cover_hard[5][16] = { + {40,40,40,40,40,40,30,30,30,40,40,40,40,40,30,40}, + {40,40,40,40,40,40,30,30,30,40,40,40, 0, 0, 0, 0}, + {80,80,80,40,40,40,40,40,40,80,40, 0, 0, 0, 0, 0}, + {80,80,80,40,40,40,40,40,40,80,40, 0, 0, 0, 0, 0}, + {80,80,80,40,40,40,40,40,40,80,40, 0, 0, 0, 0, 0} +}; + void MakeCoordLUT::generateLUTs_run() { constexpr double theta_scale = (UPPER_THETA - LOWER_THETA)/128; // = 0.28515625 (7 bits encode 128 values) constexpr double nominal_pitch = 10./75.; // = 0.133333 (ME2/2 strip pitch. 10-degree chamber, 80 strips - 5 overlap strips) - // values for ph and th init values hardcoded in verilog zones.v - // these are with offset relative to actual init values to allow for chamber displacement - // [station_5][chamber_16] - // ME1 chambers 13,14,15,16 are neighbor sector chambers 3,6,9,12 - // ME2 chambers 10,11 are neighbor sector chambers 3,9 - // NOTE: since Sep 2016, th_init_hard and ph_cover_hard are not being used anymore - const int ph_init_hard[5][16] = { - {39, 57, 76, 39, 58, 76, 41, 60, 79, 39, 57, 76, 21, 21, 23, 21}, - {95, 114, 132, 95, 114, 133, 98, 116, 135, 95, 114, 132, 0, 0, 0, 0}, - {38, 76, 113, 39, 58, 76, 95, 114, 132, 1, 21, 0, 0, 0, 0, 0}, - {38, 76, 113, 39, 58, 76, 95, 114, 132, 1, 21, 0, 0, 0, 0, 0}, - {38, 76, 113, 38, 57, 76, 95, 113, 132, 1, 20, 0, 0, 0, 0, 0} - }; - - const int th_init_hard[5][16] = { - {1,1,1,42,42,42,94,94,94,1,1, 1,1,42,94, 1}, - {1,1,1,42,42,42,94,94,94,1,1, 1,0, 0, 0, 0}, - {1,1,1,48,48,48,48,48,48,1,48,0,0, 0, 0, 0}, - {1,1,1,40,40,40,40,40,40,1,40,0,0, 0, 0, 0}, - {2,2,2,34,34,34,34,34,34,2,34,0,0, 0, 0, 0} - }; - - // hardcoded chamber ph coverage in verilog prim_conv.v - const int ph_cover_hard[5][16] = { - {40,40,40,40,40,40,30,30,30,40,40,40,40,40,30,40}, - {40,40,40,40,40,40,30,30,30,40,40,40, 0, 0, 0, 0}, - {80,80,80,40,40,40,40,40,40,80,40, 0, 0, 0, 0, 0}, - {80,80,80,40,40,40,40,40,40,80,40, 0, 0, 0, 0, 0}, - {80,80,80,40,40,40,40,40,40,80,40, 0, 0, 0, 0, 0} - }; - - for (int endcap = MIN_ENDCAP; endcap <= MAX_ENDCAP; ++endcap) { for (int sector = MIN_TRIGSECTOR; sector <= MAX_TRIGSECTOR; ++sector) { for (int station = 1; station <= 4; ++station) { @@ -541,6 +540,15 @@ void MakeCoordLUT::validateLUTs() { int es = 0; int st = 0; int ch = 0; + // + int endcap = 0; + int station = 0; + int sector = 0; + int subsector = 0; + int ring = 0; + int chamber = 0; + int CSC_ID = 0; + // int strip = 0; // it is half-strip, despite the name int wire = 0; // it is wiregroup, despite the name int fph_int = 0; @@ -555,6 +563,15 @@ void MakeCoordLUT::validateLUTs() { ttree->Branch("es" , &es ); ttree->Branch("st" , &st ); ttree->Branch("ch" , &ch ); + // + ttree->Branch("endcap" , &endcap ); + ttree->Branch("station" , &station ); + ttree->Branch("sector" , §or ); + ttree->Branch("subsector", &subsector ); + ttree->Branch("ring" , &ring ); + ttree->Branch("chamber" , &chamber ); + ttree->Branch("CSC_ID" , &CSC_ID ); + // ttree->Branch("strip" , &strip ); ttree->Branch("wire" , &wire ); ttree->Branch("fph_int", &fph_int); @@ -588,11 +605,11 @@ void MakeCoordLUT::validateLUTs() { assert(es < 12 && st < 5 && ch < 16); // Retrieve endcap, sector, subsector, station, chamber - int endcap = (es/6) + 1; - int sector = (es%6) + 1; - int subsector = (st <= 1) ? st + 1 : 0; - int station = (st <= 1) ? 1 : st; - int chamber = ch + 1; + endcap = (es/6) + 1; + sector = (es%6) + 1; + subsector = (st <= 1) ? st + 1 : 0; + station = (st <= 1) ? 1 : st; + chamber = ch + 1; bool is_me11a = false; bool is_neighbor = false; @@ -638,12 +655,14 @@ void MakeCoordLUT::validateLUTs() { } } + CSC_ID = rcscid; + // Set maxWire, maxStrip const CSCDetId cscDetId = getCSCDetId(endcap, rsector, rsubsector, station, rcscid, is_me11a); const CSCChamber* chamb = theCSCGeometry_->chamber(cscDetId); const CSCLayerGeometry* layerGeom = chamb->layer(CSCConstants::KEY_CLCT_LAYER)->geometry(); - const int ring = cscDetId.ring(); + ring = cscDetId.ring(); const int maxWire = layerGeom->numberOfWireGroups(); const int maxStrip = layerGeom->numberOfStrips(); @@ -712,6 +731,9 @@ void MakeCoordLUT::validateLUTs() { int fph = ph_init_full[es][st][ch]; fph = fph + ph_tmp_sign * ph_tmp; + // ph_init_hard is used to calculate zone_hit in the firmware + assert(((fph + (1<<4)) >> 5) >= ph_init_hard[st][ch]); + // ___________________________________________________________________ // theta conversion @@ -1023,7 +1045,19 @@ double MakeCoordLUT::getSectorPhi(int endcap, int sector, int subsector, int sta #ifndef REPRODUCE_OLD_LUTS // but sector boundary does depend on endcap. apply additional correction to make integer phi 0 // lines up at -22 deg (Jia Fu, 2016-11-12) - sectorStartPhi = (endcap == 2) ? sectorStartPhi + 36./60 : sectorStartPhi + 28./60; + //sectorStartPhi = (endcap == 2) ? sectorStartPhi + 36./60 : sectorStartPhi + 28./60; + + // Manually lines up at -22 deg (Jia Fu, 2018-09-19) + double oldSectorStartPhi = sectorStartPhi; + sectorStartPhi = -22. + 15. + (60. * (sector-1)); + if (isNeighbor) { + // This chamber comes from the neighbor sector into the native sector + // Use the native sector sectorStartPhi (+60 deg) + sectorStartPhi += 60.; + } + if (sectorStartPhi > 180.) + sectorStartPhi -= 360.; + assert(std::abs(oldSectorStartPhi-sectorStartPhi) < 2.); // sanity check #endif double res = deltaPhiInDegrees(globalPhi, sectorStartPhi); diff --git a/L1Trigger/L1TMuonEndCap/test/tools/README.md b/L1Trigger/L1TMuonEndCap/test/tools/README.md new file mode 100644 index 0000000000000..3691bf3e96f4f --- /dev/null +++ b/L1Trigger/L1TMuonEndCap/test/tools/README.md @@ -0,0 +1,43 @@ + +############################# +### EMTF emulator tools ### +############################# + +------------------------------------------------- +-- Primitive Conversion Look-Up Table generation +------------------------------------------------- + +'PC LUTs' are responsible for converting the CSC LCT strip and wire info into phi and theta coordinates +New PC LUTs can be generated for data (using real CMS geometry) or MC as follows +The latest Global Tag can be found at: https://twiki.cern.ch/twiki/bin/view/CMSPublic/SWGuideFrontierConditions + +cd CMSSW_X_Y_Z/src +cmsenv +cd L1Trigger/L1TMuonEndCap/test/tools/ +mkdir -p pc_luts/firmware_data ## To store the 924 actual LUTs needed by the firmware +mkdir pc_luts/firmware_MC ## These files are then simplified into 6 text files used by the emulator +cmsRun make_coordlut_data.py ## To create 924 LUTs from real CMSSW geometry, specified by process.GlobalTag +cmsRun make_coordlut_MC.py ## Instead uses ideal CMS geometry / alignment from MC +python write_ph_lut_v2.py ## Modify 'path' in file to specify data or MC + +The 6 text files for the emulator will appear in pc_luts/emulator_data or pc_luts/emulator_MC +These can be copied over to the L1Trigger/L1TMuon/data/emtf_luts directory as follows: + +cd CMSSW_X_Y_Z/src +git cms-addpkg L1Trigger/L1TMuon +git clone https://github.com/cms-l1t-offline/L1Trigger-L1TMuon.git L1Trigger/L1TMuon/data +mkdir L1Trigger/L1TMuon/data/emtf_luts/ph_lut_new +cp L1Trigger/L1TMuonEndCap/test/tools/pc_luts/emulator_data/* L1Trigger/L1TMuon/data/emtf_luts/ph_lut_new/ + +The new path can then be added to L1Trigger/L1TMuonEndCap/src/SectorProcessorLUT.cc in the lines containing "ph_lut" + +To validate that the coordinate transformation worked properly, you can do the following: + +cd L1Trigger/L1TMuonEndCap/test/tools/ +root -l pc_luts/firmware_data/validate.root +## EMTF emulator vs. CMS simulation phi or theta coordinate +tree->Draw("fph_emu - fph_sim : fph_sim >> dPh_vs_phi(360,-180,180,80,-0.5,0.5)","","colz") +tree->Draw("fth_emu - fth_sim : fph_sim >> dTh_vs_phi(360,-180,180,80,-1.0,1.0)","","colz") +## Look at a specific region, e.g. ME+1/1a +tree->Draw("fph_emu - fph_sim : fph_sim >> dPh_vs_phi(360,-180,180,80,-0.5,0.5)","(endcap == 1 && station == 1 && ring == 4)","colz") + diff --git a/L1Trigger/L1TMuonEndCap/test/tools/make_coordlut.py b/L1Trigger/L1TMuonEndCap/test/tools/make_coordlut_MC.py similarity index 83% rename from L1Trigger/L1TMuonEndCap/test/tools/make_coordlut.py rename to L1Trigger/L1TMuonEndCap/test/tools/make_coordlut_MC.py index 9a265b72d981c..33948860f1664 100644 --- a/L1Trigger/L1TMuonEndCap/test/tools/make_coordlut.py +++ b/L1Trigger/L1TMuonEndCap/test/tools/make_coordlut_MC.py @@ -1,16 +1,14 @@ -from __future__ import print_function import FWCore.ParameterSet.Config as cms process = cms.Process("Whatever") -#process.load('Configuration.Geometry.GeometryExtended2016Reco_cff') process.load("Configuration.StandardSequences.GeometryDB_cff") # load from DB process.load('Configuration.StandardSequences.MagneticField_cff') process.load("Configuration.StandardSequences.FrontierConditions_GlobalTag_cff") from Configuration.AlCa.GlobalTag import GlobalTag process.GlobalTag = GlobalTag(process.GlobalTag, 'auto:run2_mc', '') -print("Using GlobalTag: %s" % process.GlobalTag.globaltag.value()) +print "Using GlobalTag: %s" % process.GlobalTag.globaltag.value() # Fake alignment is/should be ideal geometry # ========================================== @@ -26,7 +24,7 @@ verbosity = cms.untracked.int32(1), # Output diectory - outdir = cms.string("./"), + outdir = cms.string("./pc_luts/firmware_MC/"), # Produce "validate.root" to validate the LUTs please_validate = cms.bool(True), diff --git a/L1Trigger/L1TMuonEndCap/test/tools/make_coordlut_data.py b/L1Trigger/L1TMuonEndCap/test/tools/make_coordlut_data.py new file mode 100644 index 0000000000000..e0b16ce44c650 --- /dev/null +++ b/L1Trigger/L1TMuonEndCap/test/tools/make_coordlut_data.py @@ -0,0 +1,35 @@ +import FWCore.ParameterSet.Config as cms + +from Configuration.StandardSequences.Eras import eras + +process = cms.Process("Whatever",eras.Run2_2018) + +process.load('Configuration.StandardSequences.GeometryRecoDB_cff') # load from DB +process.load('Configuration.StandardSequences.MagneticField_AutoFromDBCurrent_cff') +process.load("Configuration.StandardSequences.FrontierConditions_GlobalTag_cff") + +from Configuration.AlCa.GlobalTag import GlobalTag +process.GlobalTag = GlobalTag(process.GlobalTag, '102X_dataRun2_Sep2018Rereco_v1') +print "Using GlobalTag: %s" % process.GlobalTag.globaltag.value() + +process.source = cms.Source("EmptyIOVSource", + timetype = cms.string('runnumber'), + firstValue = cms.uint64(321988), + lastValue = cms.uint64(321988), + interval = cms.uint64(1) +) + +process.maxEvents = cms.untracked.PSet(input = cms.untracked.int32(1)) + +process.analyzer1 = cms.EDAnalyzer("MakeCoordLUT", + # Verbosity level + verbosity = cms.untracked.int32(1), + + # Output diectory + outdir = cms.string("./pc_luts/firmware_data/"), + + # Produce "validate.root" to validate the LUTs + please_validate = cms.bool(True), +) + +process.path1 = cms.Path(process.analyzer1) \ No newline at end of file diff --git a/L1Trigger/L1TMuonEndCap/test/tools/write_ph_lut_v2.py b/L1Trigger/L1TMuonEndCap/test/tools/write_ph_lut_v2.py index c530c804265b1..9f7d31b2e99c1 100644 --- a/L1Trigger/L1TMuonEndCap/test/tools/write_ph_lut_v2.py +++ b/L1Trigger/L1TMuonEndCap/test/tools/write_ph_lut_v2.py @@ -2,11 +2,15 @@ import os -path = 'L1Trigger/L1TMuonEndCap/data/emtf_luts/vl_lut_me11_edges/' - +in_path = 'L1Trigger/L1TMuonEndCap/test/tools/pc_luts/firmware_data/' +# in_path = 'L1Trigger/L1TMuonEndCap/test/tools/pc_luts/firmware_MC/' def main(): - full_path = os.environ['CMSSW_BASE'] + '/src/' + path + '%s' + full_path = os.environ['CMSSW_BASE'] + '/src/' + in_path + '%s' + out_dir = os.environ['CMSSW_BASE'] + '/src/' + in_path.replace('firmware', 'emulator') + + if not os.path.exists(out_dir): + os.makedirs(out_dir) all_files = [] @@ -115,12 +119,12 @@ def dump_array_into_file(arr, fn): assert(len(th_lut_array) == 12*61*128) assert(len(th_corr_lut_array) == 12*7*128) - dump_array_into_file(ph_init_array, "ph_init_neighbor.txt") - dump_array_into_file(ph_disp_array, "ph_disp_neighbor.txt") - dump_array_into_file(th_init_array, "th_init_neighbor.txt") - dump_array_into_file(th_disp_array, "th_disp_neighbor.txt") - dump_array_into_file(th_lut_array, "th_lut_neighbor.txt") - dump_array_into_file(th_corr_lut_array, "th_corr_lut_neighbor.txt") + dump_array_into_file(ph_init_array, out_dir+"ph_init_neighbor.txt") + dump_array_into_file(ph_disp_array, out_dir+"ph_disp_neighbor.txt") + dump_array_into_file(th_init_array, out_dir+"th_init_neighbor.txt") + dump_array_into_file(th_disp_array, out_dir+"th_disp_neighbor.txt") + dump_array_into_file(th_lut_array, out_dir+"th_lut_neighbor.txt") + dump_array_into_file(th_corr_lut_array, out_dir+"th_corr_lut_neighbor.txt") return