text:
/*!
 * \file
 * \brief Image View Tests
 *//*--------------------------------------------------------------------*/

#include "vktPipelineImageViewTests.hpp"
#include "vktPipelineImageSamplingInstance.hpp"
#include "vktPipelineImageUtil.hpp"
#include "vktPipelineVertexUtil.hpp"
#include "vktTestCase.hpp"
#include "vkImageUtil.hpp"
#include "vkPrograms.hpp"
#include "tcuPlatform.hpp"
#include "tcuTextureUtil.hpp"
#include "deStringUtil.hpp"
#include "deMemory.h"

#include <sstream>
#include <vector>

namespace vkt
{
namespace pipeline
{

using namespace vk;
using de::MovePtr;

namespace
{

class ImageViewTest : public vkt::TestCase
{
public:
								ImageViewTest					(tcu::TestContext&				testContext,
																 const char*					name,
																 const char*					description,
																 VkImageViewType				imageViewType,
																 VkFormat						imageFormat,
																 float							samplerLod,
																 const VkComponentMapping&		componentMapping,
																 const VkImageSubresourceRange&	subresourceRange);
	virtual						~ImageViewTest					(void) {}

	ImageSamplingInstanceParams	getImageSamplingInstanceParams	(VkImageViewType				imageViewType,
																 VkFormat						imageFormat,
																 float							samplerLod,
																 const VkComponentMapping&		componentMapping,
																 const VkImageSubresourceRange&	subresourceRange) const;

	virtual void				initPrograms					(SourceCollections&				sourceCollections) const;
	virtual void				checkSupport					(Context&						context) const;
	virtual TestInstance*		createInstance					(Context&						context) const;
	static std::string			getGlslSamplerType				(const tcu::TextureFormat&		format,
																 VkImageViewType				type);
	static tcu::UVec2			getRenderSize					(VkImageViewType				viewType);
	static tcu::IVec3			getImageSize					(VkImageViewType				viewType);
	static int					getArraySize					(VkImageViewType				viewType);
	static int					getNumLevels					(VkImageViewType				viewType);
	static tcu::Vec4			swizzle							(tcu::Vec4						inputData,
																 VkComponentMapping				componentMapping);
private:
	VkImageViewType				m_imageViewType;
	VkFormat					m_imageFormat;
	float						m_samplerLod;
	VkComponentMapping			m_componentMapping;
	VkImageSubresourceRange		m_subresourceRange;
};

ImageViewTest::ImageViewTest (tcu::TestContext&					testContext,
							  const char*						name,
							  const char*						description,
							  VkImageViewType					imageViewType,
							  VkFormat							imageFormat,
							  float								samplerLod,
							  const VkComponentMapping&			componentMapping,
							  const VkImageSubresourceRange&	subresourceRange)

	: vkt::TestCase			(testContext, name, description)
	, m_imageViewType		(imageViewType)
	, m_imageFormat			(imageFormat)
	, m_samplerLod			(samplerLod)
	, m_componentMapping	(componentMapping)
	, m_subresourceRange	(subresourceRange)
{
}

ImageSamplingInstanceParams ImageViewTest::getImageSamplingInstanceParams (VkImageViewType					imageViewType,
																		   VkFormat							imageFormat,
																		   float							samplerLod,
																		   const VkComponentMapping&		componentMapping,
																		   const VkImageSubresourceRange&	subresourceRange) const
{
	const tcu::UVec2				renderSize		= getRenderSize(imageViewType);
	const tcu::IVec3				imageSize		= getImageSize(imageViewType);
	const int						arraySize		= getArraySize(imageViewType);
	const std::vector<Vertex4Tex4>	vertices		= createTestQuadMosaic(imageViewType);

	const VkSamplerCreateInfo		samplerParams	=
	{
		VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,								// VkStructureType			sType;
		DE_NULL,															// const void*				pNext;
		0u,																	// VkSamplerCreateFlags		flags;
		VK_FILTER_NEAREST,													// VkFilter					magFilter;
		VK_FILTER_NEAREST,													// VkFilter					minFilter;
		VK_SAMPLER_MIPMAP_MODE_NEAREST,										// VkSamplerMipmapMode		mipmapMode;
		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,								// VkSamplerAddressMode		addressModeU;
		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,								// VkSamplerAddressMode		addressModeV;
		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,								// VkSamplerAddressMode		addressModeW;
		0.0f,																// float					mipLodBias;
		VK_FALSE,															// VkBool32					anisotropyEnable;
		1.0f,																// float					maxAnisotropy;
		false,																// VkBool32					compareEnable;
		VK_COMPARE_OP_NEVER,												// VkCompareOp				compareOp;
		0.0f,																// float					minLod;
		(float)(subresourceRange.levelCount - 1),							// float					maxLod;
		getFormatBorderColor(BORDER_COLOR_TRANSPARENT_BLACK, imageFormat),	// VkBorderColor			borderColor;
		false																// VkBool32					unnormalizedCoordinates;
	};

	return ImageSamplingInstanceParams(renderSize, imageViewType, imageFormat, imageSize, arraySize, componentMapping, subresourceRange, samplerParams, samplerLod, vertices);
}

void ImageViewTest::checkSupport (Context& context) const
{
	checkSupportImageSamplingInstance(context, getImageSamplingInstanceParams(m_imageViewType, m_imageFormat, m_samplerLod, m_componentMapping, m_subresourceRange));
}

tcu::Vec4 ImageViewTest::swizzle (tcu::Vec4 inputData, VkComponentMapping componentMapping)
{
	// array map with enum VkComponentSwizzle
	const float channelValues[] =
	{
		-1.0f,
		0.0f,
		1.0f,
		inputData.x(),
		inputData.y(),
		inputData.z(),
		inputData.w(),
		-1.0f
	};

	return tcu::Vec4(channelValues[componentMapping.r],
					 channelValues[componentMapping.g],
					 channelValues[componentMapping.b],
					 channelValues[componentMapping.a]);
}

void ImageViewTest::initPrograms (SourceCollections& sourceCollections) const
{
	std::ostringstream				vertexSrc;
	std::ostringstream				fragmentSrc;
	const char*						texCoordSwizzle	= DE_NULL;
	const tcu::TextureFormat		format			= (isCompressedFormat(m_imageFormat)) ? tcu::getUncompressedFormat(mapVkCompressedFormat(m_imageFormat))
																						  : mapVkFormat(m_imageFormat);

	tcu::Vec4						lookupScale;
	tcu::Vec4						lookupBias;

	getLookupScaleBias(m_imageFormat, lookupScale, lookupBias);

	tcu::Vec4						swizzledScale	= swizzle(lookupScale, m_componentMapping);
	tcu::Vec4						swizzledBias	= swizzle(lookupBias, m_componentMapping);

	switch (m_imageViewType)
	{
		case VK_IMAGE_VIEW_TYPE_1D:
			texCoordSwizzle = "x";
			break;
		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
		case VK_IMAGE_VIEW_TYPE_2D:
			texCoordSwizzle = "xy";
			break;
		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
		case VK_IMAGE_VIEW_TYPE_3D:
		case VK_IMAGE_VIEW_TYPE_CUBE:
			texCoordSwizzle = "xyz";
			break;
		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
			texCoordSwizzle = "xyzw";
			break;
		default:
			DE_ASSERT(false);
			break;
	}

	vertexSrc << "#version 440\n"
			  << "layout(location = 0) in vec4 position;\n"
			  << "layout(location = 1) in vec4 texCoords;\n"
			  << "layout(location = 0) out highp vec4 vtxTexCoords;\n"
			  << "out gl_PerVertex {\n"
			  << "	vec4 gl_Position;\n"
			  << "};\n"
			  << "void main (void)\n"
			  << "{\n"
			  << "	gl_Position = position;\n"
			  << "	vtxTexCoords = texCoords;\n"
			  << "}\n";

	fragmentSrc << "#version 440\n"
				<< "layout(set = 0, binding = 0) uniform highp " << getGlslSamplerType(format, m_imageViewType) << " texSampler;\n"
				<< "layout(location = 0) in highp vec4 vtxTexCoords;\n"
				<< "layout(location = 0) out highp vec4 fragColor;\n"
				<< "void main (void)\n"
				<< "{\n"
				<< "	fragColor = ";

	if (m_samplerLod > 0.0f)
		fragmentSrc << "textureLod(texSampler, vtxTexCoords." << texCoordSwizzle << ", " << std::fixed <<  m_samplerLod << ")";
	else
		fragmentSrc << "texture(texSampler, vtxTexCoords." << texCoordSwizzle << ")" << std::fixed;

	fragmentSrc << " * vec4" << std::scientific << swizzledScale << " + vec4" << swizzledBias << ";\n"
				<< "}\n";

	sourceCollections.glslSources.add("tex_vert") << glu::VertexSource(vertexSrc.str());
	sourceCollections.glslSources.add("tex_frag") << glu::FragmentSource(fragmentSrc.str());
}

TestInstance* ImageViewTest::createInstance (Context& context) const
{
	return new ImageSamplingInstance(context, getImageSamplingInstanceParams(m_imageViewType, m_imageFormat, m_samplerLod, m_componentMapping, m_subresourceRange));
}

std::string ImageViewTest::getGlslSamplerType (const tcu::TextureFormat& format, VkImageViewType type)
{
	std::ostringstream samplerType;

	if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
		samplerType << "u";
	else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
		samplerType << "i";

	switch (type)
	{
		case VK_IMAGE_VIEW_TYPE_1D:
			samplerType << "sampler1D";
			break;

		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
			samplerType << "sampler1DArray";
			break;

		case VK_IMAGE_VIEW_TYPE_2D:
			samplerType << "sampler2D";
			break;

		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
			samplerType << "sampler2DArray";
			break;

		case VK_IMAGE_VIEW_TYPE_3D:
			samplerType << "sampler3D";
			break;

		case VK_IMAGE_VIEW_TYPE_CUBE:
			samplerType << "samplerCube";
			break;

		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
			samplerType << "samplerCubeArray";
			break;

		default:
			DE_FATAL("Unknown image view type");
			break;
	}

	return samplerType.str();
}

tcu::UVec2 ImageViewTest::getRenderSize (VkImageViewType viewType)
{
	if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_2D)
		return tcu::UVec2(16u, 16u);
	else
		return tcu::UVec2(16u * 3u, 16u * 2u);
}

tcu::IVec3 ImageViewTest::getImageSize (VkImageViewType viewType)
{
	switch (viewType)
	{
		case VK_IMAGE_VIEW_TYPE_1D:
		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
			return tcu::IVec3(16, 1, 1);

		case VK_IMAGE_VIEW_TYPE_3D:
			return tcu::IVec3(16);

		default:
			break;
	}

	return tcu::IVec3(16, 16, 1);
}

int ImageViewTest::getArraySize (VkImageViewType viewType)
{
	switch (viewType)
	{
		case VK_IMAGE_VIEW_TYPE_3D:
			return 1;

		case VK_IMAGE_VIEW_TYPE_CUBE:
		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
			return 18;

		default:
			break;
	}

	return 6;
}

int ImageViewTest::getNumLevels (VkImageViewType viewType)
{
	const tcu::IVec3 imageSize = getImageSize(viewType);

	return deLog2Floor32(deMax32(imageSize.x(), deMax32(imageSize.y(), imageSize.z()))) + 1;
}

static std::string getFormatCaseName (const VkFormat format)
{
	const std::string fullName = getFormatName(format);

	DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));

	return de::toLower(fullName.substr(10));
}

static de::MovePtr<tcu::TestCaseGroup> createSubresourceRangeTests(tcu::TestContext& testCtx, VkImageViewType viewType, VkFormat imageFormat)
{
	struct TestCaseConfig
	{
		const char*				name;
		float					samplerLod;
		VkImageSubresourceRange	subresourceRange;
	};

	const deUint32				numLevels				= ImageViewTest::getNumLevels(viewType);
	const deUint32				arraySize				= ImageViewTest::getArraySize(viewType);
	const VkImageAspectFlags	imageAspectFlags		= VK_IMAGE_ASPECT_COLOR_BIT;
	const VkComponentMapping	componentMapping		= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };

	de::MovePtr<tcu::TestCaseGroup> rangeTests (new tcu::TestCaseGroup(testCtx, "subresource_range", ""));

#define ADD_SUBRESOURCE_RANGE_TESTS(TEST_CASES)															\
	do {																								\
		for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(TEST_CASES); configNdx++)				\
		{																								\
			std::ostringstream		desc;																\
			const TestCaseConfig	config	= (TEST_CASES)[configNdx];									\
			desc << "Samples level " << config.samplerLod << " with :\n" << config.subresourceRange;	\
			rangeTests->addChild(new ImageViewTest(testCtx, config.name, desc.str().c_str(), viewType,	\
												   imageFormat, config.samplerLod, componentMapping,	\
												   config.subresourceRange));							\
		}																								\
	} while (deGetFalse())

	if (viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY || viewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY)
	{
		const TestCaseConfig mipLevelRangeCases[] =
		{
			//	name					samplerLod	subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
			{ "lod_base_mip_level",		0.0f,		{ imageAspectFlags, 2u, numLevels - 2u, 0u, arraySize } },
			{ "lod_mip_levels",			4.0f,		{ imageAspectFlags, 0u, 3u, 0u, arraySize } },
		};

		const TestCaseConfig arrayRangeCases[] =
		{
			//	name					samplerLod		subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
			{ "base_array_layer",		0.0f,			{ imageAspectFlags, 0u, numLevels, 1u, arraySize - 1u } },
			{ "array_size",				0.0f,			{ imageAspectFlags, 0u, numLevels, 0u, 4u } },
			{ "array_base_and_size",	0.0f,			{ imageAspectFlags, 0u, numLevels, 2u, 3u } },
		};

		const TestCaseConfig mipLevelAndArrayRangeCases[] =
		{
			//	name										samplerLod		subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
			{ "lod_base_mip_level_base_array_layer",		0.0f,			{ imageAspectFlags, 2u, numLevels - 2u, 1u, 5u } },
			{ "lod_mip_levels_base_array_layer",			4.0f,			{ imageAspectFlags, 0u, 3u, 1u, 5u } },

			{ "lod_base_mip_level_array_size",				0.0f,			{ imageAspectFlags, 2u, numLevels - 2u, 0u, 4u } },
			{ "lod_mip_levels_array_size",					4.0f,			{ imageAspectFlags, 0u, 3u, 0u, 4u } },

			{ "lod_base_mip_level_array_base_and_size",		0.0f,			{ imageAspectFlags, 2u, numLevels - 2u, 2u, 3u } },
			{ "lod_mip_levels_array_base_and_size",			4.0f,			{ imageAspectFlags, 0u, 3u, 2u, 3u } },
		};

		const TestCaseConfig mipLevelAndArrayRemainingRangeCases[] =
		{
			//	name																samplerLod	subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
			{ "lod_base_mip_level_remaining_levels",								0.0f,		{ imageAspectFlags,	1u,	VK_REMAINING_MIP_LEVELS,	0u,	arraySize					} },
			{ "base_array_layer_remaining_layers",									0.0f,		{ imageAspectFlags,	0u,	numLevels,					1u,	VK_REMAINING_ARRAY_LAYERS	} },
			{ "lod_base_mip_level_base_array_layer_remaining_levels_and_layers",	0.0f,		{ imageAspectFlags,	2u,	VK_REMAINING_MIP_LEVELS,	2u,	VK_REMAINING_ARRAY_LAYERS	} },
		};

		ADD_SUBRESOURCE_RANGE_TESTS(mipLevelRangeCases);
		ADD_SUBRESOURCE_RANGE_TESTS(arrayRangeCases);
		ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRangeCases);
		ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRemainingRangeCases);
	}
	else if (viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
	{
		const TestCaseConfig mipLevelRangeCases[] =
		{
			//	name					samplerLod	subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
			{ "lod_base_mip_level",		0.0f,		{ imageAspectFlags, 2u, numLevels - 2u, 0u, arraySize } },
			{ "lod_mip_levels",			4.0f,		{ imageAspectFlags, 0u, 3u, 0u, arraySize } },
		};

		const TestCaseConfig arrayRangeCases[] =
		{
			//	name					samplerLod		subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
			{ "base_array_layer",		0.0f,			{ imageAspectFlags, 0u, numLevels, 6u, arraySize - 6u } },
			{ "array_size",				0.0f,			{ imageAspectFlags, 0u, numLevels, 0u, 6u } },
			{ "array_base_and_size",	0.0f,			{ imageAspectFlags, 0u, numLevels, 12u, 6u } },
		};

		const TestCaseConfig mipLevelAndArrayRangeCases[] =
		{
			//	name										samplerLod		subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
			{ "lod_base_mip_level_base_array_layer",		0.0f,			{ imageAspectFlags, 2u, numLevels - 2u, 6u, arraySize - 6u } },
			{ "lod_mip_levels_base_array_layer",			4.0f,			{ imageAspectFlags, 0u, 3u, 6u, arraySize - 6u } },

			{ "lod_base_mip_level_array_size",				0.0f,			{ imageAspectFlags, 2u, numLevels - 2u, 0u, 6u } },
			{ "lod_mip_levels_array_size",					4.0f,			{ imageAspectFlags, 0u, 3u, 0u, 6u } },

			{ "lod_base_mip_level_array_base_and_size",		0.0f,			{ imageAspectFlags, 2u, numLevels - 2u, 12u, 6u } },
			{ "lod_mip_levels_array_base_and_size",			4.0f,			{ imageAspectFlags, 0u, 3u, 12u, 6u } },
		};

		const TestCaseConfig mipLevelAndArrayRemainingRangeCases[] =
		{
			//	name																samplerLod	subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
			{ "lod_base_mip_level_remaining_levels",								0.0f,		{ imageAspectFlags,	1u,	VK_REMAINING_MIP_LEVELS,	0u,		arraySize					} },
			{ "base_array_layer_remaining_layers",									0.0f,		{ imageAspectFlags,	0u,	numLevels,					6u,		VK_REMAINING_ARRAY_LAYERS	} },
			{ "lod_base_mip_level_base_array_layer_remaining_levels_and_layers",	0.0f,		{ imageAspectFlags,	2u,	VK_REMAINING_MIP_LEVELS,	12u,	VK_REMAINING_ARRAY_LAYERS	} },
		};

		ADD_SUBRESOURCE_RANGE_TESTS(mipLevelRangeCases);
		ADD_SUBRESOURCE_RANGE_TESTS(arrayRangeCases);
		ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRangeCases);
		ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRemainingRangeCases);
	}
	else if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_2D)
	{
		const TestCaseConfig mipLevelRangeCases[] =
		{
			//	name					samplerLod	subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
			{ "lod_base_mip_level",		0.0f,		{ imageAspectFlags, 2u, numLevels - 2u, 0u, 1u } },
			{ "lod_mip_levels",			4.0f,		{ imageAspectFlags, 0u, 3u, 0u, 1u } },
		};

		const TestCaseConfig arrayRangeCases[] =
		{
			//	name					samplerLod		subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
			{ "array_layer_second",		0.0f,			{ imageAspectFlags, 0u, numLevels, 1u, 1u } },
			{ "array_layer_last",		0.0f,			{ imageAspectFlags, 0u, numLevels, arraySize - 1u, 1u } },
		};

		const TestCaseConfig mipLevelAndArrayRangeCases[] =
		{
			//	name									samplerLod	subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
			{ "lod_base_mip_level_array_layer_second",	0.0f,		{ imageAspectFlags, 2u, numLevels - 2u, 1u, 1u } },
			{ "lod_mip_levels_array_layer_second",		4.0f,		{ imageAspectFlags, 0u, 3u, arraySize - 1u, 1u } },

			{ "lod_base_mip_level_array_layer_last",	0.0f,		{ imageAspectFlags, 2u, numLevels - 2u, 5u, 1u } },
			{ "lod_mip_levels_array_layer_last",		4.0f,		{ imageAspectFlags, 0u, 3u, arraySize - 1u, 1u } },
		};

		const TestCaseConfig mipLevelAndArrayRemainingRangeCases[] =
		{
			//	name																samplerLod	subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
			{ "lod_base_mip_level_remaining_levels",								0.0f,		{ imageAspectFlags,	1u,	VK_REMAINING_MIP_LEVELS,	0u,				1u							} },
			{ "array_layer_last_remaining_layers",									0.0f,		{ imageAspectFlags,	0u,	numLevels,					arraySize - 1u,	VK_REMAINING_ARRAY_LAYERS	} },
			{ "lod_base_mip_level_array_layer_last_remaining_levels_and_layers",	0.0f,		{ imageAspectFlags,	2u,	VK_REMAINING_MIP_LEVELS,	arraySize - 1u,	VK_REMAINING_ARRAY_LAYERS	} },
		};

		ADD_SUBRESOURCE_RANGE_TESTS(mipLevelRangeCases);
		ADD_SUBRESOURCE_RANGE_TESTS(arrayRangeCases);
		ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRangeCases);
		ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRemainingRangeCases);
	}
	else if (viewType == VK_IMAGE_VIEW_TYPE_CUBE)
	{
		const TestCaseConfig mipLevelRangeCases[] =
		{
			//	name					samplerLod	subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
			{ "lod_base_mip_level",		0.0f,		{ imageAspectFlags, 2u, numLevels - 2u, 0u, 6u } },
			{ "lod_mip_levels",			4.0f,		{ imageAspectFlags, 0u, 3u, 0u, 6u } },
		};

		const TestCaseConfig arrayRangeCases[] =
		{
			//	name					samplerLod		subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
			{ "array_layer_second",		0.0f,			{ imageAspectFlags, 0u, numLevels, 6u, 6u } },
			{ "array_layer_last",		0.0f,			{ imageAspectFlags, 0u, numLevels, arraySize - 6u, 6u } },
		};

		const TestCaseConfig mipLevelAndArrayRangeCases[] =
		{
			//	name									samplerLod	subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
			{ "lod_base_mip_level_array_layer_second",	0.0f,		{ imageAspectFlags, 2u, numLevels - 2u, 6u, 6u } },
			{ "lod_mip_levels_array_layer_second",		4.0f,		{ imageAspectFlags, 0u, 3u, 6u, 6u } },

			{ "lod_base_mip_level_array_layer_last",	0.0f,		{ imageAspectFlags, 2u, numLevels - 2u, arraySize - 6u, 6u } },
			{ "lod_mip_levels_array_layer_last",		4.0f,		{ imageAspectFlags, 0u, 3u, arraySize - 6u, 6u } },
		};

		const TestCaseConfig mipLevelAndArrayRemainingRangeCases[] =
		{
			//	name																samplerLod	subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
			{ "lod_base_mip_level_remaining_levels",								0.0f,		{ imageAspectFlags,	1u,	VK_REMAINING_MIP_LEVELS,	0u,				6u							} },
			{ "array_layer_last_remaining_layers",									0.0f,		{ imageAspectFlags,	0u,	numLevels,					arraySize - 6u,	VK_REMAINING_ARRAY_LAYERS	} },
			{ "lod_base_mip_level_array_layer_last_remaining_levels_and_layers",	0.0f,		{ imageAspectFlags,	2u,	VK_REMAINING_MIP_LEVELS,	arraySize - 6u,	VK_REMAINING_ARRAY_LAYERS	} },
		};

		ADD_SUBRESOURCE_RANGE_TESTS(mipLevelRangeCases);
		ADD_SUBRESOURCE_RANGE_TESTS(arrayRangeCases);
		ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRangeCases);
		ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRemainingRangeCases);
	}
	else if (viewType == VK_IMAGE_VIEW_TYPE_3D)
	{
		const TestCaseConfig mipLevelRangeCases[] =
		{
			//	name					samplerLod	subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
			{ "lod_base_mip_level",		0.0f,		{ imageAspectFlags, 2u, numLevels - 2u, 0u, arraySize } },
			{ "lod_mip_levels",			4.0f,		{ imageAspectFlags, 0u, 3u, 0u, arraySize } },
		};

		const TestCaseConfig mipLevelAndArrayRemainingRangeCases[] =
		{
			//	name																samplerLod	subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
			{ "lod_base_mip_level_remaining_levels",								0.0f,		{ imageAspectFlags,	1u,	VK_REMAINING_MIP_LEVELS,	0u,	arraySize					} },
			{ "single_array_layer_remaining_layers",								0.0f,		{ imageAspectFlags,	0u,	numLevels,					0u,	VK_REMAINING_ARRAY_LAYERS	} },
			{ "lod_base_mip_level_single_array_layer_remaining_levels_and_layers",	0.0f,		{ imageAspectFlags,	2u,	VK_REMAINING_MIP_LEVELS,	0u,	VK_REMAINING_ARRAY_LAYERS	} },
		};

		ADD_SUBRESOURCE_RANGE_TESTS(mipLevelRangeCases);
		ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRemainingRangeCases);
	}

#undef ADD_SUBRESOURCE_RANGE_TESTS

	return rangeTests;
}

static std::vector<VkComponentMapping> getComponentMappingPermutations (const VkComponentMapping& componentMapping)
{
	std::vector<VkComponentMapping> mappings;

	const VkComponentSwizzle channelSwizzles[4] = { componentMapping.r, componentMapping.g, componentMapping.b, componentMapping.a };

	// Rearranges the channels by shifting their positions.
	for (int firstChannelNdx = 0; firstChannelNdx < 4; firstChannelNdx++)
	{
		VkComponentSwizzle currentChannel[4];

		for (int channelNdx = 0; channelNdx < 4; channelNdx++)
			currentChannel[channelNdx] = channelSwizzles[(firstChannelNdx + channelNdx) % 4];

		const VkComponentMapping mappingPermutation  =
		{
			currentChannel[0],
			currentChannel[1],
			currentChannel[2],
			currentChannel[3]
		};

		mappings.push_back(mappingPermutation);
	}

	return mappings;
}

static std::string getComponentSwizzleCaseName (VkComponentSwizzle componentSwizzle)
{
	const std::string fullName = getComponentSwizzleName(componentSwizzle);

	DE_ASSERT(de::beginsWith(fullName, "VK_COMPONENT_SWIZZLE_"));

	return de::toLower(fullName.substr(21));
}

static std::string getComponentMappingCaseName (const VkComponentMapping& componentMapping)
{
	std::ostringstream name;

	name << getComponentSwizzleCaseName(componentMapping.r) << "_"
		 << getComponentSwizzleCaseName(componentMapping.g) << "_"
		 << getComponentSwizzleCaseName(componentMapping.b) << "_"
		 << getComponentSwizzleCaseName(componentMapping.a);

	return name.str();
}

static de::MovePtr<tcu::TestCaseGroup> createComponentSwizzleTests (tcu::TestContext& testCtx, VkImageViewType viewType, VkFormat imageFormat)
{
	deUint32 arraySize = 0;

	switch (viewType)
	{
		case VK_IMAGE_VIEW_TYPE_1D:
		case VK_IMAGE_VIEW_TYPE_2D:
		case VK_IMAGE_VIEW_TYPE_3D:
			arraySize = 1;
			break;

		case VK_IMAGE_VIEW_TYPE_CUBE:
			arraySize = 6;
			break;

		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
			arraySize = ImageViewTest::getArraySize(viewType);
			break;

		default:
			break;
	}

	const VkImageSubresourceRange subresourceRange =
	{
		VK_IMAGE_ASPECT_COLOR_BIT,							// VkImageAspectFlags	aspectMask;
		0u,													// deUint32				baseMipLevel;
		(deUint32)ImageViewTest::getNumLevels(viewType),	// deUint32				mipLevels;
		0u,													// deUint32				baseArrayLayer;
		arraySize,											// deUint32				arraySize;
	};

	const VkComponentMapping				baseMapping			= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
	const std::vector<VkComponentMapping>	componentMappings	= getComponentMappingPermutations(baseMapping);
	de::MovePtr<tcu::TestCaseGroup>			swizzleTests		(new tcu::TestCaseGroup(testCtx, "component_swizzle", ""));

	for (size_t mappingNdx = 0; mappingNdx < componentMappings.size(); mappingNdx++)
	{
		swizzleTests->addChild(new ImageViewTest(testCtx,
												 getComponentMappingCaseName(componentMappings[mappingNdx]).c_str(),
												 "",
												 viewType,
												 imageFormat,
												 0.0f,
												 componentMappings[mappingNdx],
												 subresourceRange));
	}

	return swizzleTests;
}

} // anonymous

tcu::TestCaseGroup* createImageViewTests (tcu::TestContext& testCtx)
{
	const struct
	{
		VkImageViewType		type;
		const char*			name;
	}
	imageViewTypes[] =
	{
		{ VK_IMAGE_VIEW_TYPE_1D,			"1d" },
		{ VK_IMAGE_VIEW_TYPE_1D_ARRAY,		"1d_array" },
		{ VK_IMAGE_VIEW_TYPE_2D,			"2d" },
		{ VK_IMAGE_VIEW_TYPE_2D_ARRAY,		"2d_array" },
		{ VK_IMAGE_VIEW_TYPE_3D,			"3d" },
		{ VK_IMAGE_VIEW_TYPE_CUBE,			"cube" },
		{ VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	"cube_array" }
	};

	const VkFormat formats[] =
	{
		VK_FORMAT_R4G4_UNORM_PACK8,
		VK_FORMAT_R4G4B4A4_UNORM_PACK16,
		VK_FORMAT_R5G6B5_UNORM_PACK16,
		VK_FORMAT_R5G5B5A1_UNORM_PACK16,
		VK_FORMAT_R8_UNORM,
		VK_FORMAT_R8_SNORM,
		VK_FORMAT_R8_USCALED,
		VK_FORMAT_R8_SSCALED,
		VK_FORMAT_R8_UINT,
		VK_FORMAT_R8_SINT,
		VK_FORMAT_R8_SRGB,
		VK_FORMAT_R8G8_UNORM,
		VK_FORMAT_R8G8_SNORM,
		VK_FORMAT_R8G8_USCALED,
		VK_FORMAT_R8G8_SSCALED,
		VK_FORMAT_R8G8_UINT,
		VK_FORMAT_R8G8_SINT,
		VK_FORMAT_R8G8_SRGB,
		VK_FORMAT_R8G8B8_UNORM,
		VK_FORMAT_R8G8B8_SNORM,
		VK_FORMAT_R8G8B8_USCALED,
		VK_FORMAT_R8G8B8_SSCALED,
		VK_FORMAT_R8G8B8_UINT,
		VK_FORMAT_R8G8B8_SINT,
		VK_FORMAT_R8G8B8_SRGB,
		VK_FORMAT_R8G8B8A8_UNORM,
		VK_FORMAT_R8G8B8A8_SNORM,
		VK_FORMAT_R8G8B8A8_USCALED,
		VK_FORMAT_R8G8B8A8_SSCALED,
		VK_FORMAT_R8G8B8A8_UINT,
		VK_FORMAT_R8G8B8A8_SINT,
		VK_FORMAT_R8G8B8A8_SRGB,
		VK_FORMAT_A2R10G10B10_UNORM_PACK32,
		VK_FORMAT_A2R10G10B10_UINT_PACK32,
		VK_FORMAT_A2B10G10R10_USCALED_PACK32,
		VK_FORMAT_R16_UNORM,
		VK_FORMAT_R16_SNORM,
		VK_FORMAT_R16_USCALED,
		VK_FORMAT_R16_SSCALED,
		VK_FORMAT_R16_UINT,
		VK_FORMAT_R16_SINT,
		VK_FORMAT_R16_SFLOAT,
		VK_FORMAT_R16G16_UNORM,
		VK_FORMAT_R16G16_SNORM,
		VK_FORMAT_R16G16_USCALED,
		VK_FORMAT_R16G16_SSCALED,
		VK_FORMAT_R16G16_UINT,
		VK_FORMAT_R16G16_SINT,
		VK_FORMAT_R16G16_SFLOAT,
		VK_FORMAT_R16G16B16_UNORM,
		VK_FORMAT_R16G16B16_SNORM,
		VK_FORMAT_R16G16B16_USCALED,
		VK_FORMAT_R16G16B16_SSCALED,
		VK_FORMAT_R16G16B16_UINT,
		VK_FORMAT_R16G16B16_SINT,
		VK_FORMAT_R16G16B16_SFLOAT,
		VK_FORMAT_R16G16B16A16_UNORM,
		VK_FORMAT_R16G16B16A16_SNORM,
		VK_FORMAT_R16G16B16A16_USCALED,
		VK_FORMAT_R16G16B16A16_SSCALED,
		VK_FORMAT_R16G16B16A16_UINT,
		VK_FORMAT_R16G16B16A16_SINT,
		VK_FORMAT_R16G16B16A16_SFLOAT,
		VK_FORMAT_R32_UINT,
		VK_FORMAT_R32_SINT,
		VK_FORMAT_R32_SFLOAT,
		VK_FORMAT_R32G32_UINT,
		VK_FORMAT_R32G32_SINT,
		VK_FORMAT_R32G32_SFLOAT,
		VK_FORMAT_R32G32B32_UINT,
		VK_FORMAT_R32G32B32_SINT,
		VK_FORMAT_R32G32B32_SFLOAT,
		VK_FORMAT_R32G32B32A32_UINT,
		VK_FORMAT_R32G32B32A32_SINT,
		VK_FORMAT_R32G32B32A32_SFLOAT,
		VK_FORMAT_B10G11R11_UFLOAT_PACK32,
		VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
		VK_FORMAT_B4G4R4A4_UNORM_PACK16,
		VK_FORMAT_B5G5R5A1_UNORM_PACK16,

		// Compressed formats
		VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
		VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,
		VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,
		VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK,
		VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,
		VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,
		VK_FORMAT_EAC_R11_UNORM_BLOCK,
		VK_FORMAT_EAC_R11_SNORM_BLOCK,
		VK_FORMAT_EAC_R11G11_UNORM_BLOCK,
		VK_FORMAT_EAC_R11G11_SNORM_BLOCK,
		VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
		VK_FORMAT_ASTC_4x4_SRGB_BLOCK,
		VK_FORMAT_ASTC_5x4_UNORM_BLOCK,
		VK_FORMAT_ASTC_5x4_SRGB_BLOCK,
		VK_FORMAT_ASTC_5x5_UNORM_BLOCK,
		VK_FORMAT_ASTC_5x5_SRGB_BLOCK,
		VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
		VK_FORMAT_ASTC_6x5_SRGB_BLOCK,
		VK_FORMAT_ASTC_6x6_UNORM_BLOCK,
		VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
		VK_FORMAT_ASTC_8x5_UNORM_BLOCK,
		VK_FORMAT_ASTC_8x5_SRGB_BLOCK,
		VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
		VK_FORMAT_ASTC_8x6_SRGB_BLOCK,
		VK_FORMAT_ASTC_8x8_UNORM_BLOCK,
		VK_FORMAT_ASTC_8x8_SRGB_BLOCK,
		VK_FORMAT_ASTC_10x5_UNORM_BLOCK,
		VK_FORMAT_ASTC_10x5_SRGB_BLOCK,
		VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
		VK_FORMAT_ASTC_10x6_SRGB_BLOCK,
		VK_FORMAT_ASTC_10x8_UNORM_BLOCK,
		VK_FORMAT_ASTC_10x8_SRGB_BLOCK,
		VK_FORMAT_ASTC_10x10_UNORM_BLOCK,
		VK_FORMAT_ASTC_10x10_SRGB_BLOCK,
		VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
		VK_FORMAT_ASTC_12x10_SRGB_BLOCK,
		VK_FORMAT_ASTC_12x12_UNORM_BLOCK,
		VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
	};

	de::MovePtr<tcu::TestCaseGroup> imageTests			(new tcu::TestCaseGroup(testCtx, "image_view", "Image tests"));
	de::MovePtr<tcu::TestCaseGroup> viewTypeTests		(new tcu::TestCaseGroup(testCtx, "view_type", ""));

	for (int viewTypeNdx = 0; viewTypeNdx < DE_LENGTH_OF_ARRAY(imageViewTypes); viewTypeNdx++)
	{
		const VkImageViewType			viewType		= imageViewTypes[viewTypeNdx].type;
		de::MovePtr<tcu::TestCaseGroup>	viewTypeGroup	(new tcu::TestCaseGroup(testCtx, imageViewTypes[viewTypeNdx].name, (std::string("Uses a ") + imageViewTypes[viewTypeNdx].name + " view").c_str()));
		de::MovePtr<tcu::TestCaseGroup>	formatTests		(new tcu::TestCaseGroup(testCtx, "format", "Uses samplable formats"));

		for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
		{
			const VkFormat		format		= formats[formatNdx];

			if (isCompressedFormat(format))
			{
				// Do not use compressed formats with 1D and 1D array textures.
				if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY)
					break;
			}

			de::MovePtr<tcu::TestCaseGroup>	formatGroup	(new tcu::TestCaseGroup(testCtx,
																				getFormatCaseName(format).c_str(),
																				(std::string("Samples a texture of format ") + getFormatName(format)).c_str()));

			de::MovePtr<tcu::TestCaseGroup>	subresourceRangeTests	= createSubresourceRangeTests(testCtx, viewType, format);
			de::MovePtr<tcu::TestCaseGroup>	componentSwizzleTests	= createComponentSwizzleTests(testCtx, viewType, format);

			formatGroup->addChild(componentSwizzleTests.release());
			formatGroup->addChild(subresourceRangeTests.release());
			formatTests->addChild(formatGroup.release());
		}

		viewTypeGroup->addChild(formatTests.release());
		viewTypeTests->addChild(viewTypeGroup.release());
	}

	imageTests->addChild(viewTypeTests.release());

	return imageTests.release();
}

} // pipeline
} // vkt


Graf & Lewent was retained by CUNY to design a new 2,000 square foot Sound Studio for Hostos Community College. The project entailed complete Architectural/Engineering services plus audio visual design, acoustical design, MEP infrastructure, and the selection of all the finishes. The Sound Studio is situated on a floating wood floor with double thick walls which have an STC rating of 72. In addition, the ceiling is composed of special acoustical diffusers while the walls have two type of sound treatment to aid with the acoustics.


BERGISCH GLADBACH, August 14, 2014 – Addition of lentiviral gene delivery capabilities complements strategic partnering portfolio.
BERGISCH GLADBACH, GERMANY, August 14, 2014 — Miltenyi Biotec announced today that it has acquired the lentiviral vector manufacturing business and related assets from US company Lentigen Corporation, a global leader in lentiviral technology for cell and gene therapy applications.
The acquisition further strengthens Miltenyi Biotec's portfolio in cell and gene therapy. Assets obtained in the transaction include a broad range of intellectual property, process technologies, and cGMP-qualified manufacturing facilities. The Lentigen team will join Miltenyi Biotec, and operate through its newly formed, wholly owned US subsidiary Lentigen Technology, Inc. based in Gaithersburg, MD.
Miltenyi Biotec will leverage the combined capabilities by offering customized system and application design in strategic partnerships with clinical investigators and companies to develop and commercialize cell and gene therapies.
Lentiviral technology provides the most efficient method for delivering genetic material into cells to modulate their function, as demonstrated by recent clinical trials in genetic diseases and oncology indications utilizing lentivirus-modified chimeric antigen receptor (CAR) T cells.
Concurrent with the transaction, the sellers, now operating as Opus Bio, Inc., have been granted certain rights to deploy lentiviral technology in some therapeutic indications, for which Lentigen Technology, Inc. shall be the preferred manufacturing supplier.
Miltenyi Biotec is a global provider of products and services that advance biomedical research and cellular therapy. The company's integrated tools support research at every level, from basic research to translational research to clinical application. Their technologies cover techniques of sample preparation, cell isolation, flow sorting, flow cytometry, cell culture, molecular analysis, and preclinical imaging. The company's more than 25 years of expertise spans research areas including immunology, stem cell biology, neuroscience, and cancer, and clinical research areas like hematology, graft engineering, and apheresis. Trusted around the world, the Miltenyi Biotec brand continues to set new standards in the industry. Miltenyi Biotec has more than 1,400 employees in 25 countries.


text:
Broad MSU Presents Exhibition Exploring Changing Role of Women in Chinese Culture
Fire Within: A New Generation of Chinese Women Artists Features Twenty-Seven Emerging Artists Working in Painting, Installation, Sculpture, Video, Animation, Photography, and Performance
Courtesy of the artist and Klein Sun Gallery, New York.
The Eli and Edythe Broad Art Museum at Michigan State University (Broad MSU) presents a group exhibition that investigates a wide range of themes surrounding the changing role of women in China, Fire Within: A New Generation of Chinese Women Artists. On view August 27, 2016–February 12, 2017, the exhibition features twenty-seven emerging artists working across media, including performances by Hu Jiayi and Lin Ran.
The generation of artists born in China during the 1970s and 1980s witnessed significant changes throughout their society as the country opened up to foreign markets and international exchange. The artists featured in Fire Within confront ideological, cultural, and social topics throughout their work—including the changing perceptions of cultural and gender identity, social dynamics and status, and traditional values and belief systems.
"Rooted in experiences within a rapidly modernizing China, the artists in this exhibition offer new perspectives and ways of understanding an array of cultural, social, and political spheres throughout contemporary life," said Dr. Wang Chunchen, Adjunct Curator at the Broad MSU. "The breadth of perspectives represented by some of the most exciting artists working in the country today offers the opportunity for intergenerational and cross-cultural dialogues on subjects both universal and specific to life in Chinese society. We're proud to introduce the work of many of these artists to American audiences for the first time."
The exhibition spans three galleries within the Zaha Hadid-designed museum, anchored by overarching themes within each: "Shifting Identities" explores how a changing China alters constructions of identity; "Body as Site" focuses on the physical body as a literal and figurative site of discussion and debate; and "Confronting Tradition" highlights the ways in which artists draw inspiration from classical texts, teachings, and artistic practices to reinterpret and question evolving power structures and social norms.
GengXue's Mr. Sea (2013-14) uses porcelain figures in an elaborate stop-motion animation video work adapted from a traditional 18th-century Chinese text, Liao Zhai Zhi Yi (Strange Tales from a Chinese Studio). The use of porcelain figures throughout the thirteen-minute work underscores the fragility of the characters themselves and the relationship between long-established Chinese values and rapid modernization.
Yu Feifei's installation I want to. But I shouldn't (2015) considers issues of repression and surveillance throughout society, which emanate from both internal and external forces. A fractured plaster mask is engulfed by an expansive installation of screen-printed tissue paper that obsessively repeat the work's title, reflecting the deeply personal and suffocating nature of these experiences.
In Art should be beautiful, Artist should be beautiful (2015), Pei Li addresses a type of plastic surgery common amongst Chinese woman as a result of societal pressures to conform to increasingly unattainable norms of beauty and femininity. The bust depicts a young woman, with a piece of bone shaved from the figure's face cast in silver and placed just below.
Hu Jiayi is represented with Ice Skate (2014), which comments on the erasure of the natural environment in the wake of modernization through a short video documenting a performance by the artist in her hometown of Xinjiang wherein she attempted to ice skate on tempered glass in a construction site. Hu will also perform Suitcase (2016), which addresses her experience of dislocation in the face of greater mobility brought about by China's development. The U.S. premiere of the performance will be realized across two galleries, creating an installation that will become a permanent part of the exhibition. In both works, the artist presents social observations by way of very personal experiences.
Lin Ran's Island (2014-15) embodies the collective and personal experiences of LGBTQ individuals in Chinese society. A traditional Chinese medical herb cupboard is filled and surrounded by objects of particular meaning to members of this community—photographs, letters, clothing, marriage certificates, drawings, etc.—making visible a population that remains largely invisible. Accompanying the installation, Lin Ran will perform Captivity (2007) on the night of the exhibition's opening, exploring notions of isolation and constraint through the physical entanglement of her body in space.
A comprehensive catalog will accompany Fire Within, with an essay by Dr. Wang and individual interviews with the artists featured in the exhibition.
Fire Within: A New Generation of Chinese Women Artists is co-organized by the Eli and Edythe Broad Art Museum at Michigan State University and the Central Academy of Fine Arts Art Museum in Beijing, China. The exhibition is curated by Dr. Wang Chunchen, Broad MSU Adjunct Curator and Head of the Curatorial Research Department at CAFAM, in collaboration with Steven L. Bridges, Broad MSU Assistant Curator. Support for this exhibition is provided by the Eli and Edythe Broad Endowed Fund; the Ministry of Culture of the People's Republic of China; and the China Arts and Entertainment Group.

redpajama_set_name: RedPajamaCommonCrawl


Most patients are familiar with spider veins and varicose veins, but they are often puzzled about the third type of venous condition: reticular veins. At DHR Health Vein Institute, we specialize in venous diseases and offer solutions that meet your individual vein needs.
Reticular veins are the middle siblings to varicose veins and spider veins. These veins are usually blue or purple, and they are called "feeder veins" because they merge into spider veins and can worsen them. These veins are typically located on the back of the legs near the ankles and behind the knees.
Are They a Serious Health Risk?
This vein disorder is not life-threatening, but it can become uncomfortable and can worsen related vein conditions. If blood pools around the area, you can see the veins beneath the skin. Patients suffering from this vein disorder may experience tenderness or itching and burning, and reticular veins can heighten the risk of patients experiencing the pain and discomfort associated with spider veins.
Sclerotherapy is a medical method for treating reticular and spider veins. The practitioner injects sclerosant into the damaged veins to break them apart. Then, as the sclerosant breaks up the diseased vein, the body redirects the blood flow into nearby veins.
Sclerotherapy is minimally-invasive and does not require much, if any, real downtime. Most patients return to their normal activities right after the procedure. However, you may be given compression socks to wear after your treatment to promote healing.
If you are suffering from leg veins, make an appointment at DHR Health Vein Institute in Edinburg, as we are the vein treatment experts in the area. Contact us today to schedule a consultation so you can begin your journey to smoother and less painful legs.


text:
Get 'It's Christmas Live'
Review: Planetshakers - I Know You Can
News: Planetshakers Releases First Single Of 2023 'Yes and Amen (Live in Manila)'
Video: Planetshakers - Come Alive (Live in Manila)
Planetshakers
Planetshakers Release 'It's Christmas Live'
Internationally recognized praise band Planetshakers globally releases It's Christmas Live Nov. 27 from Venture3Media (V3M). Available to pre-buy / pre-save now at all major digital and streaming outlets, the recording celebrates Jesus and His coming to earth to bring us life, hope and freedom.
Recorded live in front of a packed auditorium at Planetshakers Church before the pandemic lockdowns, the full production recording and companion video was produced, directed and mixed by Joth Hunt at Planetshakers Studios. Combining Planetshakers' unique musical interpretation of classic favorites alongside its original Christmas songs, the new album is led by Hunt and worship leaders Rudy Nikkerud, Chelsi Nikkerud, Natalie Ruiz, Joe Vatucicila, Rachel Vatucicila, Kemara Fuimaono and Steve Sowden. The recording also features a 59-voice choir and multiple drum, guitar, bass and keyboard musicians.
"Christmas is a great time to remember what Jesus has done," says Russell Evans, Planetshakers Founder and Lead Pastor. "Despite what we may see around us or how we may feel, Christmas is a time where we can refocus our attention firmly on Jesus. God becoming man to save humanity!"
"The Christmas season is a wonderful time to celebrate the goodness of God," adds Hunt. "These songs are full of life and joy; great reminders of some of the blessings God has given to believers."
This all new live recording of Planetshakers' first-ever full-length studio Christmas album released last year highlights the David Foster and Carole Bayer Sayer-penned "The Prayer (Italian Lyric Version)" that is beautifully-delivered in a Natalie Ruiz and Joe Vatucicila duet. Other highlights include the lead track "Angels We Have Heard On High," which has additional lyrics by Hunt, the title track and original song "It's Christmas," co-written by worship leader and pastor Sam Evans, the jazz-inspired original offering "All Glory" featuring Hunt on vocals and piano, and the declarative original "Light of the World" spiced with rap vocals.
The new album's companion, 60-minute video special entitled, Christmas Down Under, Recorded Live from Planetshakers Australia, will be broadcast globally by Daystar Television Network, American's largest Christian TV network, beginning at 11:00 am CST / 12:00 Noon EST Dec. 22. Hosted by Planetshakers' Joshua Brown and Daystar's Rachael Lamb Brown, the special will not only feature all the new music from It's Christmas Live, but also a timely message from Pastor Evans.
Along with Daystar's Christmas Down Under presentation, Amazon Prime Video will further offer a special It's Christmas Live feature next month.
"Now more than ever before we need to make a deliberate decision to remember the joy of Christmas," says Joshua Brown. "The joy of knowing that Jesus, through his unconditional love, gave up heaven and came to earth to serve us, by giving His life, so we can take on His eternal life through Salvation."
Along with the live recording, Planetshakers released its Over It All studio album earlier this month. The recording features 10 artfully crafted songs, all inspired by the hurt and the hope they see around them in this season. Sharing Bible-based, faith declarations, the album opens with the "247 365" principle of worship as the title track emphasizes that God is "Over It All" and the closing track, "The Great Outpouring," looks past the present pandemic, declaring that "revival is in the air."
Sarah Kroger Releases New Live Single 'Belovedness' Recorded In London
Initially released on Sarah Kroger's sophomore album, 'Light', during the peak of a global healthcare crisis, 'Belovedness' found a beautiful following for those battling with mental health challenges. From a barn turned studio…
Introducing Stockholm Worship Presented By Hillsong - New Live Album Coming In March, Debut Song Out Today
Capitol CMG is excited to announce its partnership with the worship group Stockholm Worship, presented by Hillsong. The worship group's live debut LP, titled Other Side, will release on March 24, and its first song, "Radical Love…
The Rock Music Releases 'Mercy'
'Mercy', the emotive new worship anthem from Salt Lake City-based collective The Rock Music, is now available. Produced by Sam Hart (Aaron Shust) and co-penned by Hart along with The Rock Music's Steele Croswhite, Thomas…
Yes and Amen (Live in Manila)
Come Alive (Live in Manila)
Greater (Live in Manila)


text:
"The Afghan Insurgent Group That Will Not Negotiate" (The Atlantic)
The Afghan Insurgent Group That Will Not Negotiate
Jeffrey Dressler, The Atlantic
The recent clamoring over Afghan insurgents' decision to engage in "talks" with the Afghan government has obscured some rather important distinctions between who is talking and what the prospects are for those talks. Two of Afghanistan's most prominent insurgent groups, the Quetta Shura Taliban and the Haqqani network are both said to be participating in these "talks." But the two groups are quite distinct, with different objectives, ideological sentiments and partnerships with radical Islamic terrorists. These distinctions make any possible deal with the Haqqanis a particularly dubious proposition.
While it is true that the Taliban and the Haqqani network share the common objective of forcing the withdrawal of U.S. and coalition forces from Afghanistan and favor the return of a hardline Islamic government, that is about where their commonalities end. Perhaps the most important difference is their relationship with al-Qaeda. The Taliban has many ties to the terrorist group, but it is the Haqqanis that shelter al-Qaeda's de facto headquarters in North Waziristan.
The Haqqani network's operations are distinct from those of the Taliban in several key ways. Their command and control, support infrastructure, recruiting and funding mechanisms are all largely separate. They operate out of Pakistan's North Waziristan Agency, just miles away from Afghanistan's southeastern border. Unlike the Taliban, a national umbrella insurgent movement, the Haqqanis influence is mostly limited to the southeast of the country, the same area from which they fought the Soviet Army in the 1980s. Although the network is currently led by the sons of the infamous Mujahideen commander Jallaludin Haqqani, who distinguished himself as a particularly effective anti-Soviet Mujahideen commander known for his high body counts, they remain a potent force. (The elder Haqqani was once described as "goodness personified" by former Texas congressman Charlie Wilson,) The Haqqanis have been responsible for the majority of Kabul's most sophisticated suicide attacks as well as the December 2009 suicide bombing of a CIA base in southeastern Afghanistan, the deadliest attack suffered by the CIA since the 1983 Beirut embassy bombing.
Unlike the Taliban, the Haqqanis are neither interested in nor capable of governing the country as a whole. This disinterest in national governance, combined with the network's close association with al-Qaeda, makes a grand bargain with senior Haqqani leadership an unacceptable proposition. Any deal that met the Haqqanis' demands would likely require recognizing q Haqqani-dominated mini-state within Afghan borders, which could, once again, become a safe harbor for al-Qaeda and many other international terrorists. In other words, it could roll an entire region of Afghanistan right back to Sept. 10, 2001. Clearly, that is something the U.S. simply cannot tolerate.
The Haqqani's close relationship with al-Qaeda dates back to the mid-1980s. In 1986, prior to founding al-Qaeda, Osama bin Laden was tapped by Pakistan's military intelligence agency, the Inter-Services Intelligence (ISI), to build a cave complex in Haqqani-controlled territory in the southeast to train Arab volunteers to fight the Soviets in Afghanistan. Following the U.S. invasion of Afghanistan in October of 2001, it was the Haqqanis' turn to come to the aid of al-Qaeda, helping their fighters elude U.S. forces in the Tora Bora mountains. According to the current head of the Haqqani network, Sirraj Haqqani, his network's cooperation with al-Qaeda is "at its highest limit." Indeed, recent reports emanating out of the Haqqani stronghold in North Waziristan confirms Siraj's claims.
Al-Qaeda shelters, trains, and plans attacks under the protection of the Haqqani network in North Waziristan. Chairmen of the Joint Chiefs, Admiral Mike Mullen recently described the area as "the epicenter of terrorism ... where al-Qaeda lives." In the past four months alone, drone strikes in North Waziristan have killed al-Qaeda's number three operative, Mustafa al-Yazid, and his replacement, Sheikh Fateh al Masri.
The only thing more unlikely than a negotiated settlement with the Haqqanis is the prospect of the group breaking ties with al-Qaeda.
To read the full opinion editorial, please visit The Atlantic.
Afghanistan Project
Regional Command East
Afghan Government
Afghan Taliban (Quetta Shura)
Haqqani Network
Khost Province
Kunar Province
Laskhar-e-Taiba (LeT)
Logar Province
Nuristan Province
Paktika Province
SUPPORT ISWFEEDSUNDERSTANDING THE SURGECONTACT US
1400 16th Street NW, Suite 515 Washington, DC 20036
©2007 – 2022 THE INSTITUTE FOR THE STUDY OF WAR


family tree coloring page pages printable plus my free halloween.
family tree coloring pages of photo printable games disney.
coloring family tree colouring sheets pages printable state page christmas.
preschool family tree coloring pages page for kids find photos of sweet amazing template res printable books teens.
my family coloring pages tree colouring sheets well suited ideas proud printable pa.
coloring pages family tree printable for kids online.
free family tree templates inspirational coloring pages printable s for adults.
family tree coloring page for kids pages printable photos blank forms free the big as template christmas stocking.
family tree coloring page pages printable guy color for girls.
unique spring holiday adult coloring pages designs fun time family lovely colouring free of tree printable.
family tree template to print unique coloring pages printable s for adults.
family tree coloring page my pages printable colouring christmas.
draw background family tree coloring pages printable with kids book.
coloring pages of family tree colouring printable snowman for adults flowers.
family tree coloring pages printable new word pictures for kids.
gallery of coloring pages for kids printable family tree page books adults.
family tree coloring page of a pages printable trees fa pictures animals.
family tree coloring pages printable of life page kids my pictures for.
family tree coloring pages printable page the giving games for girls.
family tree coloring pages printable blank kids sheets of plus members free for teens.
family tree coloring page free printable pages kids spreadsheet excel inspirational template my for.
tree coloring pages page for trees palm printable family disney.
family tree coloring pages printable state page free trunk pattern sheet p disney halloween.
printable tree coloring page best template images on family trees craft pages games.


text:
package streamz.converter

import scala.concurrent.{ ExecutionContext, Future }
import scala.util.{ Failure, Success }

import akka.stream._
import akka.stream.scaladsl.{ Flow => AkkaFlow, Sink => AkkaSink, Source => AkkaSource, _ }
import akka.{ Done, NotUsed }
import cats.effect._
import cats.effect.concurrent.Deferred
import cats.effect.implicits._
import cats.implicits._
import fs2._
import scala.annotation.implicitNotFound

trait Converter {

  /**
   * Converts an Akka Stream [[Graph]] of [[SourceShape]] to an FS2 [[Stream]].
   * If the materialized value needs be obtained, use [[akkaSourceToFs2StreamMat]].
   */
  def akkaSourceToFs2Stream[F[_]: Async: ContextShift, A](source: Graph[SourceShape[A], NotUsed])(implicit materializer: Materializer): Stream[F, A] =
    Stream.force {
      Async[F].delay {
        val subscriber = AkkaSource.fromGraph(source).toMat(AkkaSink.queue[A]())(Keep.right).run()
        subscriberStream[F, A](subscriber)
      }
    }

  /**
   * Converts an Akka Stream [[Graph]] of [[SourceShape]] to an FS2 [[Stream]]. This method returns the FS2 [[Stream]]
   * and the materialized value of the [[Graph]].
   */
  def akkaSourceToFs2StreamMat[F[_]: Async: ContextShift, A, M](source: Graph[SourceShape[A], M])(implicit materializer: Materializer): F[(Stream[F, A], M)] =
    Async[F].delay {
      val (mat, subscriber) = AkkaSource.fromGraph(source).toMat(AkkaSink.queue[A]())(Keep.both).run()
      (subscriberStream[F, A](subscriber), mat)
    }

  /**
   * Converts an Akka Stream [[Graph]] of [[SinkShape]] to an FS2 [[Pipe]].
   * If the materialized value needs be obtained, use [[akkaSinkToFs2PipeMat]].
   */
  def akkaSinkToFs2Pipe[F[_]: Concurrent: ContextShift, A](sink: Graph[SinkShape[A], NotUsed])(implicit materializer: Materializer): Pipe[F, A, Unit] =
    (s: Stream[F, A]) =>
      Stream.force {
        Async[F].delay {
          val publisher = AkkaSource.queue[A](0, OverflowStrategy.backpressure).toMat(sink)(Keep.left).run()
          publisherStream[F, A](publisher, s)
        }
      }

  /**
   * Converts an Akka Stream [[Graph]] of [[SinkShape]] to an FS2 [[Pipe]]. This method returns the FS2 [[Pipe]]
   * and the materialized value of the [[Graph]].
   */
  def akkaSinkToFs2PipeMat[F[_]: Concurrent: ContextShift, A, M](sink: Graph[SinkShape[A], M])(implicit materializer: Materializer): F[(Pipe[F, A, Unit], M)] =
    Concurrent[F].delay {
      val (publisher, mat) = AkkaSource.queue[A](0, OverflowStrategy.backpressure).toMat(sink)(Keep.both).run()
      ((s: Stream[F, A]) => publisherStream[F, A](publisher, s), mat)
    }

  /**
   * Converts an akka sink with a success-status-indicating Future[M]
   * materialized result into an fs2 Pipe which will fail if the Future fails.
   * The stream returned by this will emit the Future's value one time at the end,
   * then terminate.
   */
  def akkaSinkToFs2PipeMat[F[_]: ConcurrentEffect: ContextShift, A, M](akkaSink: Graph[SinkShape[A], Future[M]])(
    implicit
    ec: ExecutionContext,
    m: Materializer): F[Pipe[F, A, Either[Throwable, M]]] =
    for {
      promise <- Deferred[F, Either[Throwable, M]]
      fs2Sink <- akkaSinkToFs2PipeMat[F, A, Future[M]](akkaSink).flatMap {
        case (stream, mat) =>
          // This callback tells the akka materialized future to store its result status into the Promise
          val callback = ConcurrentEffect[F].delay(
            mat.onComplete {
              case Failure(ex) => promise.complete(ex.asLeft).toIO.unsafeRunSync()
              case Success(value) => promise.complete(value.asRight).toIO.unsafeRunSync()
            })
          callback.map(_ => stream)
      }
    } yield {
      in: Stream[F, A] =>
        {
          // Async wait on the promise to be completed
          val materializedResultStream = Stream.eval(promise.get)
          val fs2Stream: Stream[F, Unit] = fs2Sink.apply(in)

          // Run the akka sink for its effects and then run stream containing the effect of getting the Promise results
          fs2Stream.drain ++ materializedResultStream
        }
    }

  /**
   * Converts an Akka Stream [[Graph]] of [[FlowShape]] to an FS2 [[Pipe]].
   * If the materialized value needs be obtained, use [[akkaSinkToFs2PipeMat]].
   */
  def akkaFlowToFs2Pipe[F[_]: Concurrent: ContextShift, A, B](flow: Graph[FlowShape[A, B], NotUsed])(implicit materializer: Materializer): Pipe[F, A, B] =
    (s: Stream[F, A]) =>
      Stream.force {
        Concurrent[F].delay {
          val src = AkkaSource.queue[A](0, OverflowStrategy.backpressure)
          val snk = AkkaSink.queue[B]()
          val (publisher, subscriber) = src.viaMat(flow)(Keep.left).toMat(snk)(Keep.both).run()
          transformerStream[F, A, B](subscriber, publisher, s)
        }
      }

  /**
   * Converts an Akka Stream [[Graph]] of [[FlowShape]] to an FS2 [[Pipe]]. This method returns the FS2 [[Pipe]]
   * and the materialized value of the [[Graph]].
   */
  def akkaFlowToFs2PipeMat[F[_]: Concurrent: ContextShift, A, B, M](flow: Graph[FlowShape[A, B], M])(implicit materializer: Materializer): F[(Pipe[F, A, B], M)] =
    Concurrent[F].delay {
      val src = AkkaSource.queue[A](0, OverflowStrategy.backpressure)
      val snk = AkkaSink.queue[B]()
      val ((publisher, mat), subscriber) = src.viaMat(flow)(Keep.both).toMat(snk)(Keep.both).run()
      ((s: Stream[F, A]) => transformerStream[F, A, B](subscriber, publisher, s), mat)
    }

  /**
   * Converts an FS2 [[Stream]] to an Akka Stream [[Graph]] of [[SourceShape]]. The [[Stream]] is run when the
   * [[Graph]] is materialized.
   */
  def fs2StreamToAkkaSource[F[_]: ConcurrentEffect: ContextShift, A](stream: Stream[F, A]): Graph[SourceShape[A], NotUsed] = {
    val source = AkkaSource.queue[A](0, OverflowStrategy.backpressure)
    // A sink that runs an FS2 publisherStream when consuming the publisher actor (= materialized value) of source
    val sink = AkkaSink.foreach[SourceQueueWithComplete[A]] { p =>
      // Fire and forget Future so it runs in the background
      publisherStream[F, A](p, stream).compile.drain.toIO.unsafeToFuture()
      ()
    }

    AkkaSource.fromGraph(GraphDSL.create(source) { implicit builder => source =>
      import GraphDSL.Implicits._
      builder.materializedValue ~> sink
      SourceShape(source.out)
    }).mapMaterializedValue(_ => NotUsed)
  }

  /**
   * Converts an FS2 [[Pipe]] to an Akka Stream [[Graph]] of [[SinkShape]]. The [[Sink]] is run when the
   * [[Graph]] is materialized.
   */
  def fs2PipeToAkkaSink[F[_]: ContextShift: Effect, A](sink: Pipe[F, A, Unit]): Graph[SinkShape[A], Future[Done]] = {
    val sink1: AkkaSink[A, SinkQueueWithCancel[A]] = AkkaSink.queue[A]()
    // A sink that runs an FS2 subscriberStream when consuming the subscriber actor (= materialized value) of sink1.
    // The future returned from unsafeToFuture() completes when the subscriber stream completes and is made
    // available as materialized value of this sink.
    val sink2: AkkaSink[SinkQueueWithCancel[A], Future[Done]] = AkkaFlow[SinkQueueWithCancel[A]]
      .map(s => subscriberStream[F, A](s).through(sink).compile.drain.toIO.as(Done: Done).unsafeToFuture())
      .toMat(AkkaSink.head)(Keep.right)
      .mapMaterializedValue(ffd => Async.fromFuture(Async.fromFuture(Effect[F].pure(ffd))).toIO.unsafeToFuture())
    // fromFuture dance above is because scala 2.11 lacks Future#flatten. `pure` instead of `delay`
    // because the future value is already strict by the time we get it.

    AkkaSink.fromGraph(GraphDSL.create(sink1, sink2)(Keep.both) { implicit builder => (sink1, sink2) =>
      import GraphDSL.Implicits._
      builder.materializedValue ~> AkkaFlow[(SinkQueueWithCancel[A], _)].map(_._1) ~> sink2
      SinkShape(sink1.in)
    }).mapMaterializedValue(_._2)
  }

  /**
   * Converts an FS2 [[Pipe]] to an Akka Stream [[Graph]] of [[FlowShape]]. The [[Pipe]] is run when the
   * [[Graph]] is materialized.
   */
  def fs2PipeToAkkaFlow[F[_]: ConcurrentEffect: ContextShift, A, B](pipe: Pipe[F, A, B]): Graph[FlowShape[A, B], NotUsed] = {
    val source = AkkaSource.queue[B](0, OverflowStrategy.backpressure)
    val sink1: AkkaSink[A, SinkQueueWithCancel[A]] = AkkaSink.queue[A]()
    // A sink that runs an FS2 transformerStream when consuming the publisher actor (= materialized value) of source
    // and the subscriber actor (= materialized value) of sink1
    val sink2 = AkkaSink.foreach[(SourceQueueWithComplete[B], SinkQueueWithCancel[A])] { ps =>
      // Fire and forget Future so it runs in the background
      ConcurrentEffect[F].toIO(transformerStream(ps._2, ps._1, pipe).compile.drain).unsafeToFuture()
      ()
    }

    AkkaFlow.fromGraph(GraphDSL.create(source, sink1)(Keep.both) { implicit builder => (source, sink1) =>
      import GraphDSL.Implicits._
      builder.materializedValue ~> sink2
      FlowShape(sink1.in, source.out)
    }).mapMaterializedValue(_ => NotUsed)
  }

  private def subscriberStream[F[_]: Async: ContextShift, A](subscriber: SinkQueueWithCancel[A]): Stream[F, A] = {
    val pull = Async.fromFuture(Async[F].delay(subscriber.pull()))
    val cancel = Async[F].delay(subscriber.cancel())
    Stream.repeatEval(pull).unNoneTerminate.onFinalize(cancel)
  }

  private def publisherStream[F[_]: Concurrent: ContextShift, A](publisher: SourceQueueWithComplete[A], stream: Stream[F, A]): Stream[F, Unit] = {
    def publish(a: A): F[Option[Unit]] = Async.fromFuture(Concurrent[F].delay(publisher.offer(a))).flatMap {
      case QueueOfferResult.Enqueued => ().some.pure[F]
      case QueueOfferResult.Failure(cause) => Concurrent[F].raiseError[Option[Unit]](cause)
      case QueueOfferResult.QueueClosed => none[Unit].pure[F]
      case QueueOfferResult.Dropped => Concurrent[F].raiseError[Option[Unit]](new IllegalStateException("This should never happen because we use OverflowStrategy.backpressure"))
    }.recover {
      // This handles a race condition between `interruptWhen` and `publish`.
      // There's no guarantee that, when the akka sink is terminated, we will observe the
      // `interruptWhen` termination before calling publish one last time.
      // Such a call fails with StreamDetachedException
      case _: StreamDetachedException => none[Unit]
    }

    def watchCompletion: F[Unit] = Async.fromFuture(Concurrent[F].delay(publisher.watchCompletion())).void
    def fail(e: Throwable): F[Unit] = Concurrent[F].delay(publisher.fail(e)) >> watchCompletion
    def complete: F[Unit] = Concurrent[F].delay(publisher.complete()) >> watchCompletion

    stream.interruptWhen(watchCompletion.attempt).evalMap(publish).unNoneTerminate
      .onFinalizeCase {
        case ExitCase.Completed | ExitCase.Canceled => complete
        case ExitCase.Error(e) => fail(e)
      }
  }

  private def transformerStream[F[_]: ContextShift: Concurrent, A, B](subscriber: SinkQueueWithCancel[B], publisher: SourceQueueWithComplete[A], stream: Stream[F, A]): Stream[F, B] =
    subscriberStream[F, B](subscriber).concurrently(publisherStream[F, A](publisher, stream))

  private def transformerStream[F[_]: ContextShift: Concurrent, A, B](subscriber: SinkQueueWithCancel[A], publisher: SourceQueueWithComplete[B], pipe: Pipe[F, A, B]): Stream[F, Unit] =
    subscriberStream[F, A](subscriber).through(pipe).through(s => publisherStream(publisher, s))
}

trait ConverterDsl extends Converter {

  implicit class AkkaSourceDsl[A, M](source: Graph[SourceShape[A], M]) {

    /** @see [[Converter#akkaSourceToFs2Stream]] */
    def toStream[F[_]: ContextShift: Async](implicit materializer: Materializer, @implicitNotFound(
      "Cannot convert `Source[A, M]` to `Stream[F, A]` - `M` value would be discarded.\nIf that is intended, first convert the `Source` to `Source[A, NotUsed]`.\nIf `M` should not be discarded, then use `source.toStreamMat[F]` instead.") ev: M <:< NotUsed): Stream[F, A] = {
      val _ = ev // to suppress 'never used' warning. The warning fires on 2.12 but not on 2.13, so I can't use `nowarn`
      akkaSourceToFs2Stream(source.asInstanceOf[Graph[SourceShape[A], NotUsed]])
    }

    /** @see [[Converter#akkaSourceToFs2StreamMat]] */
    def toStreamMat[F[_]: ContextShift: Async](implicit materializer: Materializer): F[(Stream[F, A], M)] =
      akkaSourceToFs2StreamMat(source)

    @deprecated(message = "Use `.toStream[F]` for M=NotUsed; use `.toStreamMat[F]` for other M. This version relies on side effects.", since = "0.11")
    def toStream[F[_]: ContextShift: Async](onMaterialization: M => Unit = _ => ())(implicit materializer: Materializer): Stream[F, A] =
      Stream.force(
        akkaSourceToFs2StreamMat(source).map {
          case (akkaStream, mat) =>
            onMaterialization(mat)
            akkaStream
        })
  }

  implicit class AkkaSinkFutureDsl[A, M](sink: Graph[SinkShape[A], Future[M]]) {

    /** @see [[Converter#akkaSinkToFs2SinkMat]] */
    def toPipeMatWithResult[F[_]: ConcurrentEffect: ContextShift](
      implicit
      ec: ExecutionContext,
      m: Materializer): F[Pipe[F, A, Either[Throwable, M]]] =
      akkaSinkToFs2PipeMat[F, A, M](sink)

  }

  implicit class AkkaSinkDsl[A, M](sink: Graph[SinkShape[A], M]) {

    /** @see [[Converter#akkaSinkToFs2Sink]] */
    def toPipe[F[_]: ContextShift: Concurrent](implicit
      materializer: Materializer,
      @implicitNotFound(
        "Cannot convert `Sink[A, M]` to `Pipe[F, A, Unit]` - `M` value would be discarded.\nIf that is intended, first convert the `Sink` to `Sink[A, NotUsed]`.\nIf `M` should not be discarded, then use `sink.toPipeMat[F]` instead.") ev: M <:< NotUsed): Pipe[F, A, Unit] = {
      val _ = ev // to suppress 'never used' warning. The warning fires on 2.12 but not on 2.13, so I can't use `nowarn`
      akkaSinkToFs2Pipe(sink.asInstanceOf[Graph[SinkShape[A], NotUsed]])
    }

    /** @see [[Converter#akkaSinkToFs2SinkMat]] */
    def toPipeMat[F[_]: ContextShift: Concurrent](implicit materializer: Materializer): F[(Pipe[F, A, Unit], M)] =
      akkaSinkToFs2PipeMat(sink)

    @deprecated(message = "Use `.toSink[F]` for M=NotUsed; use `.toSinkMat[F]` for other M. This version relies on side effects.", since = "0.11")
    def toSink[F[_]: ContextShift: Concurrent](onMaterialization: M => Unit)(implicit materializer: Materializer): Pipe[F, A, Unit] =
      (s: Stream[F, A]) =>
        Stream.force {
          akkaSinkToFs2PipeMat(sink).map {
            case (fs2Sink, mat) =>
              onMaterialization(mat)
              s.through(fs2Sink)
          }
        }

  }

  implicit class AkkaFlowDsl[A, B, M](flow: Graph[FlowShape[A, B], M]) {

    /** @see [[Converter#akkaFlowToFs2Pipe]] */
    def toPipe[F[_]: ContextShift: ConcurrentEffect](
      implicit
      materializer: Materializer,
      @implicitNotFound(
        "Cannot convert `Flow[A, B, M]` to `Pipe[F, A, B]` - `M` value would be discarded.\nIf that is intended, first convert the `Flow` to `Flow[A, B, NotUsed]`.\nIf `M` should not be discarded, then use `flow.toPipeMat[F]` instead.") ev: M <:< NotUsed): Pipe[F, A, B] = {
      val _ = ev // to suppress 'never used' warning. The warning fires on 2.12 but not on 2.13, so I can't use `nowarn`
      akkaFlowToFs2Pipe(flow.asInstanceOf[Graph[FlowShape[A, B], NotUsed]])
    }

    /** @see [[Converter#akkaFlowToFs2PipeMat]] */
    def toPipeMat[F[_]: ContextShift: ConcurrentEffect](implicit materializer: Materializer): F[(Pipe[F, A, B], M)] =
      akkaFlowToFs2PipeMat(flow)

    @deprecated(message = "Use `.toPipe[F]` for M=NotUsed; use `.toPipeMat[F]` for other M. This version relies on side effects.", since = "0.11")
    def toPipe[F[_]: ContextShift: ConcurrentEffect](onMaterialization: M => Unit = _ => ())(implicit materializer: Materializer): Pipe[F, A, B] =
      (s: Stream[F, A]) => Stream.force {
        akkaFlowToFs2PipeMat(flow).map {
          case (fs2Pipe, mat) =>
            onMaterialization(mat)
            s.through(fs2Pipe)
        }
      }
  }

  implicit class FS2StreamNothingDsl[A](stream: Stream[Nothing, A]) {

    /** @see [[Converter#fs2StreamToAkkaSource]] */
    @deprecated("Use `stream.covary[F].toSource` instead", "0.10")
    def toSource(implicit contextShift: ContextShift[IO]): Graph[SourceShape[A], NotUsed] =
      fs2StreamToAkkaSource(stream: Stream[IO, A])
  }

  implicit class FS2StreamPureDsl[A](stream: Stream[Pure, A]) {

    /** @see [[Converter#fs2StreamToAkkaSource]] */
    @deprecated("Use `stream.covary[F].toSource` instead", "0.10")
    def toSource(implicit contextShift: ContextShift[IO]): Graph[SourceShape[A], NotUsed] =
      fs2StreamToAkkaSource(stream: Stream[IO, A])
  }

  implicit class FS2StreamIODsl[F[_]: ContextShift: ConcurrentEffect, A](stream: Stream[F, A]) {

    /** @see [[Converter#fs2StreamToAkkaSource]] */
    def toSource: Graph[SourceShape[A], NotUsed] =
      fs2StreamToAkkaSource(stream)
  }

  implicit class FS2SinkIODsl[F[_]: Effect: ContextShift, A](sink: Pipe[F, A, Unit]) {
    /** @see [[Converter#fs2PipeToAkkaSink]] */
    def toSink: Graph[SinkShape[A], Future[Done]] =
      fs2PipeToAkkaSink(sink)
  }

  implicit class FS2PipeIODsl[F[_]: ContextShift: ConcurrentEffect, A, B](pipe: Pipe[F, A, B]) {

    /** @see [[Converter#fs2PipeToAkkaFlow]] */
    def toFlow: Graph[FlowShape[A, B], NotUsed] =
      fs2PipeToAkkaFlow(pipe)
  }
}

redpajama_set_name: RedPajamaGithub


Planning to start your own online business similar to FundedByMe?
We have custom solutions and ready-to-go platform approach for your FundedByMe clone script requirement. The custom developed solution can include of all the necessary features you need to kick-start a booming online business similar to FundedByMe.
FundedByMe clone script is an online Fintech script. You can offer a crowdfunding platform which connects investors and entrepreneurs by using the Best FundedByMe clone script. It is the fantabulous solution for you to kick-start your own online Fintech business. You can offer two types of crowdfunding to your users across the globe, and they are reward-based crowdfunding & equity-based crowdfunding by using FundedByMe clone script PHP. FundedByMe clone PHP can be used to allow people to invest a very small amount of capital in several companies they choose, and they let various entrepreneurs of small and large companies raise capital from friends, family, communities, business angels, and from crowds by using a simple online process. FundedByMe clone script PHP is customizable, so you can customize it as per your niche requirements.
Why should you use FundedByMe Clone?
Think differently in this way! As nowadays people are supporting the concept of entrepreneurship program across the globe, so in this regard, suppose any person want to start their own small business by using an innovative idea under this entrepreneurship program, but they are missing sufficient capital that will require to start their company. So, due to this reason, they are in search of a platform which helps them to connect with several investors across the world and raise funds for their startup by using crowdfunding technique. Hence, you can use this FundedByMe clone script in order to fulfil their fund-raising requirement for startup. You can also offer equity crowdfunding and peer to business crowd-lending to your users across the globe by using the Best FundedByMe clone script. It is an ideal platform for entrepreneurs looking to create their own workspace in the marketplace for Fintech business. With FundedByMe clone PHP, you can offer various types of investments on a pledge basis, and pledges are not released unless the project meets or exceeds a pre-set funding target globally.
Investment Opportunities Feature: This unique feature will display a list of different types of small and large startup companies for the investments by investors such as consumer products, media & entertainment, fashion, healthcare, real estate, food & beverage, design, technology, education, and many other categories of companies by using FundedByMe clone script.
Start Investing Feature: With this exemplary feature, users will be able to discover a project, invest in equity, and share in the success of various business globally with FundedByMe clone script PHP.
Multiple Currency Management Feature: You will be able to manage different types of currencies based on their country in order to attract the global audience by using FundedByMe clone script PHP.
Raise Capital Feature: This exceptional feature will help businesses of various sizes such as start-up, early-stage, and growth-phase in raising capitals from several different types of investors across the globe by using FundedByMe clone script.
Networking Feature: You will offer this exemplary feature in order to connect intelligent entrepreneurs of various start-up companies to a quickly growing, vibrant group of investors globally by using FundedByMe clone PHP.
Simplified Fund-raising Process Feature: This unique feature will simplify the process of creating a campaign for fund-raising of different types of start-up companies across the globe by using FundedByMe clone script PHP.
Statistics Viewing Feature: You will offer this exceptional feature to your users where they will have access to their campaign's visitor statistics, and track their success by using FundedByMe clone script.
Multiple Language Management Feature: You will be able to manage, view, edit, and add many more languages with its content value in order to reach the global audience with help of FundedByMe clone PHP.
User Management Feature: You will manage different types of registered and unregistered users of the site with the help of FundedByMe clone script.
Attractive Search Dashboard Feature: With the help of this unique feature, users will be able to search various companies for investments or for fund-raising by using this highly extensive and attractive search dashboard of FundedByMe clone PHP.
Website Clone Scripts are pristine clone scripts developed solely by our tech aficionados that allows startups to shine with swift website solutions. Our skills puts you in the driver's seat when it comes to leading the industry with FundedByMe Clone Script.
Our diligent App clone Scripts are designed to boost up your startup idea with a ready-to-go market approach. As mobile devices have taken the world by storm, you can get started with FundedByMe Clone Script application, delivering your mobile audience with our world-class mobile app clone script.
Ready-to-go Platform: Our FundedByMe Clone Script platform already has standard features developed that enables you to kick start your project quickly with quality. The advantage of working with us is the fact that we've already got the base ready for you! The website clone architecture that we use in creating cutting-edge clone scripts which are highly scalable, robust, user-friendly and can easily be customized as per your project requirements.
WHY CHOOSE Clone Daddy for FundedByMe Clone Script?
Please note that the use of the phrase "FundedByMe Clone" is for marketing purpose only as this is how the web development industry refers to building a website similar to FundedByMe or another site. NCrypted Websites certifies that the entire design and code is built by our own team of designers and developers. By no means FundedByMe has any association with NCrypted Websites. No code, design or graphics has been or will be used from the FundedByMe website. NCrypted Websites' custom solution enables you to run a website similar to FundedByMe based on our standard structure and technology blueprint. Learn more on what is website cloning.


text:
Push poll (July 24, 2015)
When Chris Schilling calls the Town of Apple Valley's latest excuse to spend money demonizing Apple Valley Ranchos Water Company a push poll (Daily Press, Town's survey shows support for Ranchos acquisition, July 24, 2015), he's not kidding.
Did the pollsters mention that Ranchos is not for sale? Did they mention what the Town has spent already, what it's going to have to spend going forward, what the hostile takeover price for Ranchos will be, how the Town will pay for it, or how the Town — which can't seem to do anything else right — is going to run what is arguably the most important service we currently enjoy?
Of course not, because the Town has promulgated one false narrative after another to hide its true motives.
So, are we surprised at the results? The Town has spent somewhere in excess of a million dollars so far in its jihad against Ranchos (it's hiding expenditures, and fighting the release of information about how much has been spent and where the money is going), which amounts to roughly $50 per household served by Ranchos. Four years of mendacious attacks have taken their toll, both on Ranchos and on our quality of life. One can only surmise from their actions that eventually the Town intends to change the motto from A better way of life to Rule or ruin.
It's not about water, it's about the money. With its spend now, pay later approach to small-town government, the Town needs money, and this survey demonstrates once again that it's willing to do or say anything to get what it wants.
— Greg Raven is Co-Chair of Apple Valley Citizens for Government Accountability, and is concerned about quality of life issues.
"The Town's use of borrowed money to shore up its General Fund raises alarm bells because it shows the Town cannot pay its current bills out of current revenue."


"Cheap Flight Day," one day each year from August 21 to 23 when flights supposedly go on sale, is a myth.
Unless you want to book a flight with Southwest Airlines.
Because from August 21 until August 24, Southwest is having an end of summer sale with flights starting at $49.
Travel dates for domestic flights are available from September 5 to February 14, and for international flights from September 12 to December 13, and January 9 to March 1.
Travelers who want to get out of town during historically quiet travel times (particularly September and October, and between Thanksgiving and December) will enjoy thin crowds and more availability.
Los Angeles-based travelers, for example, can book $54 one-way flights to Tahoe, or $100 flights to Cabo San Lucas.
From the New York City area, there are $50 flights to Fort Lauderdale, Florida — and from here, there are a number of excellent warm-weather destinations for fall and winter fliers.
There are flights to Belize, the Bahamas, Turks and Caicos, and the Cayman Islands for only $59 one-way. For just $90, there are flights to Cuba and Cancun.
To take advantage of this true cheap flight day(s), be sure to book your ticket by 11:59 p.m. in the time zone of your departure city on August 24.


text:
'Vietnam Mailbag' author, veteran to appear at CHEER
Journalist Nancy E. Lynch, author of the award-winning social history "Vietnam Mailbag, Voices From the War: 1968-1972," and Vietnam veteran Rick Lovekin will join forces for a program at 6 p.m. on July 25 at the CHEER Coastal Leisure Center. Their presentation, designed as a salute to all Vietnam veterans, is sponsored by the CHEER Center, at 30637 Cedar Neck Road in Ocean View.
Lynch, who lives in Bethel, will read selected correspondence from servicemen featured in her book, based on the nearly 1,000 letters and hundreds of pictures her popular column "Nancy's Vietnam Mailbag" received for five years from U.S. troops on the front lines during the undeclared and polarizing war.
In her final column, in December 1972, she promised "her guys" she would someday put all their war letters and pictures in a book to honor them. The 2008 Veterans Day release of her 456-page social history fulfilled her pledge. The book earned a gold medal from Independent Publisher in 2009 for Best Non-Fiction in the Mid-Atlantic.
Lovekin, who had a medical disability and could have avoided service in Vietnam, chose instead to enlist in the Army and spent a year in combat as a door gunner on a Huey helicopter and later as crew chief on a Cobra chopper. He was based in Bien Hoa and Vung Tau with the 147th Helicopter Company.
He wrote frequently to Lynch during his 1969-1970 tour, always signing his letters, "Your Man in Nam." He will share some of his combat experiences, as well as slides of images from Vietnam enhanced with 1960s music. Now retired, Lovekin, formerly of New Castle County, lives in North East, Md.
Lynch and Lovekin will be available for questions after their program and to autograph copies of Vietnam Mailbag at $40. A DVD based on the book will also be on sale for $10.


Providing a stable, thermoregulated environment that enables fast, easy access to the baby, the Lullaby* Warmer helps clinicians meet the requirements of different care areas, from newborns in Labour & Delivery to at-risk infants in the NICU.
Microprocessor technology and intelligent engineering create a consistently warm bed with built-in monitors that notify caregivers of critical temperature events. The warmer is fast and designed to be simple to use, so the focus is on the baby, not the switches.
Fast warm-up and uniform heat delivery: Blue colour indicates mattress is warm over entire surface.


This year marks the 500th anniversary of the Protestant Reformation. Therefore, in honor of Martin Luther's significant role in the Reformation and the Church of Christ, I thought we would consider one of the Christmas carols that he wrote. It is one of Lutheranism's greatest Christmas carols, and it is entitled "From Heaven Above to Earth I Come".
Robert J. Morgan in Then Sings My Soul, book 2, presents the story behind the carol and it is as touching as the words Luther wrote.
Luther was an Augustinian monk, and that means the he had taken a vow of celibacy. Even though the Reformation truths of Scripture Alone, Faith Alone, meant that such vows were not required, Luther intended to maintain a celibate life.
After the Reformation, both monks and nuns were renouncing vows of celibacy and marrying. Luther heard of a nearby cloister in which the nuns wanted to marry but they were in virtual captivity. Luther sought help from a merchant, and he smuggled the nuns out by placing them in empty barrels used to deliver herring to the nunnery.
After freeing the nuns, Luther took it upon himself to find husbands for them, and he was successful except for one young lady, Katharina Von Bora, who remained unmarried for two years. When Luther visited his parents, and said that he might have to marry her himself, his father gave whole-hearted support.
Martin and Katharina were married on June 27, 1525. In the spring of 1526 Martin bragged to his friends: "There's about to be born a child of a monk and a nun!" and on June 7, 1526, little Hans Luther was born to the couple.
Luther was a devoted father and for Christmas when Hans was 5 years old, Martin penned this hymn, calling it "a Christmas child's song concerning the child Jesus" and it was annually sung in Luther's home during the Christmas Eve festivities.
Let Luther's hymn and the words of Paul remind you during this season that our Savior did come from heaven to earth, He did leave all his majesty and power behind Him in heaven and He did become man so that He could be our Savior. He deserves all honor, glory and reverence from us for this sacrifice on our behalf.
Hear this hymn sung by the University of St. Thomas Alumni Choir, Aquinas Chapel, December 18, 2013. The YouTube description states "Written by Martin Luther (1483-1546) and translated by Catherine Winkworth (1827-1878), this carol begins with the angelic proclamation of Christ's birth and ends with a worshipful human response inviting Jesus to abide within the "quiet chamber" of the heart. In this new setting, verses selected from the original text alternate with the refrain "Gloria, the Christ is born."" Music composed and conducted by Josh Bauder.
Father, I thank You for giving us the gift of Jesus Christ who came as a Babe and lived a perfect life so that He could be the atoning sacrifice for me, one who cannot life a perfect moment let alone life! I pray that this Christmas season I would have a new appreciation for Christ's coming to earth from heaven above.


text:
Vytautas Landsbergis, född  i Kaunas, är en litauisk politiker.

Landsbergis var en av de stora ledarna för demokrati- och frigörelserörelsen Sajudis under 1980-talet. Han var ordförande i Litauens högsta råd 1990-1992 och därmed landets första statschef efter självständigheten från Sovjetunionen. 1993 grundade han Fosterlandsförbundet – Litauiska kristdemokrater som han ledde till 2003. Han var ledamot av Seimas 1992-2004, dess talman 1996-2000 och var 2004-2014 ledamot  av Europaparlamentet. Han var presidentkandidat i valet 1997 men kom på tredje plats.

Landsbergis är sedan 1978 professor i musikvetenskap.

Källor
 Landsbergis på Europaparlamentets webbplats

Noter

Litauiska politiker under 2000-talet
Ledamöter av Europaparlamentet från Litauen
Ledamöter av Europaparlamentet 2004–2009
Mottagare av Hederslegionen
Mottagare av Rumänska kronorden
Storkorset av Rumänska kronorden
Födda 1932
Levande personer
Män

redpajama_set_name: RedPajamaWikipedia


text:
by Luke Auburn
Professor helms program for NASA's newest space telescope
Share on Facebook Share on Twitter Share on LinkedIn Share on Reddit Share via Email
Scott Hamilton/background image courtesy of NASA
Associate Professor Jeyhan Kartaltepe is the principal investigator of COSMOS-Web, the largest General Observer program selected for James Webb Space Telescope's first year.
When the James Webb Space Telescope (JWST)—the long-awaited successor to the Hubble Space Telescope—becomes operational this year, Jeyhan Kartaltepe will co-lead a team of nearly 50 researchers to map the earliest structures of the universe.
The associate professor in RIT's School of Physics and Astronomy is principal investigator of COSMOS-Web, the largest General Observer program selected for JWST's first year. Over the course of 218 observing hours, COSMOS-Web will conduct an ambitious survey of half a million galaxies with multi-band, high-resolution near infrared imaging and an unprecedented 32,000 galaxies in mid infrared.
Kartaltepe said the COSMOS-Web survey will map 0.6 square degrees of the sky—about the area of three full moons.
She said she was shocked when she found out that her program was chosen for JWST's first cycle of observations. It is one of just 286 General Scientific Observer programs selected out of more than 1,000 proposals for the telescope's first year of science.
Her program will provide the worldwide astronomical community with one of the first extensive opportunities to investigate scientific targets with JWST.
Kartaltepe said she is proud to help lead such a major effort and believes the program will benefit her field in still unimaginable ways.
"The sheer scope of our program is so exciting," said Kartaltepe. "The first year of JWST observations will result in a lot of new discoveries that people will want to explore more in-depth in future cycles. I think the public legacy of COSMOS-Web will be that it is the field where the community conducts this type of follow-up research."
Her leadership role in this program is the result of years of hard work with the Cosmic Evolution Survey (COSMOS), a worldwide collaboration of more than 200 scientists that uses the world's major telescopes to study how galaxies are influenced by both their fundamental physical properties and the environment that surrounds them.
Kartaltepe has been involved in COSMOS since she was a graduate student at the University of Hawai'i at Manoa and became one of COSMOS's three leaders in 2019, co-chairing the scientific steering committee.
Kartaltepe has been a fixture of RIT's astronomical community since she joined the university in 2015 and was promoted to associate professor last fall.
She is director of RIT's Laboratory for Multiwavelength Astrophysics and is a leading member of other large collaborative multiwavelength surveys including CANDELS (The Cosmic Assembly Near-Infrared Deep Extragalactic Legacy Survey) and CEERS (The Cosmic Evolution Early Release Science Survey). In addition, she serves as chair of RIT's Women in Science program.
RIT scientists reach a milestone in the search for continuous gravitational waves
Scientists on the hunt for a previously undetected type of gravitational waves believe they are getting close and have refined techniques to use in upcoming observational runs. Researchers from the LIGO-Virgo-KAGRA Collaboration outlined the most sensitive search to date for continuous gravitational waves from a promising source in a paper recently published in the Astrophysical Journal Letters.
Why universities need to build a culture around data and privacy
The Ed Scoop podcast Cutting Edge talks to Ben Woelk, governance, awareness, and training manager, about cybersecurity and data privacy.
RIT appoints inaugural Vignelli Center Designer in Residence
The Vignelli Center for Design Studies has appointed RZLBD (Reza Aliabadi) as the inaugural Vignelli Center Designer in Residence. This position was created to assist with an upcoming campus project to design and build a series of outdoor interactive exhibits tentatively titled the RIT Museumscape.
Metaproject 13 heads to New York City Design Week 2023
Students who took part in Metaproject 13 will have their designs showcased as part of the 2023 New York City Design Week courtesy of their client, Lazzoni. In the fall, students spent the semester working to design seating solutions for the alumnus-owned international furniture company. All of the designs presented will be prototyped by Lazzoni, a first in Metaproject's history.


text:
Home People on the Move Prado Group Appoints Bridgett McCormick, Acquisitions Manager, Pacific Northwest
Prado Group Appoints Bridgett McCormick, Acquisitions Manager, Pacific Northwest
As Acquisitions Manager for the Pacific Northwest, Ms. McCormick will be responsible for the organization's expansion into Seattle and the Pacific Northwest markets
SAN FRANCISCO–Prado Group, a privately held real estate investment and development management company, has hired Bridgett McCormick as its new Acquisitions Manager for the Pacific Northwest. Ms. McCormick previously worked at Prado Group in its San Francisco office and will be based in Seattle for her new role having recently completed her MBA at USC.
"Since our founding in 2003, Prado Group has acquired and developed more than 80 properties in excess of $1.3B with approximately $2B in our existing asset and development pipeline," stated Zach Felson, Head of Acquisitions at the Prado Group. "We are excited about the opportunity to expand our presence in Seattle and the Pacific Northwest and look forward to building a quality portfolio and enduring local relationships. Initially, we will be focused on the Seattle market as we expand into the region. We are thrilled to have Bridgett re-join our team and expand our presence in one of the country's top urban knowledge markets."
Prado Group was formed with a mission to positively transforming the built environment and the communities in which it operates. The company is inspired by the power of blending creativity, quality design, the natural environment, and the energy of the public realm. In every project, the company seeks to create quality environments that will serve and inspire future generations. Prado Group seeks to create value through development, repositioning and property enhancement and has a 17-year track record of creating award-winning projects in the San Francisco Bay Area.
About Prado Group
Prado Group is a privately held real estate development and investment management company with a primary focus on residential, retail and mixed-use properties. We seek in-fill, supply-constrained markets with high barriers-to-entry. Our goal is to enhance the communities we work in by creating high-quality, sustainable environments for people to live, work, shop and relax.
Prado Group


text:
Home » From the Editor: ASF impact goes beyond pork industry
From the Editor: ASF impact goes beyond pork industry
As it continues to spread across the globe, African swine fever's far-reaching impact on the pork, feed and grain markets is still being assessed by experts.
"ASF is something that's very hard for the market to understand," said Stefan Vogel, head of commodities for Rabobank U.K. "We have never received so many calls and questions from clients on one single topic as we have this one."
What is known at this point is that in China, which is the world's largest pork producer and consumer, and where the outbreak began, Rabobank estimates the pig herd may shrink by 50% by the end of 2019. Analysts say it may take more than five years for China to recover to levels prior to the outbreak as challenges, including a lack of solutions to prevent or treat the disease and a lack of capital, will restrict restocking.
But the outbreak stretches far beyond the borders of China, with parts of Asia, Africa and Eastern Europe among the hardest hit. The virus has been found in at least 36 countries on three continents since June 2018, according to the International Organization for Animal Health, which noted that it had been controlled or eradicated in half of those countries, most of them in Africa. As of early September, 18 countries had reported cases of ASF.
What these countries have discovered is that the virus — which is usually fatal to pigs but does not infect humans — is difficult to kill. With no available vaccine, prevention remains the best defense, and many countries around the world are working to bolster their defenses against the virus.
The U.S. Department of Agriculture has even added more dogs to its "Beagle Brigade," which sniffs out pork hidden in travelers' luggage at international airports and border crossings. As of early September, there had been no reports of the virus reaching the U.S., which has the third largest hog population behind China and Europe. If ASF were to spread to the U.S., it would mean the world's top three pork producing markets, which account for 86% of the planet's pork output, would be impacted.
Besides the obvious impact on the pork sector, the implications for the global grain and feed markets also could be significant. Denver, Colorado-based CoBank conservatively estimates that if China's hog herd declines by one-third, soybean meal consumption will drop by roughly 9 million tonnes and corn consumption will decline by 28 million tonnes. A silver lining is that Chinese consumers already are switching to poultry, fish and beef from pork, so feed demand in those sectors could increase to soften the blow. But chicken and fish convert feed more efficiently than hogs and cattle, so there is risk that global feed demand declines if the shift in consumption is a long-term trend.
While scientists work to develop a vaccine, the global pork industry must increase education efforts so that pig farmers recognize ASF symptoms and know how to prevent the virus from spreading. Countries also should follow the lead of China, Australia and Japan, which have proposed hefty fines and even prison sentences for travelers transporting diseased pork. Perhaps that sounds extreme, but it really isn't given what's at stake. Eradicating this disease will require a global team effort involving the public and private sectors.
Business Trends Market Segments Feed Milling grain handling Safety African Swine Fever (ASF) food safety
From the editor: Pandemic's potentially permanent impact
From the editor: Organic grain industry must weed out bad actors
From the Editor: Grain industry a casualty of trade wars
From the editor: Supply chain woes weigh on grain industry
From the editor: The massive price tag of Putin's war